Harness 工程
🎯 学习目标
- 定义 Harness 作为 Agent 运行时壳层的职责
- 实现 beforeToolCall / afterLLM / onError 等 Hook
- 集成 AbortSignal、超时、死循环检测与审计
- 建立 trace、metrics 与人工 escalation 路径
引言
Loop + Tools 是引擎;Harness 是车架、安全带与仪表盘。没有 Harness 的 Agent 只能 Demo。本节把分散的安全、观测、中断话题收拢为一套运行时工程。
章节正文
第 1 步:Harness 职责边界
Harness 不替 LLM 思考;它:
- 强制执行权限与确认策略
- 在工具/LLM 前后插入 Hook
- 统一 timeout、retry、cancel(AbortSignal)
- emit trace/metrics/audit
- 检测死循环与 budget 超限
- 提供 pause/resume/escalate API
业务逻辑在 Tools 与 Planner;策略在 Harness。
第 2 步:Hook 设计
class AgentHarness {
async beforeToolCall(call: ToolCall, ctx: SessionCtx) {
this.audit.log({ phase: 'before', call })
if (this.isHighRisk(call)) await this.confirmWithUser(call, ctx)
if (ctx.signal.aborted) throw new AbortError()
}
async afterLLM(response: LLMResponse, ctx: SessionCtx) {
this.metrics.tokens.inc(response.usage.totalTokens)
this.contentFilter.scan(response.message.content)
}
async onError(err: unknown, ctx: SessionCtx) {
this.trace.fail(ctx.sessionId, err)
if (isRetryable(err)) return this.retryPolicy.next()
throw err
}
}Hook 保持纯副作用,不改变业务语义,便于单测。
第 3 步:AbortSignal 与优雅中断
const ac = new AbortController()
ui.onPause(() => ac.abort())
await runAgentLoop(state, { signal: ac.signal, harness })
// ToolExecutor / fetch 均需传入 signal用户点「停止」后,应在当前 tool 完成后停止,而非 kill 进程留 half-written 文件。
第 4 步:观测:Trace 与 Metrics
OpenTelemetry 风格 span:
session.run
├─ llm.planner (iteration=1)
├─ tool.search_docs
├─ llm.planner (iteration=2)
└─ llm.finalMetrics:agent_run_duration、tool_errors_total、iterations_per_run、human_confirm_denied。
日志关联 sessionId、userId、traceId。
第 5 步:Escalation 与降级
当 abortReason === 'MAX_ITERATIONS' 或 critical tool 失败:
- 返回 partial result + 清晰说明
- 可选 ticket 转人工,附带 trace link
- 降级:关闭 write 工具,只读继续
Harness 配置应用层 policy YAML,而非硬编码 if。
动手练习
- 为 AgentHarness 写 3 个 Hook 的单测(mock user deny confirm)。
- 设计 policy.yaml:tools.write.requireConfirm、maxIterations、tokenBudget。
- 画 OTel span 树示例,含一次失败 retry。
- 实现 onPause → AbortController 与 Loop 协作的伪代码。
- 写 escalation 工单应包含哪些字段(trace、partial state、user goal)。
常见问题
Q:Harness 和 Middleware 一样吗?
类似 HTTP middleware 链,但面向 Agent 语义(tool、iteration、budget)。可复用 middleware 思想实现 Hook pipeline。
Q:Hook 里能改 tool arguments 吗?
谨慎。sanitize 可以;实质性改参应记 audit 并最好让人确认,否则 accountability 模糊。
Q:Cursor / Claude Code 的 Harness 我们能复用吗?
IDE 产品有内置 Harness(权限、沙箱)。自研 Agent 仍需自己的 policy 与 observability,不能假设 IDE 层覆盖服务端场景。
本节小结
Harness = Agent 的生产运行时:Hook、权限、中断、retry、trace、escalation。策略配置化、观测标准化,Loop 才能从 Demo 进生产。