Agent Harness 是把模型输出转化为受约束、可观测工作的运行时控制层。它不会让模型天然拥有权威,而是决定模型能看到什么上下文、哪些动作提议有效、使用谁的凭证、如何执行副作用、提交什么状态,以及失败后能否继续。

本文讨论 AI 智能体运行时基础设施,不涉及电气线束、测试夹具硬件或机械工程中的 Harness。

本文只负责架构与数据流。相邻搜索意图由以下页面承接:

直接回答

不存在一个标准化的 Agent Harness 产品,也没有全行业强制一致的组件清单。团队可以用应用代码、Agent SDK、状态机、队列、策略服务、隔离 Worker 和事件管道组合实现。

真正稳定的是责任边界:

模型负责提议;Harness 负责授权、执行、记录与恢复。

只有 Prompt 或 Tool Calling API,不等于生产级 Harness。Harness 必须保留概率性提议与权威副作用之间的边界。

Agent Harness、Agent Loop、Runtime 与工作流引擎的边界

不同厂商会混用这些术语。设计系统时应定义内部契约,不能假设名称存在统一含义。

概念 主要职责 谁决定下一步 它不能证明什么
模型 根据输入上下文生成文本、结构化输出或工具提议 模型推理 权限、执行、持久化或正确性
Agent Loop 重复模型决策、环境观察与动作,直至终态 通常由模型在运行时限制内动态决定 持久状态、隔离或副作用安全
工作流引擎 执行预定义 DAG、状态机或调度计划 应用代码或声明式图 模型选择的动作已经获得授权
Agent Runtime 承载并调度一个或多个 Agent 会话 Runtime 加已配置的循环或工作流 某种具体策略、证据或恢复设计
Agent Harness 中介一次运行的上下文、能力、策略、状态、副作用、证据与恢复 模型提议,确定性控制决定能否执行 绝对安全或模型推理一定正确

Anthropic 的工程文档提供了相近的区分:Workflow 沿预定义代码路径执行,Agent 则动态决定过程与工具使用。两者都可以运行在 Harness 内;模型获得的自主权越大,Harness 契约就越需要显式化。

四个架构平面

将职责划分为四个平面,比背诵固定的“六层架构”更利于落地。

1. 控制平面

控制平面拥有不能下放给模型文本的决策:

  • 身份、租户、目的与资源上下文
  • 能力白名单与工具 Schema 版本
  • 策略评估与审批要求
  • 步数、墙钟时间、Token、费用、重试与字节预算
  • 取消、终止与升级规则

模型可以建议执行某个动作,但不能自行增加能力、扩大凭证范围或把自己的动作标记为已审批。

2. 执行平面

执行平面把已授权提议转换为有边界的操作:

  • 模型与 Provider Adapter
  • 工具注册表和参数校验
  • 按负载风险选择沙箱或隔离 Worker
  • 单工具超时、并发限制与输出上限
  • 稳定操作 ID 与下游幂等键

沙箱可以收窄故障影响范围,但不能替代授权。一个与宿主机隔离的进程,仍可能滥用 API 凭证或发出外部可见请求。

3. 状态平面

状态平面是“运行已知什么、系统已提交什么”的事实源:

  • Run、Step、Tool Call 与 Approval 标识
  • 使用乐观并发控制的版本化运行状态
  • 消息、产物与结果引用
  • 检查点及等待中的人工决策
  • 预算计数器与终态
  • 副作用状态:not_startedin_flightcommittedfailedunknown

线程检查点与长期记忆是两个不同的数据产品。例如 LangGraph 把线程级图状态 Checkpointer 与跨线程应用数据 Store 分开。混用两者,会让保留、删除、授权和恢复边界难以定义。

4. 证据平面

证据平面解释一次运行,但不把模型的私有推理当成事实:

  • 结构化生命周期事件与分布式 Trace
  • 策略和审批决策
  • 工具请求元数据与受限结果
  • 状态转换、耗时、错误与预算
  • 业务结果与评测标签

OpenTelemetry 的 GenAI 语义约定仍在演进,可以用于映射跨厂商的 Span、Metric 和 Event。应用自身仍应维护稳定的事件契约,再按当前约定输出遥测数据。

核心组件与责任归属

四个平面通过以下组件落地:

