View a markdown version of this page

策略会话和身份传播 - 亚马逊基岩 AgentCore

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

策略会话和身份传播

使用临时策略,您可以根据会话中过去发生的事件来定义规则,而不仅仅是当前请求。您可以强制执行约束条件,例如:

  • “每个会话最多允许 5 次工具调用”

  • “除非在此会话中首先调用工具 A,否则禁止访问工具 B”

  • “在此会话中访问敏感数据后拒绝外部 API 调用”

策略会话将多个网关调用分组为一个逻辑会话。会话是评估临时策略规则的边界。

工作原理

  • 您的应用程序使用标头在向网关发出的请求时传递会话x-amzn-bedrock-agentcore-policy-session-id标识符。

  • 网关将会话绑定到调用者的身份验证身份(主体)。

  • 每次调用时,网关都会根据该会话中累积的操作历史来评估时间策略。

  • 在多跳场景中(网关 → 运行时 → 网关),平台通过服务管理的标头自动传播会话和呼叫者身份。X-Amz-Bedrock-AgentCore-Identity-WAT您的代理代码无需管理此标头—— AgentCore 可以透明地进行处理。

重要

Multi-hop 场景仅适用于单个 AWS 账户和区域。 AgentCore 不支持跨账户或跨区域的多跳场景。

传递策略会话 ID

在向网关发出的请求中包含x-amzn-bedrock-agentcore-policy-session-id标题。从您的第一个请求开始,您必须生成会话 ID 并将其发送到每个请求中。网关不会代表您生成会话 ID。该值是标识会话的字符串,我们建议使用 UUIDv4。在同一会话中为每个请求发送相同的 ID。

如果您省略标头或发送空值,则网关不会建立会话。如果关联的策略引擎包含临时策略,则没有会话 ID 的请求会因验证错误而失败。

有关接受的格式以及网关如何对其进行验证,请参阅标头验证和非运行时部署。

第一个请求(创建会话):

curl -X POST \ https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "x-amzn-bedrock-agentcore-policy-session-id: 12345678-1234-1234-1234-123456789012" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "PaymentTool___transfer_funds", "arguments": { "amount": 500, "recipient": "account-789" } } }'

后续请求(继续会话):

curl -X POST \ https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "x-amzn-bedrock-agentcore-policy-session-id: 12345678-1234-1234-1234-123456789012" \ -d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "PaymentTool___transfer_funds", "arguments": { "amount": 600, "recipient": "account-456" } } }'

如果您的临时策略将每个会话限制为 1 次传输,则前面示例中显示的第二个请求将被拒绝。

Python 示例:

import requests import uuid GATEWAY_URL = "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp" ACCESS_TOKEN = "YOUR_ACCESS_TOKEN" # Generate or reuse a session ID for the conversation session_id = str(uuid.uuid4()) # for example, "12345678-1234-1234-1234-123456789012" def call_tool(tool_name, arguments, session_id): headers = { "Content-Type": "application/json", "Authorization": f"Bearer {ACCESS_TOKEN}", "x-amzn-bedrock-agentcore-policy-session-id": session_id } payload = { "jsonrpc": "2.0", "id": "request-1", "method": "tools/call", "params": { "name": tool_name, "arguments": arguments } } response = requests.post(GATEWAY_URL, headers=headers, json=payload) return response.json() # First call - allowed result1 = call_tool( "PaymentTool___transfer_funds", {"amount": 500, "recipient": "account-789"}, session_id ) print(result1) # Success # Second call in same session - may be denied by temporal policy result2 = call_tool( "PaymentTool___transfer_funds", {"amount": 600, "recipient": "account-456"}, session_id ) print(result2) # Denied if rate-limit policy applies

会话生命周期

属性 值

创建

在使用会话 ID 的第一个请求时隐含

空闲超时

自上次活动起 24 小时

明确关闭

不支持;会话自然过期

最长使用寿命

受空闲超时限制

多跳场景中的身份传播

在代理架构中,请求通常会流经多个 AgentCore 原语:

User -> Gateway1 -> Runtime (agent) -> Gateway1 (tool call) -> Target

