会话机制与会话隔离

更新时间:
复制 MD 格式

AgentCore 通过会话标识把属于同一次对话的请求组织在一起,并按实例容量配置管理这些会话。会话标识经 HTTP Header 传递,与 AG-UI、Chat Completions 的协议字段处在请求的不同位置。会话标识只表示请求归属,不表示平台已保存对话历史;历史与业务状态由应用或托管 Harness 负责。

以下内容以高代码 Agent 为主,托管 Harness 与其他 Agent 形态的差异在对应章节就地说明。创建高代码 Agent 时,可先按高代码 Agent 部署与使用指南完成部署,再结合本文涉及业务调用中的会话标识与历史管理。

会话与会话标识

会话(Session)用于将属于同一次对话或交互过程的请求组织在一起。终端用户先提交“分析这份报告”,随后继续问“把结论整理为三点”,两次请求可以使用同一个会话标识;终端用户另起一次对话时,应使用新的会话标识。

本文区分两个角色:使用 Agent 对话的终端用户,以及接入 Agent 的调用方(业务应用)。会话标识由调用方生成和维护。会话机制涉及三个概念:

概念

解决的问题

说明与示例

会话标识

这次请求属于哪一个会话

如 demo-session-01,同一对话复用,新对话更换。

运行实例

由哪个运行环境执行请求

一个实例可按容量配置承载多个会话。

对话历史与业务状态

本次执行需要哪些上下文,以及执行结果存在哪里

消息列表、框架检查点、用户文件、工具执行结果。

历史与状态的归属

会话标识用于识别会话,不是对话历史本身。把两个请求标成同一个会话,不等于平台已经替应用保存了上一轮消息。历史与业务状态是否保存、能否恢复,取决于应用或托管 Harness 的实现:

  • 在控制台声明协议,不会自动实现接口,也不会自动保存历史。

  • 仅使用 AgentCoreServer,不会自动获得完整历史持久化。

  • 调试面板发送了会话标识,不能作为服务端已保存或恢复历史的依据。

  • 两个协议的请求使用相同会话标识,不代表应用会在协议之间自动转换或共享历史;需要跨协议继续对话时,由应用保证一致的历史与状态管理。

会话标识的传递方式

创建高代码 Agent 时配置的是会话标识方式。当前基于 HTTP Header 识别会话,承载会话标识的 Header 名称在创建 Agent 时设置。例如应用采用 X-AgentCore-Session-ID 作为会话 Header:

X-AgentCore-Session-ID: demo-session-01

请求中有两个不同的值:

  • X-AgentCore-Session-ID 是 Header 名称,为 Agent 配置与调用方之间约定的字段名。创建后,调用方按该名称发送请求;名称可改为业务既有字段,示例见“调用示例”中的场景四。

  • demo-session-01 是会话标识。同一对话复用此值,新对话使用新值。它不是 Agent 名称、实例 ID,也不是 API Key。

    会话标识由调用方生成,可以是业务生成的不可预测标识,无需把终端用户手机号等个人信息作为会话标识。

请求组成与字段口径

一次请求的组成

会话 Header 位于 HTTP 请求头,AG-UI 和 Chat Completions 则规定请求体及响应的格式。它们处在请求的不同位置,不是三个互斥的选项。

一次 HTTP 请求
├─ URL:选择此次调用的协议接口
├─ Headers
│  ├─ 鉴权 Header:证明调用方有权访问 Endpoint
│  └─ 会话 Header:标识请求属于哪个会话
└─ Body:使用本次所选协议的格式
   ├─ AG-UI:threadId、runId、messages 等
   └─ Chat Completions:model、messages、stream 等

一次请求选择一种协议。协议能力由代码实际实现并在控制台声明,可以实现一种或多种;Agent 实现了两种协议并完成声明时,可以分别通过两个接口调用,但不要把两种协议的请求体混装在一次请求中。接入前以目标 Endpoint 的调用示例为准。两种协议的会话承载位置不同:

协议

会话承载位置

请求体中的会话相关字段

AG-UI

会话 Header

threadId(与会话 Header 同值)、runId(标识本次运行)

Chat Completions

会话 Header;控制台调试请求另在 URL 查询参数携带 sessionId

标准请求体没有 threadId、runId 这两个会话字段

AgentCore 控制台的 Chat Completions 调试请求所携带的 sessionId 查询参数属于平台接入用法,不是标准 Chat Completions 的 Body 字段。业务接入时存在多个承载位置,则使用同一个会话值。

调试面板构造方式与业务调用参考

下表的“调试面板实际构造方式”描述调试面板的请求组装行为,“业务调用参考”提供相应的填写建议。业务接口的必填字段、可省略字段及服务端处理规则,以目标 Endpoint 和所用应用的接口约定为准。

字段与位置

调试面板实际构造方式

业务调用参考