组件 负责内容 关键不变量
请求网关 认证、租户、Request ID、输入限制 先解析身份,再选择能力
运行协调器 状态机、租约、预算、取消 每次状态更新只有一个版本化转换胜出
上下文构建器 指令、消息、检索数据、产物引用 不可信内容保持为数据,不能上浮为策略
模型网关 Provider 请求、结构化响应、模型元数据 模型输出只是提议,不是授权
工具注册表 版本化 Schema、风险类别、Executor 绑定 只能调用已注册能力
策略与审批服务 Allow、Deny、Redact 或 Suspend 审批绑定主体、参数、资源与过期时间
工具执行器 隔离、超时、操作键、结果分类 重试不能悄悄复制已提交副作用
状态与检查点存储 版本化快照、决策、副作用 Journal 从已提交证据恢复,而不是依赖模型记忆
事件与评测 Sink 脱敏事件、Trace、结果、测试 Fixture 遥测可诊断,但不能变成敏感信息仓库

这些组件可以同进程部署,也可以拆成独立服务。分布式部署本身不会产生正确性,只会增加网络失败和一致性决策,仍需要契约约束。

端到端数据流

sequenceDiagram participant C as Client participant H as Harness 控制平面 participant S as 状态存储 participant M as 模型网关 participant P as 策略与审批 participant X as 工具执行器 participant E as 事件管道 C->>H: 请求和已认证身份 H->>S: 创建 stateVersion = 1 的运行 H->>M: 受限上下文和允许的工具 Schema M-->>H: 最终响应或工具提议 H->>H: 校验 Schema、预算和当前状态 H->>P: 评估主体、资源、目的与副作用 alt 需要审批 P-->>H: 返回 Approval ID 并暂停 H->>S: 提交等待审批的检查点 else 允许执行 P-->>H: 返回带作用域的 Allow 决策 H->>X: 传入 Call ID 和操作键执行 X-->>H: 返回结果和副作用状态 H->>S: 比较版本并提交下一状态 else 拒绝执行 P-->>H: 返回 Deny 和原因码 H->>S: 提交拒绝或终态 end H->>E: 发送脱敏生命周期事件 H-->>C: 流式返回进度、暂停或最终结果

最重要的边界位于提议与执行之间。Schema 校验回答“数据格式是否正确”;策略回答“这个主体能否因这个目的,对这个资源执行该操作”;审批回答“指定审批人是否授权了这一次具体副作用”。三者不能合并。

版本化运行记录

一次运行应显式表达并发、审批和副作用。下面是应用级示例,不是通用行业标准:

json
{
  "runId": "run_01J...",
  "stateVersion": 12,
  "status": "waiting_for_tool",
  "stepId": "step_07",
  "actor": {
    "tenantId": "tenant_acme",
    "principalId": "user_42",
    "purpose": "resolve_support_case"
  },
  "proposal": {
    "model": "provider/model-version",
    "tool": "create_support_ticket",
    "toolVersion": "3",
    "callId": "call_09"
  },
  "policy": {
    "decision": "allow",
    "approvalId": null
  },
  "effect": {
    "operationKey": "run_01J:call_09:create_support_ticket:3",
    "status": "in_flight"
  },
  "budgets": {
    "stepsUsed": 7,
    "stepsLimit": 12
  }
}

不要单独用可变 Prompt、时间戳或参数哈希充当操作身份。应在分发前生成稳定的语义操作 ID 并持久化。下游 API 支持幂等时,传递该键并保存资源 ID;不支持时,必须定义状态查询或对账路径。

用状态转换替代无界 while 循环

五行 while 循环适合解释 Tool Calling,却会隐藏生产契约。运行生命周期应显式建模:

text
created
  -> running
  -> waiting_for_approval
  -> waiting_for_tool
  -> running
  -> completed | failed | cancelled | needs_reconciliation

每个转换都应声明:

  1. 预期状态版本
  2. 触发事件
  3. 策略与预算前置条件
  4. 状态变更
  5. 发出的事件
  6. 外部副作用是否可能已经存在

提交转换时使用 Compare-and-Set 或等价事务。租约可以减少并发执行,但租约会过期、Worker 会崩溃,因此不能替代状态版本。

失败与恢复语义

只有系统能判断副作用是否发生时,重试才是安全动作。