要使临时策略在这些跃点上起作用,必须保留会话身份。 AgentCore使用工作负载身份链 (WIC) 自动处理此问题:

  • 在原始网关:网关铸造工作负载访问令牌 (WAT),该令牌嵌入sessionId和callerPrincipal(原始调用者的身份)。

  • 网关 → 运行时:WAT 通过内部标X-Amz-Bedrock-AgentCore-Identity-WAT头传递。

  • 运行时 → 网关(工具调用):运行时将入站 WAT 交换为新的 WAT(链扩展),自动保留sessionId和callerPrincipal。出站请求上印有扩展的 WAT。

  • 接收网关:针对同一会话评估时间策略,保持连续性。

这对你意味着什么:

  • 您只需要将初始请求传递x-amzn-bedrock-agentcore-policy-session-id给网关。该平台负责处理向所有下游跃点的传播。

  • 您的代理代码无需读取、修改或转发标X-Amz-Bedrock-AgentCore-Identity-WAT头。这由 AgentCore 基础架构(运行时、网关和 AgentCore 身份服务)管理。

  • 会话ID位于WAT内部,不能被中介机构欺骗或篡改。

End-to-end 流量:

User            Gateway1            Runtime            Gateway1            Target
 |  POST /mcp      |                   |                   |                  |
 |  + session-id X |                   |                   |                  |
 |  + Authorization|                   |                   |                  |
 |---------------->|                   |                   |                  |
 |                 | mint WAT1         |                   |                  |
 |                 | (sid=X, cpn=user) |                   |                  |
 |                 |  forward + WAT1   |                   |                  |
 |                 |------------------>|                   |                  |
 |                 |                   |exchange WAT1->WAT2|                  |
 |                 |                   | (sid=X preserved) |                  |
 |                 |                   | tool call + WAT2  |                  |
 |                 |                   |------------------>|                  |
 |                 |                   |                   | evaluate temporal|
 |                 |                   |                   | policy, session X|
 |                 |                   |                   |  forward         |
 |                 |                   |                   |----------------->|

重要注意事项

  • 会话 ID 由客户管理。您可以选择何时创建新会话还是继续现有会话。新的会话 ID 意味着新的临时策略评估边界。

  • 标X-Amz-Bedrock-AgentCore-Identity-WAT题是内部的。请勿在代理代码中设置、修改或删除此标头。 AgentCore 端到端地管理它。

  • Multi-gateway 场景(网关 1 → 运行时 → 网关 2):会话状态通过 WAT 自动传播。Gateway2 使用相同的会话 ID 评估自己的临时策略。

  • authorizerType=NONE网关不提供每个调用者的会话隔离。如果未配置身份验证,则网关没有可以绑定会话的呼叫者身份。所有提供相同会话 ID 的呼叫者共享一个临时策略事件流。一个呼叫者的操作计入另一个呼叫者的速率限制或排序限制。未经身份验证的网关的时间策略仅是建议性的:它可以强制执行全局限制(例如,“每个会话对该工具的总调用次数最多为 100 次”),但无法区分或隔离单个呼叫者。要隔离每个呼叫者,请使用CUSTOM_JWT或AWS_IAM身份验证配置您的网关。

在 SDK 中使用会话 ID

您可以通过任何支持网关请求自定义标头的客户端传递策略会话 ID。以下示例显示了在使用 MCP Python SDK 和 Strands 代理时如何将其包括在内。

对同一逻辑会话中的所有调用使用相同的会话 ID 值。当新的对话开始时,生成一个新的会话 ID。

MCP 客户端(Python SDK):

当您使用带有可流式传输的 HTTP 传输的 MCP Python SDK 时,请在连接标头中包含会话 ID:

from mcp import ClientSession from mcp.client.streamable_http import streamablehttp_client import asyncio SESSION_ID = "12345678-1234-1234-1234-123456789012" async def call_with_session(gateway_url, token, tool_name, arguments): headers = { "Authorization": f"Bearer {token}", "x-amzn-bedrock-agentcore-policy-session-id": SESSION_ID } async with streamablehttp_client(url=gateway_url, headers=headers) as (read, write, _): async with ClientSession(read, write) as session: await session.initialize() result = await session.call_tool(name=tool_name, arguments=arguments) return result result = asyncio.run(call_with_session( "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp", "YOUR_TOKEN", "PaymentTool___transfer_funds", {"amount": 500, "recipient": "account-789"} ))