Endpoint 地址及鉴权信息(HTTP 请求 / 两种协议)

读取端点地址;使用 API Key 鉴权时,获取该端点的 API Key 和 Header 名后写入请求。

从目标 Endpoint 的调用说明获取地址和鉴权方式;使用 API Key 时配置相应 Header 和密钥。

会话 Header 名称(HTTP Header / 两种协议)

根据 Agent 会话配置解析请求头名称。

使用 Agent 配置对应的 Header 名称。

会话标识(HTTP Header / 两种协议)

调试面板创建新会话时生成并保存;后续请求使用当前会话标识。

由调用方生成并保存:新对话使用新值,同一对话复用。

threadId(Body / AG-UI)

填入当前会话标识,与会话 Header 的值相同。

参照调试面板,使用与会话 Header 相同的值。

runId(Body / AG-UI)

每次构造运行请求时生成新值。

每次新运行使用新值。

消息 id(Body 的 messages / AG-UI)

调试面板按当前会话标识和消息序号组装。

为请求中的消息填写 ID;格式及历史消息的 ID 复用要求按所接入服务的约定处理。

消息列表 messages(Body / 两种协议)

将当前调试对话的历史消息与本轮终端用户输入一起放入请求。

按应用接口约定提供消息列表;由调用方维护历史时,将相关历史一并传入。

sessionId(URL 查询参数 / Chat Completions 调试请求)

追加当前会话标识,与会话 Header 的值相同。

目标 Endpoint 的调用示例包含此参数时,使用同一个会话值。

AG-UI 和 Chat Completions 的调试请求都包含 messages;服务端是否保存或恢复历史,见“历史与状态的归属”。

调用示例

场景一:控制台调试 AG-UI 会话

在调试面板中创建会话并输入问题后,面板生成会话标识,并构造类似下面的请求。示例中的地址和标识仅用于说明位置。

POST /ag-ui/agent HTTP/1.1
Host: <agent-endpoint>
Content-Type: application/json
Accept: text/event-stream
X-AgentCore-Session-ID: demo-session-01
<鉴权 Header 名>: <实际鉴权值>

{
  "threadId": "demo-session-01",
  "runId": "demo-run-01",
  "messages": [
    {"id": "demo-message-01", "role": "user", "content": "请介绍这份报告的主题。"}
  ],
  "state": {},
  "tools": [ ],
  "context": [ ],
  "forwardedProps": {}
}

会话标识同时出现在 Header 与 Body 中:选择 AG-UI 并不意味着不再需要会话 Header。

场景二:业务应用继续同一个 AG-UI 会话

调用方自行保存会话标识。第二次调用复用 demo-session-01,并为本次运行使用新的 demo-run-02。服务未自动保存历史时,调用方还需携带上一轮消息,下面的 assistant 内容必须替换成上一轮实际返回结果。

POST /ag-ui/agent HTTP/1.1
Host: <agent-endpoint>
Content-Type: application/json
Accept: text/event-stream
X-AgentCore-Session-ID: demo-session-01
<鉴权 Header 名>: <实际鉴权值>

{
  "threadId": "demo-session-01",
  "runId": "demo-run-02",
  "messages": [
    {"id": "demo-message-01", "role": "user", "content": "请介绍这份报告的主题。"},
    {"id": "demo-message-02", "role": "assistant", "content": "替换为上一轮实际返回的内容。"},
    {"id": "demo-message-03", "role": "user", "content": "请把结论整理为三点。"}
  ],
  "state": {},
  "tools": [ ],
  "context": [ ],
  "forwardedProps": {}
}

新开一段对话时,同时更换会话 Header 的值和 threadId,并只传入新对话需要的消息。更换 runId 只表示开始新一次运行,不表示新开一个会话。

场景三:业务应用调用 Chat Completions 接口

下面的示例与控制台调试使用一致的会话承载位置:查询参数 sessionId 和会话 Header 使用相同的值;Body 使用 Chat Completions 格式,不添加 AG-UI 的 threadId、runId。该查询参数属于平台接入用法,业务调用是否需要携带以目标 Endpoint 的调用示例为准;调用示例包含此参数时,使用与会话 Header 相同的会话值。

POST /openai/v1/chat/completions?sessionId=demo-session-02 HTTP/1.1
Host: <agent-endpoint>
Content-Type: application/json
X-AgentCore-Session-ID: demo-session-02
<鉴权 Header 名>: <实际鉴权值>

{
  "model": "agentcore",
  "messages": [
    {"role": "user", "content": "请用一句话介绍你能做什么。"}
  ],
  "stream": false
}

路径和 model 按应用实际实现填写:上面的路径适用于 AgentCoreServer 默认接口,已有 HTTP 服务可能使用其他路径;model 是请求协议字段,是否影响下游模型选择由应用决定。需要跨协议继续对话时,由应用保证一致的历史与状态管理,见“历史与状态的归属”。

