セッション

AgentSession は、エージェントの実行全体で使用される会話状態コンテナーです。

AgentSessionに含まれる内容

フィールド Purpose
StateBag このセッションの任意の状態コンテナー

C# AgentSession は抽象基本クラスです。 具体的な実装 ( CreateSessionAsync() を使用して作成) では、サービス管理の履歴が使用されている場合に、リモート チャット履歴ストレージの ID など、追加の状態が追加される場合があります。

フィールド Purpose
session_id このセッションのローカル一意ID
service_session_id サービス管理履歴が使用されている場合のリモート サービス セッション識別子 (会話や応答 ID など)
state コンテキスト/履歴プロバイダーと共有される変更可能なディクショナリ
フィールド Purpose
agent.Session 会話に関連付けられたキー値状態コンテナー

セッションでは、型指定されたキー値ストレージが提供されます。

type UserPrefs struct {
    Theme    string `json:"theme"`
    Language string `json:"language"`
}

session.Set("user_prefs", UserPrefs{Theme: "dark", Language: "en"})

var prefs UserPrefs
session.Get("user_prefs", &prefs)

session.Delete("user_prefs")

サービス セッション ID のスコープ設定

サービス管理の履歴を使用する場合、セッションにはサービスによって発行されたセッション識別子を含めることができます。 たとえば、OpenAI 応答ではresp_*としてprevious_response_id応答 ID を使用し、OpenAI Conversations API では会話としてconv_*会話 ID を使用できます。

OpenAI は、これらの ID をバッキング API キーまたはプロジェクトに既定でスコープします。 これは通常、そのキーまたはプロジェクトが既にアプリケーションの境界 (シングル ユーザー アプリやテナントごとに別のキー/プロジェクトなど) と一致している場合に十分です。 危険なホストパターンは、複数のエンド ユーザーに対して 1 つのバッキング キーまたはプロジェクトを使用し、未加工のサービス側 ID をクライアントにエコーし、所有権を確認せずにそれらの ID を受け入れることです。 1 つのバッキング キーまたはプロジェクトを再利用するホスト型アプリまたはマルチユーザー アプリでは、 service_session_idprevious_response_id、または conversation/conversation_id をエンドユーザー承認境界として扱わないでください。 サービス側 ID を信頼されたアプリケーション ストレージに格納し、クライアントから参照できるセッション ID をそれらのサービス側 ID にマップし、会話を再開する前に認証されたユーザーまたはテナントを確認します。

組み込みの使用パターン

AgentSession session = await agent.CreateSessionAsync();

var first = await agent.RunAsync("My name is Alice.", session);
var second = await agent.RunAsync("What is my name?", session);
session = agent.create_session()

first = await agent.run("My name is Alice.", session=session)
second = await agent.run("What is my name?", session=session)
session, err := a.CreateSession(ctx)
if err != nil {
    panic(err)
}

resp, _ := a.RunText(ctx, "Hello!", agent.WithSession(session)).Collect()
resp, _ = a.RunText(ctx, "Follow-up question.", agent.WithSession(session)).Collect()

Harness Agent でセッションを使用する

Harness Agent は、上記と同じ AgentSession ライフサイクルを使用します。 1 つのセッションを順番に再利用して、チャット履歴とセッションベースのハーネス機能 (todos、オペレーティング モード、ファイル メモリ、ツールの承認、バックグラウンド タスクの状態など) が接続されたままになるようにします。 その状態がプロセスの再起動後も存続する必要がある場合に、セッションをシリアル化します。

HarnessAgent では、既定値が InMemoryChatHistoryProvider に設定されます。 履歴で別のストアを使用する必要がある場合は、 HarnessAgentOptions.ChatHistoryProvider で置き換えます。 AsHarnessAgent(options) は、 new HarnessAgent(chatClient, options)を構築するための短縮形です。

HarnessAgent agent = chatClient.AsHarnessAgent();
AgentSession session = await agent.CreateSessionAsync();

await agent.RunAsync("Plan the migration.", session);
await agent.RunAsync("Continue with the next step.", session);

var serialized = await agent.SerializeSessionAsync(session);
AgentSession resumed = await agent.DeserializeSessionAsync(serialized);

ハーネスは、外部エージェントの実行後だけでなく、ツール呼び出しループ内の各モデル呼び出しの後もローカル チャット履歴を保持します。 同じセッションを引き続き渡して、そのループ内履歴と既定のコンテキスト プロバイダーの状態を保持します。

create_harness_agentの既定値は InMemoryHistoryProvider()history_providerされます。 履歴で別のストアを使用する必要がある場合は、history_provider=を通じてカスタム HistoryProviderを渡します。

agent = create_harness_agent(client)
session = agent.create_session()

await agent.run("Plan the migration.", session=session)
await agent.run("Continue with the next step.", session=session)

serialized = session.to_dict()
resumed = AgentSession.from_dict(serialized)

ハーネスにはサービスごとの呼び出し履歴の永続化が必要であるため、構成された履歴プロバイダーは、各モデル呼び出しをツール ループ内に保存します。 セッションは、既定のツール承認ミドルウェアでも必要です。を再利用して復元し、承認とコンテキスト プロバイダーの状態を維持します。

Harness エージェントは現在、Go SDK では使用できません。 上記の通常のセッション パターンを使用します。

既存のサービス会話 ID からのセッションの作成

既存の会話 ID から新しいセッションを作成する方法は、エージェントの種類によって異なります。 いくつかの例を次に示します。

ChatClientAgentを使用する場合

AgentSession session = await chatClientAgent.CreateSessionAsync(conversationId);

A2AAgent を使用する場合は、

AgentSession session = await a2aAgent.CreateSessionAsync(contextId, taskId);

これは、バッキング サービスに既に会話状態がある場合に使用します。

session = agent.get_session(service_session_id="<service-conversation-id>")
response = await agent.run("Continue this conversation.", session=session)

ホストされているアプリで、現在のユーザーまたはテナントを確認した後、アプリケーション所有のストレージから <service-conversation-id> を解決します。 最初に呼び出し元が会話を所有していることを確認しない限り、クライアントから生のサービス側 ID を受け入れないようにします。

シリアル化と復元

var serialized = agent.SerializeSession(session);
AgentSession resumed = await agent.DeserializeSessionAsync(serialized);
serialized = session.to_dict()
resumed = AgentSession.from_dict(serialized)
data, err := json.Marshal(session)
if err != nil {
    panic(err)
}

// Save to disk, database, etc.
if err := os.WriteFile("session.json", data, 0o644); err != nil {
    panic(err)
}

// Later, restore the session.
loaded, err := os.ReadFile("session.json")
if err != nil {
    panic(err)
}

var resumedSession agent.Session
if err := json.Unmarshal(loaded, &resumedSession); err != nil {
    panic(err)
}

resp, _ := a.RunText(ctx, "Continue from where we left off.", agent.WithSession(&resumedSession)).Collect()

Tip

完全な例については、 永続化された会話のサンプル を参照してください。

Important

セッションはエージェント/サービス固有です。 別のエージェント構成またはプロバイダーでセッションを再利用すると、コンテキストが無効になることがあります。 シリアル化されたセッションにサービス側セッション ID が含まれている場合は、その ID を所有するアプリケーション ユーザーまたはテナントに対してのみ復元します。

次のステップ