Strands 代理商:

当您使用以 AgentCore 网关作为工具源的 Strands 代理时,请在 MCP 客户端传输标头中传递会话 ID。代理在会话期间进行的所有工具调用都将进行相同的会话,而临时策略则会评估完整的历史记录。

from strands.tools.mcp.mcp_client import MCPClient from mcp.client.streamable_http import streamablehttp_client SESSION_ID = "12345678-1234-1234-1234-123456789012" def create_transport(mcp_url, access_token): return streamablehttp_client( mcp_url, headers={ "Authorization": f"Bearer {access_token}", "x-amzn-bedrock-agentcore-policy-session-id": SESSION_ID } ) mcp_client = MCPClient(lambda: create_transport(gateway_url, token)) with mcp_client: result = mcp_client.call_tool_sync( tool_use_id="tool-1", name="PaymentTool___transfer_funds", arguments={"amount": 500, "recipient": "account-789"} )

Real-world 客户用例

以下场景说明了临时策略如何解决代理应用程序中常见的安全和合规性挑战。

金融服务 — 传输速率限制

金融科技应用程序允许最终用户通过对话代理发起银行转账。如果没有临时策略,受感染或循环代理可以在单个会话中执行无限制的传输。使用会话范围的速率限制,网关强制规定每个会话的最大传输次数:

User: "Transfer $500 to Alice"      -> Allowed (1 of 3)
User: "Transfer $200 to Bob"        -> Allowed (2 of 3)
User: "Transfer $1000 to Charlie"   -> Allowed (3 of 3)
User: "Transfer $50 to Dave"        -> DENIED by temporal policy

每个用户会话都使用自己的会话 ID。当新会话启动时,速率限制会重置,因为新的会话 ID 会创建新的评估边界。

医疗保健-升级控制

医疗保健代理访问患者记录,还可以向外部通知系统发送消息。临时政策规定,一旦访问了患者数据,就不允许在会话的剩余时间内进行外部 API 调用。即使代理的提示在会话中被操纵,这也能防止数据泄露:

Agent: calls PatientRecords___read_chart      -> Allowed
Agent: calls ExternalAPI___send_notification  -> DENIED (sensitive data was accessed in this session)

限制不在于工具本身,允许在从不访问患者数据的会话中使用。send_notification该政策考虑了在此特定会话中早些时候发生的事情。

DevOps — 排序限制

部署代理必须遵循强制性顺序:必须先通过测试,然后才能继续部署。临时策略强制执行,Deploy只能在同一个会话中RunTests被调用后才能调用:

Agent: calls Deploy___to_production   -> DENIED (RunTests not yet called in this session)
Agent: calls RunTests___execute       -> Allowed
Agent: calls Deploy___to_production   -> Allowed (RunTests was called earlier in this session)

无论代理如何提示或由哪个编排框架控制,这都能保证部署顺序。

Multi-tenant SaaS — 强制执行每位用户的预算

SaaS 平台通过共享应用程序凭证(通过 On-Behalf-Of (CUSTOM_JWTOBO) 流程为每个用户提供sub索赔)背后为多个最终用户托管 AI 代理。每个用户的会话都会收到一个唯一的会话 ID。由于网关将会话绑定到会话 ID 和经过身份验证的主体,因此不同的用户会话会自动隔离。临时政策强制执行 “每次会话至多100美元的工具调用” ——即使所有流量都通过相同的应用程序凭证到达,每个用户也会独立评估。

选择会话范围:宽会话与窄会话

您提供的会话 ID 决定临时策略的评估边界。选择正确的范围会影响安全性和可用性:

Strategy 会话 ID 模式 优点 缺点

Per-conversation (推荐)

每个用户对话的新 UUID

自然边界;对话之间重置速率限制;清晰的用户心理模型

代理必须启动新会话才能获得新的限制

