写 Agent 不用再写循环:AWS AgentCore harness 把编排层做成了配置
写 Agent 不用再写循环:AWS AgentCore harness 把编排层做成了配置
Agent 框架又多了一个,这次 AWS 直接把"框架"这一层收编了。
每个 Agent 都有一个编排层:一个循环,调模型、选工具、把结果塞回上下文、管理会话状态、处理失败。这个循环本身不难写,Strands、LangGraph、Claude Agent SDK 都能干。真正让团队掉头发的是循环底下的东西——生产环境要的沙箱、安全工具连接、文件系统、记忆、身份、可观测性,一样都不能少。本地跑通只要一下午,上线服务多个用户的那一刻,并发、隔离、状态、扩缩容全冒出来。
AWS Bedrock AgentCore harness 的思路是:这些活儿别自己干了。你声明 Agent 是什么(模型、工具、Skills、指令),AgentCore 负责把它变成一个真的在跑的 Agent——环境、算力、记忆、身份、网络、可观测性全托管。换个模型或加个工具是改配置,不是改代码重部署。底层编排循环由 AWS 开源的 Strands Agents 驱动,harness 本身已 GA,不单独收费,只按用到的 AgentCore 能力计费。
这篇把我读官方文档拆出来的东西整理给你:它到底管了什么、怎么上手、哪些设计值得学、以及什么时候你该选 Runtime 而不是它。
本文提纲
- harness 是什么:Agent 代码之外的另一半
- 五分钟上手:一条 CLI 到流式响应
- 配置驱动的编排:默认值加调用时覆盖
- 工具、Skills 与生命周期钩子
- harness vs Runtime:同一道题的两种答案
- 边界与冷静判断
一、harness 是什么:Agent 代码之外的另一半
"harness"这个词在 Claude Code、Codex 这类产品走红之后被讲得越来越多,指的是包住模型的整套运行系统:编排循环加底下的基础设施。AgentCore 文档把它拆成两层——循环本身(调模型、选工具、回填结果、管上下文、处理失败),和生产化需要的地基(沙箱、工具连接、文件系统、记忆、身份、可观测性)。
AgentCore harness 做的事,是把这两层全部托管:
graph LR
A["Your config: model, tools, skills, memory"] --> B["AgentCore harness: managed agent loop"]
B --> C["microVM per session: filesystem, shell"]
B --> D["Tools: Gateway, MCP, Browser, Code Interpreter"]
B --> E["Memory: short-term and long-term"]
C --> F["Event stream: text, toolUse, hookEvent"]
D --> F
E --> F
F --> G["Your app consumes the stream"]三个设计值得单独说:
每个会话一个隔离 microVM
Agent 有自己的文件系统和 shell,可以写代码、执行、改文件。会话默认有状态,短期和长期记忆、文件都能跨会话保留——哪怕底层 microVM 过期销毁、被新实例顶替,记忆和文件还在。
模型随便换,会话不丢
Amazon Bedrock、OpenAI、Google Gemini、任何 LiteLLM 兼容的模型都能接,而且可以在同一个会话的不同轮次之间切换供应商,上下文照常延续。规划用一个模型、执行用另一个,或者拿两个模型做性价比对比,都不用重建对话。
配置即部署
环境变量、执行上限(maxIterations、timeoutSeconds、maxTokens)、VPC 网络、入站 IAM/OAuth 认证、出站身份的 token vault,全是 harness 配置字段。CloudTrail 里 harness 操作记录在 AWS::BedrockAgentCore::Runtime 下面——它跑在 Runtime 之上,这层关系后面细说。
二、五分钟上手:一条 CLI 到流式响应
两条路:AgentCore CLI(Node.js 20+)或 boto3 SDK(Python 3.10+)。CLI 最快:
npm install -g @aws/agentcore
agentcore create --name myresearchagent --model-provider bedrock
agentcore deploy
agentcore invoke --harness myresearchagent \
--session-id "$(uuidgen)" \
"Research three tropical vacation options under $3k, within five hours of NYC."响应直接流式打到终端。复用同一个 --session-id,就在同一个环境里继续对话。本地开发用 agentcore dev:它先把 harness 资源(IAM 角色、harness、memory)部署到 AWS,然后起一个本地 dev server,在浏览器里打开 agent inspector,可以对话、看 trace、改配置。
走 SDK 的话,核心是三个 API 调用:
aws bedrock-agentcore-control create-harness \
--harness-name "MyHarness" \
--execution-role-arn "arn:aws:iam::123456789012:role/MyHarnessRole"轮询 get-harness 到 READY,拿到 ARN,然后 invoke_harness:
response = client.invoke_harness(
harnessArn="arn:aws:bedrock-agentcore:us-west-2:123456789012:harness/MyHarness-XyZ123",
runtimeSessionId="1234abcd-12ab-34cd-56ef-1234567890ab", # 至少 33 字符
messages=[{"role": "user", "content": [{"text": "Research three tropical vacation options under $3k."}]}],
)
for event in response["stream"]:
if "contentBlockDelta" in event:
delta = event["contentBlockDelta"].get("delta", {})
if "text" in delta:
print(delta["text"], end="", flush=True)不指定模型时,harness 默认用 Amazon Bedrock 上的 Anthropic Claude Sonnet 4.6(global.anthropic.claude-sonnet-4-6)。流式事件里有几个 stopReason 值值得记住:tool_use、tool_result、max_iterations_exceeded、timeout_exceeded、hook_stopped——最后一个来自生命周期钩子,后面讲。
三、配置驱动的编排:默认值加调用时覆盖
harness 的配置模型是一句话:创建时定默认值,调用时做覆盖。model、systemPrompt、tools、maxIterations、maxTokens、timeoutSeconds、skills、allowedTools、actorId 全部可以在单次 InvokeHarness 里临时覆盖,harness 资源本身不动。按官方文档的说法,一次重新部署的工夫,你能测 N 组模型/prompt/工具组合。
最有意思的是模型热切换。同一个会话里,三轮流式调用可以分别走不同供应商,上下文全程携带:
# Turn 1: Bedrock Converse API, Claude
model={"bedrockModelConfig": {"modelId": "us.anthropic.claude-sonnet-4-5-20250514-v1:0"}}
# Turn 2: Bedrock Mantle, OpenAI Responses 格式
model={"bedrockModelConfig": {"modelId": "openai.gpt-4o", "apiFormat": "responses"}}
# Turn 3: OpenAI 模型,走 Bedrock Mantle 端点,不需要 OpenAI API key
model={"openAiModelConfig": {"modelId": "gpt-5.4", "apiFormat": "responses", "endpoint": {"bedrockMantle": {}}}}Turn 3 那种写法值得展开说:endpoint: bedrockMantle 让你通过 Amazon Bedrock Mantle 端点调 OpenAI 模型,用执行角色的凭证,不碰 OpenAI API key。要走自己的网关或自托管端点,配 apiKeyArn(从 AgentCore Identity 的 token vault 引用)加 apiBase,密钥在调用时才被拉取,Agent 代码从头到尾看不到原始凭证。
API 格式也是可选的:Bedrock 模型默认走 converse_stream,也可以切到 OpenAI 兼容的 responses 或 chat_completions(由 bedrock-mantle 端点服务);OpenAI 配置支持 responses 和 chat_completions。换句话说,你可以让 Claude 模型说 OpenAI 的"方言",应用侧只用对接一种协议。
四、工具、Skills 与生命周期钩子
工具是声明的,不是代码。 五种类型加两个内置工具:
| 工具 | 说明 |
|---|---|
| remote MCP | 任意远程 MCP 端点,URL 直连,认证头支持 ${arn:...} 引用 token vault |
| AgentCore Gateway | 托管工具面,带出入站认证、访问控制、策略执行,引用 gateway ARN 即接入全部工具 |
| AgentCore Browser | 托管浏览器自动化 |
| AgentCore Code Interpreter | 沙箱里跑 Python/JavaScript/TypeScript |
| inline function | 在你的客户端执行,harness 暂停等结果——人在环审批就靠它 |
| shell(内置) | bash,每个会话默认可用 |
| file_operations(内置) | 查看、创建、编辑文件 |
allowedTools 控制模型能用哪些工具,支持 glob 和 @server/tool 语法(比如 "@git/git_status" 只放行某个 MCP 服务器的特定工具)。这里有个容易忽略的成本细节:内置 shell 和 file_operations 的工具定义加起来约 900 input tokens,每个模型请求都会带一遍,一次调用可能发生多次。工具挂得越多,底噪越高,按需用 allowedTools 裁剪是实打实的省钱手段。
Skills 走渐进式披露。 每个 Skill 是符合 AgentSkills.io 标准的 markdown 加脚本包,元数据约 100 tokens 注入 system prompt,完整指令按需加载。四个来源可以混搭:AWS 官方技能目录(core-skills/* 这类 glob 直接开启)、Git 仓库(支持 monorepo 子目录 sparse checkout,私库用 token vault 里的 PAT)、S3 桶(单 skill 上限 1GB)、文件系统路径(烤进容器镜像)。Skill 在会话首次调用时拉取一次,VM 过期重建后自动重新拉取保证新鲜度。拉取失败会让整个调用失败,绝不静默跳过——这个错误处理哲学我喜欢。
生命周期钩子是治理的抓手。 四个事件点(before_invocation、before_tool_call、after_tool_call、after_invocation),三种目标(Lambda、SNS、EventBridge)。只有 Lambda 能改变 Agent 循环行为:返回 deny 可以拦下整个调用、跳过某个工具调用、或在工具执行后终止调用。SNS 和 EventBridge 只做通知,不阻塞循环。每个 harness 最多 20 个钩子,Lambda 超时 1 到 900 秒,failureMode 决定钩子挂了算 allow 还是 deny(默认 deny,安全取向)。钩子上下文上限 64 KiB,超了会打截断标记,文档明确提醒:after_tool_call 对 inline function 的确认只说明 harness 收到了客户端回传的结果,不代表客户端真的执行了外部操作——这种把安全假设写在明面上的措辞,比大多数文档诚实。
五、harness vs Runtime:同一道题的两种答案
这是选型时最该搞清楚的问题。两者解决同一问题的不同部分:
| AgentCore harness | AgentCore Runtime | |
|---|---|---|
| 本质 | 托管的编排循环(Strands 驱动) | 无服务器托管环境 |
| 你提供 | 配置:模型、prompt、工具、记忆、上限 | 代码:任意框架写的 Agent,打成 ARM64 容器推 ECR |
| 编排循环 | AgentCore 提供 | 你自己写 |
| 换模型/加工具 | 改配置,不用重新部署 | 改代码,重新构建部署 |
| 自定义容器 | 支持(配置加代码混合) | 支持 |
| 框架选择 | 不行,就是 Strands 那套循环 | 任意框架或无框架 |
| 双向流式、图/工作流模式 | 不支持 | 自己实现 |
| 记忆、网关、浏览器、代码解释器 | 配置即用 | SDK 里自己调 |
| 计费 | 无单独 harness 费用,按底层能力计费 | 按 Runtime 计费 |
选型判断其实就一句:编排循环里没有你的秘密,就用 harness;循环里有你的核心逻辑(自定义图结构、特殊调度、双向流式),用 Runtime 自己写。两者不互斥——harness 跑在 Runtime 上,导出的 Strands 代码也能跑在 Runtime 上,迁移路径是留了后门的。
六、边界与冷静判断
先说它做不到的。harness 的编排循环是 Strands 的,你没法换框架,也写不了循环内的自定义 hook(Lambda 钩子在循环外围,管拦截不管循环内部逻辑)。双向流式、graph/工作流这类非 Agent-loop 模式不支持,需要就回 Runtime。inline function 要写客户端代码处理回传,属于配置加代码的混合模式。
平台层面也有几个注意点。Web 搜索工具目前只在 us-east-1 可用,得通过 Gateway 挂 Web Search connector。allowedTools 只约束 InvokeHarness 里 LLM 的工具选择,管不住 InvokeAgentRuntimeCommand——那是另一个直接执行 shell 命令的 API,有独立 IAM action,不想让人绕过 LLM 直接执行命令,就别把这个权限授出去。第三方模型配置里的 additionalParams 会原样透传给供应商,文档专门警告可能影响端点路由和凭证处理,如果你的应用把调用方传入的配置转发给 InvokeHarness,得自己校验。
锁定问题值得想一下,但没到劝退的程度。harness 的配置格式是 AWS 自家的,不过官方提供了"导出为 Strands 代码"的出口(Claude Agent SDK 支持在路上),Strands 又是开源框架——真要搬家,循环逻辑可以带走,托管的那部分基础设施(microVM、记忆、身份、可观测性)带不走,那本来也是你买它的原因。
我的整体判断:如果你们的 Agent 需求落在"标准 Agent loop 加工具加记忆"的框框里,harness 把最脏的活儿(隔离、状态、凭证、trace)收走了,剩下的都是业务决策,这买卖划算。需求越怪,harness 的抽象漏得越多,Runtime 加自选框架反而是更短的路。拿不准的话,先 agentcore create 起一个跑跑看,成本就是几次模型调用。
参考文档与链接
- AgentCore harness 官方文档 — 概念总览、GA 状态、计费说明
- Get started — CLI/boto3 上手、流式事件与 stopReason 全表
- Models and instructions — 模型热切换、API 格式、Bedrock Mantle
- Tools — 五类工具、allowedTools 语法、900 token 底噪
- Lifecycle hooks — 四类事件、Lambda/SNS/EventBridge 目标、deny 语义
- Skills — 四种来源、渐进式披露、错误处理表
- harness vs. Runtime — 逐特性对比表
- AgentCore 定价 — 无单独 harness 费用,按底层能力计费
- Strands Agents — harness 底层的开源编排框架
- AgentCore CLI(GitHub) — npm 包
@aws/agentcore - AWS Agent Toolkit Skills — 官方技能目录源码
你在用什么搭 Agent 的生产环境?评论区聊聊你的选型。觉得有用就点个赞,让更多人看到。
作者: itech001
来源: 公众号:AI人工智能时代(the-ai-era)
网站: https://www.theaiera.top/
关注每日最新AI新闻和技术博客,主页有更多的文章的AI 技术参考:https://www.theaiera.top
本文首发于 AI人工智能时代,转载请注明出处。