会期

AgentSession 是跨代理运行使用的会话状态容器。

AgentSession的内容包含

领域 Purpose
StateBag 此会话的任意状态容器

C# AgentSession 是一个抽象基类。 具体实现(通过 CreateSessionAsync() 创建)在使用服务管理的历史记录时,可能会添加其他状态,例如用于远程聊天历史记录存储的 ID。

领域 Purpose
session_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_* 响应 ID 作为 previous_response_id,OpenAI 对话 API 可能使用 conv_* 会话 ID 作为对话。

默认情况下,OpenAI 将这些 ID 限定为支持 API 密钥或项目。 当该密钥或项目已与应用程序边界匹配(例如单用户应用或每个租户单独的密钥/项目)时,这通常就足够了。 存在风险的托管模式是指:多个最终用户共用同一个后端密钥或项目,将原始的服务端 ID 回显给客户端,并在不检查所有权的情况下接收客户端回传的这些 ID。 在重复使用一个支持密钥或项目的托管或多用户应用中,请勿将service_session_idprevious_response_idconversation/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 代理配合使用

Harness 代理使用上述相同 AgentSession 生命周期。 跨轮次重复使用一个会话,以便聊天历史记录和会话支持的利用功能(如待办事项、操作模式、文件内存、工具审批和后台任务状态)保持连接。 当该状态必须在进程重启后序列化会话。

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 defaults history_provider to InMemoryHistoryProvider(). 在历史记录必须使用其他存储时传递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 的应用程序用户或租户还原它。

后续步骤