Per-user (广泛)

每个用户的稳定 ID(例如,用户 ID 的哈希值)

政策适用于所有对话;对日常预算执行很有用

在 TTL(24 小时)内永远不会重置限制;在无关的任务之间共享

Per-request (狭窄)

每个请求都有新的 UUID

每个请求都是独立的

临时策略实际上已被禁用——没有可评估的历史记录

Per-task

每个逻辑任务的 UUID(例如,“处理此订单”)

策略范围限于特定工作流程;适合多步骤代理任务

应用程序必须管理任务 → 会话 ID 映射

指南:

  • 从每次对话开始。这是大多数交互式代理用例的自然搭配。

  • 当您需要强制执行交叉对话时,请使用每位用户(例如,“无论有多少对话,每天转账不超过 10 次”)。

  • 除非你故意不想进行临时策略评估,否则切勿使用每个请求。

  • 避免会话过于宽泛(例如,为所有用户设置一个会话 ID)——这会将所有呼叫者的操作聚合到一个事件流中,从而使每位用户的速率限制变得毫无意义。

标头验证和非运行时部署

网关如何验证会话 ID

当网关收到标x-amzn-bedrock-agentcore-policy-session-id头时,它会执行以下验证:

  • 格式检查:该值必须为 1—128 个字符,仅包含字母数字字符和连字符 ()。[A-Za-z0-9-]HTTP 400 会拒绝格式错误或过大的值。如果未通过此检查,则永远不会使用或反映标头。

  • 主绑定:在经过身份验证的网关(CUSTOM_JWT或AWS_IAM)上,网关将会话绑定到调用者的经过身份验证的身份。两个提供相同会话 ID 的不同呼叫者会获得隔离的会话——身份是会话密钥的一部分。

  • 隐式创建:无需预注册会话。具有给定会话 ID 的第一个请求会隐式创建会话。无需单独的 “创建会话” API 调用。

如果你直接调用网关(不使用 AgentCore 运行时)

当您的应用程序直接调用网关端点时(例如,向网关 URL 发出 HTTP 请求的后端服务),您可以自己管理会话 ID:

  • 在每个逻辑对话开始时生成会话 ID(我们推荐uuid4)。

  • 将该对话中的每个请求x-amzn-bedrock-agentcore-policy-session-id: <your-session-id>作为 HTTP 标头包括在内。

  • 在对话期间将会话 ID 存储在客户端,以便后续请求引用同一个会话。

无需额外的配置、权限或 API 调用。网关会在首次使用时创建会话,并在不活动 24 小时后过期。

如果您的请求通过 AgentCore Runtime 传输

当调用遍历用户 → 网关 → 运行时(代理)→ 网关(工具调用)路径时,您只需要将初始请求中的会话 ID 传递给第一个网关。该平台将会话 ID 嵌入到工作负载访问令牌 (WAT) 中,并自动将其传播到所有下游跃点。您的代理代码无需读取、存储或转发会话 ID,它会透明地到达接收网关。

关于工作负载访问令牌 (WAT)

工作负载访问令牌是一个 AWS签名的不透明令牌,它携带请求在服务之间 AgentCore 流动时的身份上下文。当临时策略处于活动状态时,WAT 包含:

  • 会话 ID — 将多跳请求中的所有跃点链接到同一个临时策略会话。

  • 主叫方 — 保留原始呼叫者的身份,以便下游网关可以正确绑定会话。

  • 工作负载链 — 请求遍历的 AgentCore 服务的有序列表(例如,[Gateway, Runtime, Gateway])。

WAT 是短暂的(TTL 15 分钟),由 AgentCore 身份服务加密签名,对所有参与者都是不透明的。它不能被呼叫者或中介伪造、篡改或解码。

你不能直接与 WAT 互动。它通过内部X-Amz-Bedrock-AgentCore-Identity-WAT标头进行传输,该标头完全由平台管理。提供此解释是为了让您了解会话连续性是如何跨跃点工作的,您无需对 WAT 采取任何措施。

有关工作负载身份和访问令牌的更多详细信息,请参阅获取工作负载访问令牌和了解工作负载身份。