会话机制与会话隔离
AgentCore 通过会话标识把属于同一次对话的请求组织在一起,并按实例容量配置管理这些会话。会话标识经 HTTP Header 传递,与 AG-UI、Chat Completions 的协议字段处在请求的不同位置。会话标识只表示请求归属,不表示平台已保存对话历史;历史与业务状态由应用或托管 Harness 负责。
以下内容以高代码 Agent 为主,托管 Harness 与其他 Agent 形态的差异在对应章节就地说明。创建高代码 Agent 时,可先按高代码 Agent 部署与使用指南完成部署,再结合本文涉及业务调用中的会话标识与历史管理。
会话与会话标识
会话(Session)用于将属于同一次对话或交互过程的请求组织在一起。终端用户先提交“分析这份报告”,随后继续问“把结论整理为三点”,两次请求可以使用同一个会话标识;终端用户另起一次对话时,应使用新的会话标识。
本文区分两个角色:使用 Agent 对话的终端用户,以及接入 Agent 的调用方(业务应用)。会话标识由调用方生成和维护。会话机制涉及三个概念:
概念 | 解决的问题 | 说明与示例 |
会话标识 | 这次请求属于哪一个会话 | 如 |
运行实例 | 由哪个运行环境执行请求 | 一个实例可按容量配置承载多个会话。 |
对话历史与业务状态 | 本次执行需要哪些上下文,以及执行结果存在哪里 | 消息列表、框架检查点、用户文件、工具执行结果。 |
历史与状态的归属
会话标识用于识别会话,不是对话历史本身。把两个请求标成同一个会话,不等于平台已经替应用保存了上一轮消息。历史与业务状态是否保存、能否恢复,取决于应用或托管 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 |
|
Chat Completions | 会话 Header;控制台调试请求另在 URL 查询参数携带 | 标准请求体没有 |
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 / 两种协议) | 调试面板创建新会话时生成并保存;后续请求使用当前会话标识。 | 由调用方生成并保存:新对话使用新值,同一对话复用。 |
| 填入当前会话标识,与会话 Header 的值相同。 | 参照调试面板,使用与会话 Header 相同的值。 |
| 每次构造运行请求时生成新值。 | 每次新运行使用新值。 |
消息 id(Body 的 messages / AG-UI) | 调试面板按当前会话标识和消息序号组装。 | 为请求中的消息填写 ID;格式及历史消息的 ID 复用要求按所接入服务的约定处理。 |
消息列表 messages(Body / 两种协议) | 将当前调试对话的历史消息与本轮终端用户输入一起放入请求。 | 按应用接口约定提供消息列表;由调用方维护历史时,将相关历史一并传入。 |
| 追加当前会话标识,与会话 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-01AG-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 每次运行使用新的 | 历史按应用约定传入或恢复。 |
新会话独立开始 | 生成新的会话标识后发起对话。 | 请求与应用读取的历史均不包含旧对话内容。 |
多个终端用户并发 | 同时发起同一终端用户的多个对话与不同终端用户的对话。 | 各对话不共享不应共享的状态。 |
自定义 Header | 修改会话 Header 名称配置后发起调用。 | 调用方使用的实际字段名和值与配置一致,各调用入口已同步更新。 |
空闲与重启恢复 | 观察 Session 回收、实例重启或应用更新后的业务表现。 | 业务能从持久化状态恢复。 |
容量验证 | 查看实例就绪状态、活动 Session 数和实际错误。 | 能区分平台容量限制与下游服务限制。 |
模型回答记得上轮内容可能仅因请求携带了历史,不能单凭回答内容证明平台已保存历史,也不能证明会话独占了实例。