Tager: Harness

Table of Contents

Tager: Harness

Agent Harness:让模型在真实系统中可靠工作

1. 核心范式:Agent = Model + Harness

一个生产级 Agent 不是"一个更聪明的模型",而是两部分组成的复合系统:


组成

角色类比

职责

本质特征

Model

CPU

阅读上下文、推理、决定下一步动作

无状态、无外设、受上下文窗口限制

Harness

操作系统

上下文加载、工具编排、权限隔离、记忆管理、会话生命周期、持久化、观测、重试、人类介入

确定性代码,是模型之外的全部执行支架

剥离 Harness,模型本身​读不了代码库、跑不了测试、也无法在跨越数天的异步任务里保持记忆连贯。它只能生成 token。

核心循环是 ​ReAct(Reason + Act) :模型读上下文 → 决定动作 → Harness 通过沙箱/API 执行 → 把观察结果(Observation)反哺给模型 → 循环直到任务完成。

工程启示:评估 Agent 能力应当评估「模型 + Harness 配置」整体,而非单看基座模型。一个设计精良的 Harness 能托住弱模型的底线,也能在强模型出现"上下文腐烂"或逻辑幻觉时,通过强制验证循环把它重新锚定回真实任务。

参考架构

控制平面(Harness)执行/计算环境 分离,是安全、耐久、可扩展的基础——避免把高价值凭证直接暴露到模型生成代码的运行环境里,同时支持快照、重放与容器失效后的恢复。

暂时无法在飞书文档外展示此内容

下面分两条主线展开:内部(内稳定) 和 ​外界(外部影响)

2. 内部:内稳定——让模型长时间不跑偏

长时 Agent 的第一个硬问题不是"会不会调用工具",而是"会不会在第十轮后忘掉自己在干什么"。内稳定主要由 Context + State + Retry + 模型原生特性 四块支撑。

2.1 Context 管理与 Compact 压缩

上下文窗口是有限且昂贵的资源。原始工具输出(几千行日志、全量查询结果)会迅速填满窗口,导致信噪比骤降——这就是 ​上下文腐烂(Context Rot) ,会直接削弱推理能力与任务完成率。

生产级 Harness 摒弃"把所有历史无脑追加"的策略,改用动态上下文管理:

  • Compact(压缩) ​:窗口使用接近阈值时,后台智能总结并卸载较旧上下文,把核心发现提炼为高密度结构化记忆块(JSON/YAML),作为持久化提示注入下一轮。直接让 API 抛 context-limit 错误,在生产里不可接受。
  • Tool-Call Offloading(工具输出卸载) :对庞大的工具输出做动态截断,上下文里只保留头部和尾部 token(提供执行状态),完整结果写入(虚拟)文件系统,模型需要时按需读取,保持核心推理流纯净。

关键认知​:上下文窗口只是模型的​工作记忆​,不应承担系统完整状态仓库的角色。仅靠 compaction 不够——没有良好的任务分解和阶段性收尾,模型会留下半完成状态,下一轮只能靠猜。

2.2 目标漂移(Goal Drift)的监测与治理

模型长时间无监督自治时,即便初始提示再清晰,行为与推理也会逐渐偏移。这是多智能体系统崩溃的核心诱因之一。


漂移类型

表现机制

检测指标

治理策略

语义漂移

长上下文中倾向模式匹配,被先前噪声/对抗 token/自身冗余文本带偏,压倒初始系统提示

与目标的余弦相似度衰减、目标遵循度分数下降

情景记忆巩固(定期修剪+总结上下文)、用跨模型验证代替自我评估

协调漂移

多代理协作中共识协议崩溃,或"幻觉放大"——把某代理的错误推断固化为群体记忆

代理间一致性指数

动态路由、向高稳定性锚点代理注入基准示例强制纠偏

任务漂移

被某个挑战性子问题吸引,过度消耗资源,迷失最高层宏观目标

任务完成边界突破、API 调用频率异常峰值

“计划-执行-反思"架构,强制反思器验证当前输出是否服务于顶层目标

治理目标漂移最有效的手段​不是写更长的系统提示,而是把目标拆进确定性结构:

  • 目标重申(Goal Anchoring) :每一步强制重申顶层目标。
  • 生成者与评估者分离:避免模型对自身输出盲目自信。
  • 步数硬限制:在漂移越过临界点前强制阻断并触发修正。
  • 结构化承载​:把目标拆进 ​计划对象、阶段产物、检查点、状态机、可回放日志

2.3 持久化(Persistence)与可恢复执行(Resumeable)

