边界判断跨 Agent 重复、与领域无关、需要一致治理的机制进入 Harness;目标、完成语义、业务规则和补偿决策留在具体 Agent 或领域服务。

Harness 是模型能力的工程外骨骼

Harness 不是另一个“超级 Agent”,也不是 UI 框架。它提供 Runner 与 Loop、Model Adapter、Tool Registry/Executor、Context 与状态、Policy/Approval、Tracing/Eval Hook 和人工中断。具体 Agent 则定义任务目标、领域工具、业务完成条件和风险语义。

Harness 的责任分层:业务决策通过稳定端口使用共性能力
Harness CoreRun/Step 状态机、预算、调度、事件与终止。
Ports & Adapters模型、Tool、Store、Policy、Approval、Telemetry。
基础设施队列、数据库、密钥、工作区、网络和观测后端。

OpenAI Agents SDK 将 agent loop、tools、handoffs、guardrails、sessions、human-in-the-loop 和 tracing 作为共性能力;Anthropic 的工程指南也提醒框架抽象可能遮蔽底层 Prompt 与响应。结论不是“必须自研”,而是任何采用都要知道哪些控制被框架拥有、哪些语义会在适配中丢失。

三种常见 Harness 形态

进程内 SDK/Library

Runner 与业务服务同进程,延迟低、调试直接、可使用原生语言类型。代价是语言与发布耦合,策略和观测容易由各团队分叉。适合单团队或尚在验证共性边界的阶段。

独立 Agent Runtime Service

通过 API 接收 Run,统一模型、Tool 执行、状态和观测。它降低多语言接入成本,却引入网络、排队、租户隔离和跨服务 Debug;若把领域 Prompt 与业务编排都塞入中心服务,会形成新的单体。

控制面 + 数据面

控制面管理 Registry、策略、配置、评测和版本,数据面按数据域与延迟要求运行。适合多业务线和强隔离场景,但需要配置分发、兼容协议、租户治理和组织 Owner,不能在需求尚未稳定时一步到位。

形态选择不是成熟度竞赛
变量LibraryRuntime Service控制面 + 数据面
团队/语言少、相对统一多语言接入多业务域、多执行环境
治理一致性靠包版本集中执行集中策略、分布执行
主要风险版本碎片中心瓶颈与领域侵入平台复杂度和协议演进

稳定接口围绕责任边界

不要追求“所有模型一个完全相同接口”。稳定层应定义业务需要的最小语义,并通过能力探测保留差异:结构化输出、并行 Tool、reasoning、缓存、流事件和取消不一定跨 Provider 等价。

interface ModelAdapter {
  capabilities(): Promise<ModelCapabilities>;
  stream(request: CanonicalModelRequest): AsyncIterable<ModelEvent>;
}

interface ToolExecutor {
  authorize(call: ToolCall, principal: Principal): Promise<PolicyDecision>;
  execute(call: ToolCall, attempt: AttemptContext): Promise<ToolReceipt>;
}

interface RunStore {
  append(expectedVersion: number, events: RunEvent[]): Promise<number>;
  load(runId: string): Promise<RunSnapshot>;
}

interface ApprovalPort {
  request(decision: BoundActionPreview): Promise<ApprovalRef>;
}

接口中的核心对象应可版本化、可序列化并带稳定 ID。异常也要规范化但保留 Provider 原因:统一成 rate_limited 有助于策略,原始状态码、request ID 和重试提示仍要进入受控 Trace。

Hook 是观测和扩展点,不是隐式业务流程

Run/Step/Model/Tool 前后事件可用于 Trace、指标、成本计量、Eval 抽样和审计。OpenAI Agents SDK 的 Agent 与 Runner 生命周期事件就是一种实现。但 Hook 的顺序、并发、超时和失败语义必须明确。

关键状态变更不能依赖 best-effort Hook:例如 Tool 成功回执必须与状态提交形成可靠协议,不能寄希望于 afterTool 异步写库。插件也不能默认获得主进程全部密钥、上下文和网络权限。

诊断原则Hook 可以观察“发生了什么”,不能悄悄决定“业务下一步做什么”。否则控制流散落在回调,Trace 看得到表象却找不到真正 Owner。

全局、租户、Agent 和 Run 配置分层

建议优先级从低到高为平台默认、环境、租户、Agent 版本、Run 覆盖,但安全底线、数据驻留和最大权限不可被下层覆盖。每个 Run 固化有效配置快照与来源,动态变更默认只影响新 Run;在途 Run 是否迁移需要显式策略。

配置快照应记录模型别名解析结果、Prompt 版本、Tool Schema、预算、Feature Flag 和策略版本,秘密只记录引用或指纹。没有快照的 Trace 无法解释“同样输入为何昨天与今天路径不同”。

Harness 失败的常见原因

抽象失败与反向设计
失败后果反向措施
过早提炼最小公分母Provider 优势与错误语义丢失Canonical Core + capability extension
把业务逻辑放进通用回调Owner 不清、升级回归困难领域服务/Agent 持有业务状态机
Tool/Prompt 只有配置没有版本历史 Run 无法复现不可变版本、快照、兼容期
平台强制唯一 Golden Path团队绕过平台形成 Shadow Runtime逃逸口有边界,并用采用证据迭代

框架升级前应以行为契约回归,而不是只看编译通过。模型消息顺序、Tool 结果回注、终止判定、取消传播和错误分类的细小变化,都可能改变 Agent 行为。

用代表性任务验证 Harness

最小基准应覆盖单 Agent 多 Tool、结构化输出、审批等待、长任务恢复、Subagent、流式取消和 Provider 替换。故障注入包括超时、重复回执、限流、状态冲突、Hook 失败和旧版本 Run 恢复。

契约测试检查的是语义不变量:同一个 Tool call ID 只提交一次业务效果;取消能传播到尚未开始的节点;策略拒绝不能被重试变成允许;Trace 的父子关系完整;恢复后预算和配置版本不丢失。Provider 替换只在任务成功和关键语义保持时才算成功。

平台采用还要看开发者证据:从空项目到首个可观察 Agent 的时间、逃逸 API 使用率、升级失败率、排障平均时间和各团队重复实现下降。P8 级平台决策不是组件图,而是一份明确 Owner、迁移批次、兼容承诺、SLO 与停用条件的 RFC。

主动提取:为什么“所有 Provider 都能返回 text”不是一个充分的 Model Adapter?
Agent 依赖流事件、Tool call、结构化输出、取消、错误和能力探测等语义;只统一 text 会吞掉控制流和恢复信息,导致上层误判。
架构判断:何时应该从 SDK 演进为 Runtime Service?
当多个团队/语言重复实现执行与治理、策略分叉已产生风险,且集中服务的网络、隔离和运营成本有明确 Owner 与收益证据时。不是因为“平台化更高级”。

资料与事实边界

以下以官方文档、标准、论文和原始工程资料为主。厂商 API、价格、限额与模型能力会变化,落地时仍需按目标版本做能力探测和回归。

  1. Anthropic:Building Effective AI Agents — 框架抽象的收益、遮蔽风险和保持简单的工程建议
  2. OpenAI Agents SDK for TypeScript — Runner、Tool、Handoff、Guardrail、Session 和 Tracing 的当前官方能力
  3. OpenAI Agents SDK:Running agents — Agent loop、RunState、终止和运行配置的官方语义
  4. OpenAI Agents SDK:Tracing — Run、Agent、Generation、Tool 与 Handoff Trace 的官方实现边界