场景四:业务应用使用自定义会话 Header 名称

创建 Agent 时将会话 Header 名设为 X-Business-Session,则上述请求中的会话 Header 改为:

X-Business-Session: demo-session-01

AG-UI 的 threadId 仍填 demo-session-01,每次运行仍使用新 runId。自定义 Header 名称不改变协议 Body 的字段名,也不改变会话与实例的容量关系。

高代码 Agent 与托管 Harness 的区别

维度

高代码 Agent

托管 Harness

谁实现 Agent 的执行逻辑

应用代码、框架和 HTTP 服务。

所选 Harness。

协议能力

由代码实际实现,并在控制台声明;可以实现一种或多种协议。

以所选 Harness 及端点实际提供的协议为准,不能直接套用高代码的全部协议选项。

会话字段在控制台调试中由谁填写

调试面板按会话配置和所选协议组装。

相应调试入口按 Harness 的接入约定组装。

从业务应用调用

调用方按端点示例提供会话字段。

同样按对应端点示例提供会话字段;使用 Harness 不等于调用方无需区分对话。

历史保存、工具状态与恢复

由应用或框架实现,见“历史与状态的归属”。

由 Harness 的实现、配置及存储能力决定,应查阅所选 Harness 的使用说明。

两种形态都需要区分“哪一个会话”和“这个会话有哪些状态”。不要把某个 Harness 的历史行为描述为所有高代码应用的通用能力。

会话与实例容量

一个 Agent 可以有多个运行实例,一个实例也可以承载多个会话。会话标识不是实例 ID,增加实例数不会增加同一条请求中携带的会话数量。控制台配置项中的 Session 与本文所称会话指同一对象。以高代码 Agent 的固定实例配置为例:

配置

含义

实例数为 2

配置目标为两个运行实例。

实例最大 Session 数为 5

每个实例的活动会话容量配置为 5。

Session TTL 为 600 秒

会话持续无活动达到配置时长后回收;该值不控制单次模型生成耗时。

在两个实例都就绪、均按每实例 5 个会话承载的前提下,配置层面的会话槽位合计为 2 × 5 = 10。这不代表一定能同时执行 10 个高耗时请求,也不代表实际吞吐达到 10 QPS:模型配额、工具耗时、内存占用以及实例健康状态都会影响可用能力。

部分实例尚未就绪时,可用容量可能低于配置容量。达到容量限制时,根据实际错误与运行状态(实例就绪状态、活动 Session 数)区分会话容量、应用并发和下游限流三类原因,不能只靠提高 Session TTL 解决。TTL 越长,空闲会话可能占用容量的时间也越长。

对支持弹性伸缩的其他 Agent 形态,还需区分当前就绪实例数与配置的伸缩上限,不将高代码固定实例数的说明套用为所有形态的伸缩规则。

会话隔离的边界

会话隔离指不同会话之间不共享不应共享的历史与状态,包括同一终端用户的不同对话与不同终端用户的对话。隔离效果由平台与调用方共同决定,两侧责任范围不同。

平台侧提供会话的识别与调度边界:会话标识决定请求归属哪一个会话;同一会话的路由关联用于维持执行连续性,但不是永久绑定同一个进程的承诺;实例按“实例最大 Session 数”承载多个会话,空闲会话按 Session TTL 回收。

调用方侧决定隔离的实际效果:会话标识由业务生成,同一对话复用、新开对话更换新值,不同对话不共用同一个标识;历史与业务状态的保存与恢复由应用或框架实现;实例重启、更新或会话回收后,应用应能通过已保存的状态恢复。

会话标识只表示请求归属,既不表示平台已保存历史,也不表示会话独占了实例;历史与状态的责任划分见“历史与状态的归属”,隔离效果的验证方式见“接入验证”。

接入验证

验证路由和隔离时,结合“实例与 Session”信息及应用日志判断。

验证项

做法

通过判据

同会话多次请求

复用会话标识,AG-UI 每次运行使用新的 runId。

历史按应用约定传入或恢复。

新会话独立开始

生成新的会话标识后发起对话。

请求与应用读取的历史均不包含旧对话内容。

多个终端用户并发

同时发起同一终端用户的多个对话与不同终端用户的对话。

各对话不共享不应共享的状态。

自定义 Header

修改会话 Header 名称配置后发起调用。

调用方使用的实际字段名和值与配置一致,各调用入口已同步更新。

空闲与重启恢复

观察 Session 回收、实例重启或应用更新后的业务表现。

业务能从持久化状态恢复。

容量验证

查看实例就绪状态、活动 Session 数和实际错误。

能区分平台容量限制与下游服务限制。

重要

模型回答记得上轮内容可能仅因请求携带了历史,不能单凭回答内容证明平台已保存历史,也不能证明会话独占了实例。

相关文档