企业级 Agent 正从"即时请求-响应助手"演变为​长期运行的后台软件实体:可能暂停数天等人审批合同,或休眠等待 IT 系统配置硬件。保持连接常开或阻塞工作线程都不可行。

机制:图执行的每个超步(super-step)基于全局唯一标识(如 thread_id)把完整状态快照(checkpoint)写入持久层(如 PostgreSQL)。由此催生两种关键模式:

  • 事件驱动休眠​:执行到 interrupt()​ 或需外部事件时,进程主动释放计算资源并写入状态机;当 Webhook 回调到达或人类提交审批(Command(resume=...)​),Harness 从持久层**水化(hydrate)**先前状态,精确地从中断节点唤醒模型继续执行。
  • 睡眠时间计算(Sleep-time Compute) :利用用户离线的空闲时间执行耗时的文献综述、代码分析、故障排查,把"思考成果"持久化,待用户上线直接呈现。

持久化至少应保存五类对象:


组件

建议持久化内容

目的

会话状态

目标、阶段、上次完成节点、用户偏好

resume 与分支恢复

工具调用日志

工具名、归一化参数、结果摘要、幂等键

去重、审计、补偿

环境快照

工作目录、生成文件、安装依赖、输出目录

中断后继续跑

记忆层

长期偏好、项目约定、历史决策

减少再解释成本

审计轨迹

模型调用、审批、手工接管、策略命中

合规与事后复盘

2.4 LLM 特性支持与 Retry 机制

Harness 不应假设模型一次就对,也不应把所有错误都丢给"再问一遍”。正确做法是​区分错误类型


错误类型

是否可自动重试

推荐措施

429 / 限流 / 短暂 5xx

可以

指数退避 + jitter

结构化输出解析失败

条件可重试

优先用约束解码/结构化输出;失败时把具体错误反馈给模型做局部修复

工具超时 / 网络抖动

条件可重试

仅对无副作用或幂等工具自动重试

不可逆副作用失败

不应盲重试

需要幂等键、补偿事务或人工确认

目标 / 计划错误

不建议直接重试

回到 planner,重做任务分解

可以把"模型原生特性"理解为 Harness 的​降噪器

  • Function Calling:把动作参数从自然语言里解耦出来。
  • 结构化输出(Structured Output) :通过约束解码(constrained decoding)保证 schema 合规,减少"无效 JSON / 缺字段 / 类型错乱"的解析重试。LLM 生成畸形 JSON 或不存在的参数时,执行钩子捕获异常,构建含具体错误与修正指导的提示反馈给模型,触发内部 Retry,全程无需人类介入。
  • 指令层级(Instruction Hierarchy) :降低把外部内容当命令执行的概率(详见 Safety 篇)。
  • Compaction:延长有效上下文寿命,但不能替代状态设计。

3. 外界:外部影响——工具的副作用怎么管

模型自身是封闭的;Harness 通过 工具(Tool)环境(Env) 赋予它感知与改造世界的能力。但赋予行动力的同时引入了​副作用(Side Effects) ,这要求极严密的权限生命周期管理。

3.1 Tool 与 Env

工具可以是内联函数、数据库、第三方 API,甚至另一个 Agent。常见形态包括 hosted tools、function tools、agents-as-tools、MCP、文件读写、命令执行、Web、subagents 等。

一旦工具连接真实环境,副作用就成了一等问题:写/删文件、发邮件、下单、付款、创建工单、写数据库、浏览器点击、跨系统同步……对这些动作,Harness 不能只看"​能不能做​",还要判断"​是否已经做过、是否应该现在做、是否需要人类盖章"。

3.2 副作用管理:执行钩子、干跑、幂等

在"模型意图"与"实际执行"之间必须建立防火墙:

  • 执行钩子(Execution Hooks) ​:不是模型能阅读的软性指南,而是​由确定性代码编写的强制闸门。调用外部系统前做强制类型校验,拒绝非法的参数幻觉。
  • 干跑模式(Dry-run) :真正提交前先计算并展示"我将要做什么",为自动化校验或人类审查提供缓冲,避免错误在长链路里复合放大。
  • 幂等键(Idempotency Key) ​:对工具调用以 tool + 归一化参数​ 生成键并记录,防止重试/崩溃恢复/并发子代理导致​重复发信、重复扣费、重复写库

3.3 Permission 控制与 Human Confirm

涉及高风险、高价值或不可逆操作(生产库修改、大额转账)时,仅靠逻辑校验不够,必须引入 ​Human-in-the-Loop(HITL)