失败位置 对副作用的认知 默认处理
模型在形成提议前失败 无外部副作用 在模型与运行预算内重试
提议未通过 Schema 或策略校验 无已授权副作用 拒绝、要求修正或终止
工具被接收前分发失败 通常无副作用,但需核对传输契约 使用同一操作 ID 有界重试
工具分发后超时 未知 查询操作状态或进入对账,不能盲目重试
工具已提交,但状态写入冲突 副作用可能已经提交 按操作 ID 查询,再提交已知结果
审批过期或被拒绝 无已审批副作用 取消提议或返回规划
运行暂停期间策略发生变化 旧决策可能失效 恢复前重新评估
执行中取消 Worker 取决于工具 尝试协作式取消,并分类最终副作用

unknown 是合法的运行状态。把它折叠为 failed 会造成重复副作用;把它折叠为 completed 会掩盖缺失工作。

信任与授权边界

所有跨边界数据在确定性控制验证前都应视为不可信:

  • 用户、检索与工具内容: 都可能包含 Prompt Injection,应与系统策略和工具定义分离。
  • 模型提议: 校验类型、范围、资源 ID 与业务规则。结构化输出只改善解析,不能证明真实或有权执行。
  • 工具结果: 限制大小、验证 Schema、标记来源,禁止返回文本悄悄修改策略。
  • 凭证: 绑定主体、Audience、Scope 与操作。MCP 安全文档明确警告 Token Passthrough 与 Confused Deputy 风险。
  • 审批: 展示具体资源和副作用,绑定不可变参数,并设置过期时间。
  • 遥测: 导出前脱敏 Secret 与个人信息,Trace 的访问控制和删除策略应与生产状态分别定义。

OWASP 把 Excessive Agency 的根因归为过多功能、过大权限或过度自主。因此,能力收敛必须进入架构:暴露最小工具面,授予最窄凭证,并按影响与可逆性决定是否需要人审。

预算与终止条件

只有 maxSteps 不够。至少独立定义:

  • 墙钟时间
  • 模型请求数与 Token
  • 按风险类别划分的工具调用和重试
  • 并发任务
  • 输入、输出与产物字节数
  • 能可靠取得 Usage 时的费用
  • 审批等待时长

终止必须可确定。已经验证的业务结果、显式拒绝、策略拒绝、取消、预算耗尽、不可恢复错误或需要对账,均可进入终态。“模型声称已完成”只能作为待验证的提议。

应记录和评测什么

记录可观察证据,不记录隐藏思维链:

  • Request、Run、Step、Call、Approval 与 Operation ID
  • 模型、Prompt 模板、工具 Schema、策略和 Executor 版本
  • 每次转换前后的状态版本
  • 提议类别、策略结果、审批结果与副作用状态
  • 可取得时的耗时、重试、Token 与费用
  • 脱敏错误码和受限结果元数据
  • 最终业务结果与确定性检查

具体设计见 Agent 可观测性。发布前测试可参考 Agent Harness 评测指南,其中覆盖场景 Fixture、工具替身、故障注入、轨迹检查和 Judge 辅助评分。

生产准入清单

  • [ ] 选择工具前已经解析认证身份与租户上下文。
  • [ ] 工具 Schema、风险类别和 Executor 版本已经注册。
  • [ ] 模型输出始终按不可信提议进行校验。
  • [ ] 策略与审批在模型之外执行。
  • [ ] 凭证绑定 Audience 与 Scope,不盲目透传 Token。
  • [ ] 运行状态有版本,检查点可以跨 Worker 重启恢复。
  • [ ] 副作用操作使用稳定 ID、幂等机制或对账路径。
  • [ ] 时间、步数、Token、重试、字节、并发与费用限制显式配置。
  • [ ] 取消和未知结果都有文档化状态转换。
  • [ ] 事件结构化、脱敏、受访问控制并限制保留时间。
  • [ ] 测试覆盖重复分发、提交后超时、审批过期、策略变化、重启与取消。
  • [ ] 人员能够检查证据,并恢复或终止暂停的运行。

参考资料

总结

Agent Harness 架构不是更长的 Prompt,也不是某个品牌框架。它是把模型提议与权威副作用分开的运行契约。

可持续的设计必须显式管理身份、策略、状态版本、操作 ID、审批、预算、可观测事件与未知结果。建立这些边界后,团队才能替换模型 Provider 或编排库,而不丢失系统的运行保证。