关于 agents-harden
agents-harden 是面向准备将 AgentCore Agent 部署到生产环境的开发者的技能。它读取项目配置,针对安全性、可靠性和性能生成检查清单。
主要功能
- 01生成项目专属的生产检查清单
- 02提供 IAM 权限范围收紧建议
- 03检查入站身份验证配置
- 04检查错误处理与输入验证
- 05提供密钥和速率限制建议
适用场景
- 01在发布前审查 AgentCore Agent
- 02限制可调用 Agent 的主体
- 03排查限流或配额错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aws/ agent-toolkit-for-aws --skill agents-harden安装后在 Claude Code 中输入/agents-harden确认已加载。
附带文件references/limits.md
详细介绍
强化
让你的 AgentCore Agent 做好生产环境部署准备——提升安全性、可靠性和性能。
适用场景
- 即将将 Agent 部署到生产环境
- 想要一份上线前的检查清单
- 想要限制哪些人可以调用 Agent
- 想要缩减默认 IAM 权限
- 遇到限流或配额错误(会加载
references/limits.md) - 需要针对工作负载调整会话生命周期
- Agent 中运行着长时间的后台任务
输入
无需参数。此技能会读取项目配置,并生成针对项目的检查清单,其中包含具体发现。
流程
步骤 0:验证 CLI 版本
运行 agentcore --version。此技能要求版本为 v0.9.0 或更高。如果版本较旧,请告知开发者先运行 agentcore update。
步骤 1:读取项目
读取 agentcore/agentcore.json,了解:
- 配置了哪些资源(memory、gateway、credentials、evaluators)
- 使用了什么框架
- 配置了哪种网络模式(PUBLIC 或 VPC)
步骤 2:逐项检查清单
逐类检查,并报告针对项目的发现。
IAM:缩减权限范围
自动创建的执行角色拥有广泛的 Bedrock 访问权限(arn:aws:bedrock:*::foundation-model/*)。对于生产环境,应将权限范围缩减至 Agent 使用的特定模型。
检查当前执行角色:
agentcore status --json | jq -r '.runtimes[0].executionRoleArn'
推荐的生产环境 Bedrock 策略:
{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": [
"arn:aws:bedrock:<REGION>::foundation-model/anthropic.claude-sonnet-4-5-20250929-v1:0"
]
}
将资源 ARN 替换为 Agent 使用的特定模型 ARN。
**ECR 访问权限:**将范围缩减至特定存储库:
{
"Effect": "Allow",
"Action": ["ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer"],
"Resource": "arn:aws:ecr:<REGION>:<YOUR_ACCOUNT_ID>:repository/bedrock-agentcore-<AGENT_NAME>-*"
}
**信任策略:**确认执行角色的信任策略已限定为你的账户:
{
"Principal": {"Service": "bedrock-agentcore.amazonaws.com"},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {"aws:SourceAccount": "<YOUR_ACCOUNT_ID>"},
"ArnLike": {"aws:SourceArn": "arn:aws:bedrock-agentcore:<REGION>:<YOUR_ACCOUNT_ID>:*"}
}
}
运行时基于资源的策略(仅限 API):如需精细控制哪些主体可以调用运行时(超出 IAM 角色和 JWT 身份验证所能提供的控制范围),请通过 boto3 使用 PutAgentRuntimeResourcePolicy。CLI 和 agentcore.json 中均未提供此功能。如有可用的 awsknowledge MCP 服务,可用它查询当前 API 格式。
Shell 访问:单独限制 InvokeAgentRuntimeCommand 的权限范围
如果项目使用了 InvokeAgentRuntimeCommand(参见 agents-build/references/integrate.md),请将其 IAM 权限与 InvokeAgentRuntime 分开审查。这两个操作的影响范围不同:InvokeAgentRuntimeCommand 可在运行中的 microVM 内执行任意 Shell 命令,并拥有运行时的全部执行角色权限——调用方可以读取或写入文件系统、访问 Agent 能访问的任何网络资源,以及使用执行角色的凭证。
检查哪些主体拥有此权限:
# List customer-managed policies in your account, then inspect each for InvokeAgentRuntimeCommand
aws iam list-policies --scope Local \
--query 'Policies[*].[PolicyName, Arn, DefaultVersionId]' \
--output table
# Then for each policy of interest:
aws iam get-policy-version \
--policy-arn <POLICY_ARN> \
--version-id <VERSION_ID> \
--query 'PolicyVersion.Document'
或者使用 IAM 控制台:IAM → Policies → 按类型筛选:Customer managed → 在策略 JSON 编辑器中搜索 InvokeAgentRuntimeCommand。
为命令调用方创建单独的 IAM 策略——将此策略与授予 InvokeAgentRuntime 权限的策略分开:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "bedrock-agentcore:InvokeAgentRuntimeCommand",
"Resource": "arn:aws:bedrock-agentcore:<REGION>:<YOUR_ACCOUNT_ID>:runtime/<RUNTIME_NAME>-*"
}]
}
**启用 CloudTrail 告警。**创建 EventBridge 规则,在调用 InvokeAgentRuntimeCommand 时通知安全团队:
aws events put-rule \
--name AgentCoreCommandExecution \
--event-pattern '{"source":["aws.bedrock-agentcore"],"detail-type":["AWS API Call via CloudTrail"],"detail":{"eventName":["InvokeAgentRuntimeCommand"]}}' \
--state ENABLED
**如果调用代码中的任何位置会根据用户输入构造命令:**传递命令前先进行验证——拒绝包含 &&、;、$(...)、反引号、| 或其他 Shell 元字符的字符串。
入站身份验证:控制哪些人可以调用你的 Agent
默认情况下,Agent 使用 AWS IAM(SigV4)进行入站身份验证。对于生产环境,请确认配置正确。
检查当前身份验证配置:
agentcore status --runtime <AgentName> --json | jq '.runtimes[0].authorizerConfig'
选项:
AWS_IAM(默认)— 调用方必须使用 SigV4 对请求签名。适用于内部服务和原生支持 AWS 的客户端。
CUSTOM_JWT — 调用方提供来自身份提供商的 JWT。适用于 Web/移动应用和外部客户端。
agentcore add agent \
--name MyAgent \
--authorizer-type CUSTOM_JWT \
--discovery-url https://your-idp.example.com/.well-known/openid-configuration \
--allowed-audience my-api \
--allowed-clients my-client-id
警告
切勿在生产环境中使用
--authorizer-type NONE。这会允许未经身份验证的访问 你的 Agent — 任何知道端点 URL 的人都可以调用它。始终使用 AWS_IAM 或 CUSTOM_JWT。如果你在生产环境中看到 NONE,请立即更改。
选择 allowedClients 还是 allowedAudience
这是最常见的 JWT 配置错误。正确选择取决于身份提供商签发的令牌中包含哪些内容。
解码一个示例令牌(在身份提供商处或使用 jwt.io),并查看载荷:
- 令牌包含
client_id声明,但不包含aud声明 → 在运行时配置allowedClients - 令牌包含
aud声明 → 在运行时配置allowedAudience - 令牌同时包含两者 → 使用
allowedAudience。aud声明是标准的 OIDC 受众字段;将其作为主要检查项。
如果选择错误,即使令牌有效,调用也会返回 403 — 运行时正在根据令牌中不存在的声明进行验证。
颁发者 ↔ 发现 URL 前缀要求
AgentCore 强制执行 OIDC 发现规范(RFC 8414 §3):发现文档中的 issuer 值必须是发现端点 URL 的前缀。
这意味着,如果你的发现 URL 是 https://qa.example.com/.well-known/openid-configuration,该文档中的 issuer 字段必须以 https://qa.example.com 开头。如果文档公布的颁发者类似 https://example.com(没有子域名),验证就会失败。
一些企业身份提供商(PingFederate、Paylocity 和某些 Keycloak 配置)会将发现端点托管在特定环境的子域名上,同时公布生产级颁发者。这种模式与 RFC 8414 的前缀规则不兼容。
修复选项:
- 让身份提供商的发现端点与其颁发者保持一致 — 从与颁发者相同的源提供发现文档。
- 将运行时指向实际的发现 URL 域名 — 使用与令牌颁发者相匹配的子域名配置运行时的发现 URL。
调试 JWT 身份验证失败
调用返回 403 时,请逐步确定是哪项检查失败。
Authorization method mismatch — 运行时的身份验证类型与请求的身份验证类型不匹配。分两种情况:
- 运行时配置为
AWS_IAM(或未配置授权器),但调用方发送了 Bearer 令牌 → 将运行时重新配置为CUSTOM_JWT,或让调用方使用 SigV4。 - 运行时配置为
CUSTOM_JWT,但调用方的请求由 SigV4 签名 → SDK 或环境可能在 Bearer 令牌旁注入了 SigV4 标头。检查发出的请求中是否包含X-Amz-Date、X-Amz-Security-Token或Authorization: AWS4-HMAC-SHA256。移除 SigV4 路径,只发送 Bearer 令牌。
Invalid inbound token(或类似错误)— JWT 验证器拒绝了令牌。按以下顺序逐项检查:
- 颁发者 ↔ 发现 URL 前缀(见上文)— 确认令牌的
iss声明与发现 URL 的源匹配 allowedClients还是allowedAudience— 运行时是否根据令牌格式配置了正确的声明?- JWKS 可访问性 — AgentCore 是否能访问发现文档中列出的
jwks_uri?该地址必须可公开访问。 - 令牌已过期 — 解码令牌,检查
exp是否早于当前时间 - 签名算法支持情况 — 某些身份提供商使用并非普遍支持的算法(PS256、ES384 等)签名。检查身份提供商支持的算法;如果兼容性是问题,请切换到 RS256。
只有排除以上所有原因后,才应将其视为服务端问题。
错误处理:优雅地处理错误
检查 Agent 代码能否在不暴露内部细节的情况下处理错误:
from bedrock_agentcore.runtime import BedrockAgentCoreApp
app = BedrockAgentCoreApp()
@app.entrypoint
def invoke(payload, context):
try:
# your agent logic
return {"response": result}
except Exception as e:
# Log the full error internally
app.logger.error(f"Agent error: {e}", exc_info=True)
# Return a safe message to the caller
return {"error": "An error occurred. Please try again."}
if __name__ == "__main__":
app.run()
检查内容: 会静默吞掉错误的裸 except 块、向调用者暴露堆栈跟踪或内部细节的错误消息、工具调用代码中缺少错误处理。
输入验证和速率限制
Agent 入口点会收到调用者发送的任意负载。处理前请验证输入:
@app.entrypoint
def invoke(payload, context):
prompt = payload.get("prompt", "")
# Validate input
if not prompt or not isinstance(prompt, str):
return {"error": "Missing or invalid 'prompt' field"}
if len(prompt) > 10000:
return {"error": "Prompt exceeds maximum length (10,000 characters)"}
# Sanitize — strip control characters, excessive whitespace
prompt = " ".join(prompt.split())
# Proceed with validated input
result = agent(prompt)
return {"response": str(result)}
验证内容:
- 必填字段是否存在,且类型是否符合预期
- 字符串输入是否超过合理的长度限制(防止模型遭到令牌轰炸)
- 数值输入是否在预期范围内
- 用户提供的 ID(actor_id、session_id)是否符合预期格式
速率限制: AgentCore Runtime 内置调用速率限制(每个 Agent 默认 25 TPS;参见 references/limits.md)。如需应用级速率限制(按用户、按租户),请在调用应用或 API Gateway 层实现,而不要在 Agent 代码本身中实现。请求到达 Agent 时,Agent 应假定请求已经过速率限制。
密钥:代码中不得包含凭据,运行时环境变量中不得包含密钥
请检查以下两种失误:
1. Agent 代码中的硬编码密钥
# Search for common secret patterns in agent code
grep -r "sk-\|api_key\s*=\s*['\"]" app/ --include="*.py"
grep -r "password\s*=\s*['\"]" app/ --include="*.py"
2. 从运行时环境变量中读取的密钥
AgentCore Runtime 环境变量不受保险库保护。开发者通过 CDK、boto3 UpdateAgentRuntime 或类似方式写入运行时环境的任何内容,都是明文配置值,而不是密钥。检查以下模式:
# Flag any os.getenv / os.environ call whose name implies a secret
grep -rE "os\.(getenv|environ).*(TOKEN|SECRET|KEY|PASSWORD|CREDENTIAL)" app/ --include="*.py"
平台注入的非敏感标识符不受影响,不应与允许列表匹配(例如,MEMORY_*_ID、AGENTCORE_GATEWAY_*_URL、AWS_REGION、下游 Agent ARN)。请检查匹配项,并确认其中不包含密钥。
正确做法: 使用 agentcore add credential 注册每个出站凭据,然后通过集成的凭据提供方在代码中获取:
from bedrock_agentcore.identity.auth import requires_api_key, requires_access_token
@requires_api_key(provider_name="MyAPI")
def call_api(payload: dict, *, api_key: str) -> dict:
...
@requires_access_token(provider_name="MyOAuthProvider", scopes=["read"], auth_flow="M2M")
async def call_downstream(data: dict, *, access_token: str) -> dict:
...
装饰器会在调用时从 Secrets Manager 获取凭据,并处理缓存和刷新。以这种方式注册的凭据在静态存储时会加密,并且可以在无需重新部署的情况下轮换。
本地开发: agentcore/.env.local(已加入 gitignore)会由 agentcore dev 读取,以便装饰器在本地解析凭据。部署时不会将此文件上传到运行时;生产凭据由凭据提供方管理。
工具范围:在 Agent 代码中优先使用 Gateway 目标,而非直接 HTTP 调用
相关审计——对于 Agent 调用的每项外部服务,都要确认是否应将其设为 Gateway 目标,而不是在 Agent 代码中埋入直接 HTTP 调用。Gateway 的凭证提供程序会在边缘注入身份验证信息(因此 Agent 进程永远不会接触密钥),工具目录可通过策略强制执行;而且,即使 Agent 代码中的堆栈跟踪或日志行泄露,也无法泄露从未传到其中的凭证。
# Find direct outbound HTTP calls in agent code
grep -rEn 'httpx\.|requests\.|aiohttp\.' app/ --include="*.py"
对于每个匹配项,请按以下方式判断:
| 匹配项 | 操作 |
|---|---|
| 调用外部 REST API,且 Agent 将其视为工具 | 将其设为 Gateway 目标(agentcore add gateway-target --type open-api-schema 或 api-gateway)。加载 agents-connect/SKILL.md 路径 C。 |
| 直接调用 MCP 服务 | 将其设为 Gateway 目标(--type mcp-server)。加载 agents-connect/SKILL.md 路径 A。 |
调用 AWS 服务(S3、DynamoDB 等)——不适合归入此行,应使用 boto3 | 将 requests/httpx 迁移为 boto3 客户端,并使用运行时的执行角色进行 IAM 身份验证。无需凭证。 |
| 调用流式服务(SSE 实时输出、WebSocket、WebRTC) | 可以保留直接调用——Gateway 目前还不支持这些服务。确认任何身份验证都使用 @requires_*,而非 os.getenv。 |
| 通过 A2A 调用其他 Agent | 可以保留直接调用——A2A 的设计本就基于 HTTP。确认它使用 @requires_access_token 获取承载令牌。 |
| 调用经测量确认为延迟热点且团队选择保留的路径 | 可以保留,但要确认已有测量,并且身份验证使用 @requires_*。 |
如果某个匹配项不符合任何“可以保留直接调用”的行,请创建工单,将其转换为 Gateway 目标。对于大多数框架集成,无需修改 Agent 代码即可添加 Gateway 目标(MCP 工具发现会处理绑定)。
可观测性:验证跟踪已启用
AgentCore 会自动启用 X-Ray 跟踪和 CloudWatch 日志记录。请验证:
agentcore status --runtime <AgentName> --json | jq '.runtimes[0].observabilityConfig'
CloudWatch 控制面板: AWS 控制台 → CloudWatch → GenAI Observability → Bedrock AgentCore
日志保留: 默认情况下,日志会无限期保留。设置保留策略以控制成本:
aws logs put-retention-policy \
--log-group-name /aws/bedrock-agentcore/runtimes/<AGENT_ID>-DEFAULT \
--retention-in-days 30
评估基线:上线前了解质量水平
投入生产前,先建立质量基线,以便检测回归:
# Run a baseline eval
agentcore run eval \
--evaluator "Builtin.Helpfulness" \
--evaluator "Builtin.GoalSuccessRate"
# Set up continuous monitoring
agentcore add online-eval \
--name production_monitor \
--runtime <AgentName> \
--evaluator "Builtin.Helpfulness" \
--sampling-rate 5
agentcore deploy -y
记录基线分数。如果变更后分数大幅下降,请先调查再继续。
网络:为私有资源配置 VPC
如果 Agent 需要访问私有 AWS 资源(RDS、内部 API),请配置 VPC:
agentcore add agent \
--name MyAgent \
--network-mode VPC \
--subnets subnet-abc,subnet-def \
--security-groups sg-123
完整的 VPC 配置指南请参阅 agents-build(加载 references/vpc.md)。
初始化时间:优化冷启动性能
Agent 初始化缓慢会导致超时、424 错误和糟糕的用户体验,尤其是在一段时间未活动后首次调用时。Agent 在准备好处理请求前执行的所有操作,都会延长用户的等待时间。
冷启动时间实际花在哪里
新环境的典型冷启动时间约为 20–30 秒。大致分解如下:
- 容器映像拉取——对于基于 Container 的构建,这是最主要的耗时。100 MB 的映像需要几秒;500 MB 的映像可能需要 15 秒以上。
- 应用程序启动——代码的导入时间、框架初始化、模块级设置。通常需要 5–10 秒;如果在导入时加载模型或建立连接,耗时可能会长得多。
- 平台开销(microVM 启动、网络连接、容器启动)——不到一秒到几秒不等。
你能控制的两项是映像大小和应用程序启动时间。优化其中任意一项都能直接缩短首次响应时间。
会话复用是最具杠杆效应的优化
同一会话中的请求会路由到已初始化的现有环境,无需冷启动。每个会话的首次请求需要承担冷启动开销;该会话后续的每个请求都能快速处理。
具体模式:
- 多轮对话: 在各轮之间复用同一个
session_id。不要每轮都生成新的 UUID。 - 批处理: 在批次中的各项之间复用同一个
session_id。 - 面向用户的应用: 将会话范围限定为一次用户交互(例如,每次聊天对话使用一个会话),而不是每条消息使用一个会话。
跨 SDK 提示:如果使用 MCP,请传递一个会话标识符,不要同时传递 runtimeSessionId 和 mcpSessionId。同时发送两者可能导致平台将两个独立环境绑定到同一个逻辑会话,使冷启动开销翻倍。
软件包大小预算
部署软件包每增加 1 MB,都会增加冷启动时间。
- 目标: 小于 200 MB。如果可以,尽量控制在 100 MB 以下。
- 对于 Container 构建: 使用多阶段 Dockerfile、精简或 distroless 基础映像,移除构建工具和测试文件,并添加
.dockerignore。 - 对于 CodeZip 构建: 从
pyproject.toml/requirements.txt中删减开发依赖项。不要打包tests/、docs/、.git/和本地缓存。 - 定期审查:
pip list(Python)或npm ls(Node)可以显示实际安装的内容。移除所有不再使用的内容。
延迟繁重的初始化操作
不要在模块导入时加载大型模型、连接数据库或初始化 MCP 客户端。模块导入耗费的每一秒,都会让 Agent 多一秒无法响应请求。
# ❌ Slow — runs at import time, before the agent can handle requests
import heavy_library
client = heavy_library.Client(config)
# ✅ Fast — defers until first request
_client = None
def get_client():
global _client
if _client is None:
import heavy_library
_client = heavy_library.Client(config)
return _client
根据流量模式选择部署类型,而不是默认选择
该技能之前建议尽可能优先选择 CodeZip,而不是 Container。这种说法过于简单。实际的权衡如下:
- CodeZip: 迭代更简单,涉及范围更小。冷启动包括下载和解压代码——一个约 95 MB 的软件包会增加约 1.3 秒的平台下载时间,之后应用才会开始启动。
- Container: 可以完全控制映像,需要自定义系统依赖项时必须使用。较大的映像会增加每次冷启动的成本,但可以通过多阶段构建进行大幅优化。
两者并非在所有情况下都各有优劣。两者都能同样受益于会话复用和缩小软件包。如果流量模式中有大量突发的冷会话,请投入精力缩小所用的部署制品。如果流量模式会复用会话,部署类型的重要性就小得多。
对于 Gateway 后面的 Lambda 目标
在 Lambda 函数上使用预置并发,以消除 Lambda 冷启动。这与 Runtime 初始化不同——首次调用冷 Lambda 时,是 Lambda 本身增加了延迟。
会话生命周期管理
会话管理与成本、性能以及 maxVms 配额密切相关。正确管理会话,往往是顺利上线生产环境与被配额阻塞之间的关键区别。
默认生命周期
收到带有新会话 ID 的请求时,Runtime 会为其初始化一个全新环境。该环境会一直运行,直到发生以下情况之一:
- 会话被显式停止,通过
StopRuntimeSession实现。 - 空闲超时到期。 Runtime 会回收在
idleRuntimeSessionTimeout指定的时间内(默认为 900 秒)未收到请求的环境。 - 达到最长生命周期(
maxLifetime,默认为 8 小时)。
空闲环境在被回收之前仍会占用 maxVms 配额,即使它们没有处理流量。这是意外出现 maxVms 错误的首要原因。
根据工作负载特点选择超时
生产环境不要使用默认值。应根据工作负载实际使用会话的方式选择合适的值:
| 工作负载 | idleRuntimeSessionTimeout | maxLifetime | 原因 |
|---|---|---|---|
| 交互式聊天 / 支持 Agent | 600–900s(默认) | 3600–7200s | 用户会暂停阅读或思考。用户离开后应快速回收。 |
| 无后续请求的请求/响应 API | 60–120s | 1800s | 每次调用都独立完成,因此应尽快释放 VM。 |
| 批处理,每项作业使用一个会话 | 120s | 与作业时长相符,并留出缓冲 | 批次中各项任务之间的空闲间隔很短;应在作业之间积极回收。 |
后台 / 长时间运行的任务(使用 add_async_task) | 120–300s | 最长 28800s(8h) | 异步任务 API 会在受跟踪的工作期间保持 VM 运行;空闲超时适用于任务之间。 |
权衡一览:
- 较短的空闲超时 =
maxVms下有更多余量,成本更低。风险: 会话中途被回收,导致下一轮需要冷启动。 - 较长的空闲超时 = 会话保持预热,延迟更低。风险: 空闲 VM 会占用配额;突发流量时可能出现
maxVms错误。 - 较短的最长生命周期 = 可预测地回收,可限制内存泄漏 / 过时状态。风险: 活跃的长会话可能在流程中途被终止。
- 较长的最长生命周期 = 会话保持稳定,可大幅节省预热状态的开销。风险: 状态漂移、内存中的状态过时,且更难逐步发布。
最佳实践
工作完成后调用 StopRuntimeSession。 如果 Agent 已完成任务,且预计该会话不会再收到请求,请主动停止会话。这样可以立即释放环境,而不是等待空闲超时。
# After your invocation logic completes and you know the session is done:
client.stop_runtime_session(
agentRuntimeArn=runtime_arn,
runtimeSessionId=session_id,
)
为相关工作复用会话 ID。 每个 HTTP 请求都使用新的会话 ID,就意味着每个 HTTP 请求都会创建新环境。对于多轮对话、批处理作业或面向用户的交互,每个对话 / 批次 / 用户交互使用一个会话 ID,并将所有相关请求路由到该 ID。
根据工作负载调整 idleRuntimeSessionTimeout。 默认值 900 秒适用于预期会快速收到后续请求的交互式工作负载。对于会话生命周期较短的请求/响应工作负载,应调低该值。
编辑 agentcore/agentcore.json 中运行时对应的条目:
{
"runtimes": [
{
"name": "MyAgent",
"lifecycleConfiguration": {
"idleRuntimeSessionTimeout": 120,
"maxLifetime": 3600
}
}
]
}
然后运行 agentcore deploy 以应用更改。CLI 和 CDK 会为你处理底层的 UpdateAgentRuntime 调用。
如果你更倾向于使用 CLI,agentcore add agent ... --idle-timeout 120 --max-lifetime 3600 会将相同字段写入 agentcore.json。该文件是唯一可信来源,其中的每个字段都可通过文件顶部的 $schema URL(https://schema.agentcore.aws.dev/v1/agentcore.json)获得 IDE 自动补全。
超时越短 = VM 回收越快 = maxVms 下有更多余量。超时过短 = 环境会在会话中途被回收,导致下一轮需要冷启动。
不要同时传入 runtimeSessionId 和 mcpSessionId。 对于 MCP Agent,只使用其中一个。同时传入两者可能会将两个独立的 VM 绑定到同一个逻辑会话。
诊断 maxVms 问题
如果遇到 ServiceQuotaExceededException: maxVms limit exceeded,请不要先申请提高配额。CloudWatch 的并发会话指标不等同于运行中的 VM 数量——环境在被回收之前,即使处于空闲状态也会占用配额。
请按以下顺序排查:
- 在每个逻辑请求完成后调用
StopRuntimeSession - 检查会话 ID 的生成方式——是否为本应复用 ID 的每个请求都创建了新 ID?
- 如果会话生命周期较短,请调低
idleRuntimeSessionTimeout - 只有在完成以上所有步骤后仍达到上限,才申请提高配额
有关提高配额的流程(通过 Service Quotas 控制台)和理由模板,请参阅 references/limits.md。
长时间运行的后台任务
如果 Agent 启动的工作会在 /invocations 响应返回后继续运行——例如后台处理、异步作业或长工具链——仅采用发后即忘模式是不够的。即使后台任务仍在运行,环境也可能在 idleRuntimeSessionTimeout 时被回收,因为运行时会在发送调用响应后将会话视为闲置。
使用 SDK 的异步任务 API 表示“仍在忙碌”
bedrock-agentcore SDK 提供了任务注册功能,可在受跟踪的工作运行期间保持环境存活。在 Python 中:
from bedrock_agentcore.runtime import BedrockAgentCoreApp
app = BedrockAgentCoreApp()
@app.entrypoint
def invoke(payload, context):
# Register the task BEFORE starting it
task_id = app.add_async_task("background_work")
# Kick off the work (in a thread, asyncio, etc.)
start_background_work(task_id, payload)
# Return the invocation response — the task is still tracked
return {"status": "processing", "taskId": task_id}
def start_background_work(task_id, payload):
try:
# Long-running work here
do_the_work(payload)
finally:
# Mark the task complete when done — this releases the "busy" signal
app.complete_async_task(task_id)
if __name__ == "__main__":
app.run()
只要至少有一个已注册任务处于活动状态,运行时就会认为环境处于忙碌状态,不会在 idleRuntimeSessionTimeout 时回收环境。maxLifetime(默认值为 8 小时)仍是硬性上限。
请查阅 bedrock-agentcore SDK 对应语言的文档,了解等效 API——TypeScript SDK 也有类似模式。
无法使用异步任务 API 时的替代方案
- 将
idleRuntimeSessionTimeout调高至与预期任务时长相匹配。 如果你知道任务最长运行 10 分钟,可将超时设为 12 分钟。确保远低于maxLifetime。 - 保持 HTTP 连接打开,使用流式响应并定期发送心跳事件。适用于希望调用方等待结果而不是轮询的情况。请参阅
agents-debug/SKILL.md中的 SSE 保活模式(“Connection drops mid-stream”一节)。 - 将长时间运行的工作拆分为同一会话上的多次调用。 每次调用都会重置闲置计时器。
配额和限制
如果你遇到限流、ServiceQuotaExceededException 或其他与配额相关的错误——或者即将发布,希望确保配额不会造成阻碍——请加载 references/limits.md。
该参考资料涵盖:
- 各错误对应的配额
- 请求提高配额前可尝试的缓解措施(至关重要——大多数“配额”错误实际上是会话生命周期问题)
- 如何通过 Service Quotas 控制台请求提高配额(需要直接提交 Support 工单的情况很少见)
- 可直接复制粘贴的说明模板,包含审核者批准请求所需的全部信息
生产环境检查清单摘要
生成一份针对该项目的检查清单:
Production Readiness Checklist for <AgentName>
IAM
[ ] Execution role Bedrock access scoped to specific model ARNs
[ ] ECR access scoped to specific repository
[ ] Trust policy scoped to your account ID
Authentication
[ ] Inbound auth is AWS_IAM or CUSTOM_JWT (not NONE)
[ ] If CUSTOM_JWT: discovery URL, audience, and client IDs configured
Shell Access (if using InvokeAgentRuntimeCommand)
[ ] InvokeAgentRuntimeCommand permission granted only to identities that need it
[ ] Separate IAM policy from InvokeAgentRuntime policy
[ ] CloudTrail / EventBridge alert configured for InvokeAgentRuntimeCommand calls
[ ] If commands constructed from user input: shell injection validation implemented
Code quality
[ ] Error handling wraps all agent logic
[ ] Input validation on payload fields (type, length, format)
[ ] No secrets hardcoded in agent code
[ ] Credentials registered via agentcore add credential
Observability
[ ] X-Ray tracing enabled (auto-configured)
[ ] CloudWatch log retention policy set
[ ] Eval baseline established
Performance
[ ] Agent initialization time measured and optimized
[ ] Deployment package size under 200 MB (target under 100 MB)
[ ] Dependencies audited — no unused packages
[ ] Heavy initialization deferred to request time
[ ] Session reuse strategy chosen for multi-turn / batch workloads
[ ] `StopRuntimeSession` called after work completes where applicable
[ ] `idleRuntimeSessionTimeout` tuned to workload (default 900s)
[ ] For long-running background tasks: `add_async_task` / `complete_async_task` used
Resources
[ ] Memory strategies appropriate for use case (if using memory)
[ ] Gateway auth configured (if using gateway)
[ ] Policy engine attached (if restricting tool access)
Testing
[ ] Agent tested with production-representative inputs
[ ] Error cases tested (tool failures, model errors)
[ ] Memory cross-session tested (if using LTM)
输出
- 包含项目具体发现的检查清单
- 用于修复发现问题的具体命令
- 针对检测到的模型和资源推荐的 IAM 策略