一条铁律:永远不要让具有非确定性的语言模型自主决定"何时需要人类审批"。 审批节点必须由 Harness 的状态机​预先硬编码

运行到预定义边界时,Harness 强制剥夺模型执行权,把任务状态挂起为 PENDING_APPROVAL​,向人类控制台推送含上下文的审批负载。人类可批准、拒绝、甚至直接修改中间变量;处理完毕后,Harness 把修正信息合并入上下文并恢复执行。这保证了权限流转的​可预测、可审计

生产级 Permission 模型建议至少分四层:

  1. 资源边界:文件根目录、网络白名单、凭证作用域。
  2. 工具边界:允许哪些工具、哪些参数模式。
  3. 动作边界:哪些动作可自动、哪些必须确认。
  4. 组织边界:谁能配置工具、谁能查看审计、谁能升级权限。

4. 关键组件清单

一个生产 Harness 的最小可用组件集:


组件

作用

失效后果

Orchestrator

驱动 plan-act-observe 循环与子代理编排

流程散乱、无法恢复

Context Manager

构建工作上下文、compaction、记忆召回

目标漂移、上下文膨胀

Session / State Store

保存状态、日志、断点、标识

crash 后丢进度

Tool Router

把模型动作映射到工具与环境

参数错配、工具滥用

Policy Engine

权限判断、风险分级、审批升级

高风险动作越权

Sandbox / 隔离环境

运行代码与文件操作

主机/个人数据暴露

Observability / Audit

追踪模型、工具、审批、成本

无法复盘和合规

Retry / Idempotency Layer

处理瞬时错误与去重

重复副作用、双写

5. 主流实现对比


实现

权限模型

持久化策略

沙箱/隔离

特点

OpenAI Agents SDK

工具级needs_approval,HITL pause/resume

to_state()、session、sandbox snapshots、resumable state

原生 Sandbox,支持多家 provider

状态/审批/沙箱一体化强

Anthropic Claude Agent SDK / Claude Code

默认只读、显式授权、allowlist、acceptEdits、hooks 可控

会话恢复、memory 文件、compaction、checkpointing

/sandbox文件系统与网络隔离,工作目录写限制

coding agent 体验成熟,上下文管理原生强

LangGraph + Deep Agents

interrupts + 人工审查,策略自定义

checkpointer + stores,thread_id恢复

Deep Agents 支持 sandbox backends

编排灵活,适合自定义状态机与长流程

Google ADK

Tool Confirmation、ApprovalTool、自定义安全工具

sessions / state / TTL / long-running resume

Agent Sandbox、GKE Agent Sandbox

多语言、长流程与企业治理完善

这张表最重要的结论不是"谁最强",而是四家都在收敛到​同一种架构:状态外置、审批内建、工具标准化、沙箱隔离、可恢复执行。差异主要在默认体验与企业治理深度。

6. 统一的 Run Loop(伪代码)

把前面所有要素收进一个循环:

def run_agent(task, state_id):
    state = load_state(state_id)              # 持久化恢复

    while not state.done:
        ctx = build_context(
            goal=state.goal,
            short_term=state.recent_history,
            long_term=recall_memory(state),
            workspace=mount_workspace(state),
        )
        if near_context_limit(ctx):
            ctx = compact(ctx)                # 保留目标/计划/关键证据/未完成事项

        reply = model.generate(
            ctx,
            tool_schemas=tool_registry.schemas(),
            output_schema=PlannerOrAction,    # 结构化输出
        )

        if reply.type == "plan_update":
            state.plan = merge_plan(state.plan, reply.plan)
            persist(state); continue

        if reply.type == "tool_call":
            risk = policy_engine.classify(reply.tool, reply.args, state)  # 风险分级
            if risk.requires_human:
                persist(state, pending=reply)
                pause_for_approval(state_id, reply)   # 硬编码审批点,挂起等待
                return

            token = make_idempotency_key(reply.tool, reply.args, state)
            result = safe_execute(reply.tool, reply.args,
                                  sandbox=select_sandbox(reply.tool),
                                  idempotency_key=token)
            if result.retryable:
                backoff_retry(reply, token)           # 仅幂等动作重试
            else:
                state.recent_history.append(result)
                persist(state); continue

        if reply.type == "final":
            state.output = reply.output
            state.done = True
            persist(state)
            return state.output

这个流程把 上下文构建、compaction、结构化输出、风险分级、沙箱执行、幂等重试、暂停恢复 统一进一个 run loop,基本对应当前主流框架的共同抽象。