从0到1手写 AI Agent Harness:为什么护城河不在模型,而在工程外壳 📅 发布时间:2026/8/24 22:16:44 👁 浏览次数: 从0到1手写 AI Agent Harness为什么护城河不在模型而在工程外壳 摘要本文从 2026 GitHub 趋势deepseek-harness 周增 1.4 万星与护城河在 Harness 不在模型讨论切入讲清 Agent Harness 的定义、四大职责与手写最小可运行实现——ReAct 循环 权限门禁 可回放会话。并给出把记忆/协议/技能/可观测/评测/安全拼进同一控制平面的思路与三条生产避坑。读完你将拥有可跑的 Harness 骨架。️ 关键词Agent HarnessAI Agent工程外壳工具调度权限沙箱目录一、背景与痛点模型不再是瓶颈二、什么是 Agent Harness2.1 定义Harness 是模型的驾驶舱2.2 Harness 的四大核心职责2.3 一个信号GitHub 趋势从模型转向系统三、手写最小可运行 Harness3.1 整体架构设计3.2 ReAct 主循环 工具调度3.3 权限门禁把工具调用关进笼子3.4 可回放会话让调试可追溯四、把六件套装进 Harness4.1 记忆 / Skills / 协议如何接入4.2 可观测 / 评测 / 安全如何接入五、生产避坑5.1 星标暴涨 ≠ 可生产5.2 上下文污染与回放陷阱5.3 最小权限与默认拒绝六、总结一、背景与痛点模型不再是瓶颈过去两年大家的注意力都在哪个模型更强——榜单、参数、上下文长度。但 2026 年 8 月的一组信号很说明问题GitHub Trending 周榜第一是deepseek-harness一周暴涨约 1.4 万星紧随其后的diagram-design、prime-agent、TencentDB-Agent-Memory、agent-skills、cloudflare/computer几乎全在解决怎么把模型框起来、管起来、跑起来而不是训练新模型。社区里的共识正在收敛模型质量趋同之后真正的护城河是控制模型行为的系统。一个原始 LLM 只会聊天要让它干活——读写文件、调接口、跑命令、跨会话记住上下文、多人协作——你需要一层包裹模型的东西。这层东西就是 Agent Harness。 一句话模型是发动机Harness 是车架、方向盘和刹车。发动机再强没有车架它上不了路。二、什么是 Agent Harness2.1 定义Harness 是模型的驾驶舱Agent Harness工程外壳是介于裸 LLM和可用 Agent之间的一层工程代码。它不直接产生智能而是负责循环驱动模型、调度工具、管理上下文、控制权限、记录过程。你可以把它理解为模型的驾驶舱——模型负责思考Harness 负责让它安全地踩油门、打方向、踩刹车。它和普通的调一次 API 拿到回答有本质区别维度裸 LLM 调用Agent Harness交互方式一问一答多轮循环 工具反馈上下文单次窗口可压缩、可持久、可回放能力边界只有文字能读文件、跑命令、调外部服务安全无权限门禁、沙箱、审计可调试重跑难复现事件日志可追溯、可回放2.2 Harness 的四大核心职责一个合格的 Harness 至少承担四件事循环驱动Loop把模型输出 → 解析动作 → 执行 → 结果回填 → 再问模型串成一个闭环直到任务完成或步数耗尽。这是 ReAct 模式落地的骨架。工具调度Dispatcher把模型想用的工具名 参数路由到真实函数处理序列化、异常、超时。模型只描述意图Harness 负责落地。权限控制Permission默认拒绝。只有当工具在白名单内、参数通过校验才放行危险动作删库、公网请求必须显式授权或 human-in-the-loop。过程记录Replay把每一轮的目标、思考、工具调用、结果、报错都落盘成事件流。出事后能像看日志一样还原当时为什么这么做而不是靠记忆复现一个不稳定的交互。这四件事单独看都不神秘但把它们拼成一个稳定、可审计、可恢复的循环正是 Harness 真正的工程价值。2.3 一个信号GitHub 趋势从模型转向系统2026 年 8 月 GitHub Trending 最明显的特征是最快增长的项目几乎都在解决 Agent 的六个瓶颈之一——上下文、记忆、技能、编排、机器访问、边缘执行。模型选择已经够用开发者不再等一个稍好的基座模型而是围绕模型组装可替换的组件。这带来一个重要判断看 Trending 时星标衡量的是需求架构、验证、发布节奏、许可证、集成成本才决定能不能落地。本文要做的就是抛开星标亲手把 Harness 的核心拼起来。三、手写最小可运行 Harness下面用一个纯标准库、零外部依赖的最小 Harness 把上面四件事跑通。生产里你只需把mock_llm换成真实模型 API把工具函数换成你的业务函数即可。3.1 整体架构设计┌─────────────────────────────┐ 用户目标 → │ Harness (控制平面) │ │ ┌────────┐ ┌───────────┐ │ │ │ Loop │→│ Dispatcher │→ 工具(读文件/跑命令/调API) │ └────────┘ └───────────┘ │ │ ┌────────┐ ┌───────────┐ │ │ │ Gate │ │ SessionLog │ │ ← 权限门禁 事件回放 │ └────────┘ └───────────┘ │ └─────────────────────────────┘ ↓ SessionLog (JSONL 事件流)3.2 ReAct 主循环 工具调度核心是一个Harness类run()里跑 ReAct 闭环mock_llm仅作演示生产替换为真实 API。为了可运行我把模型决策用步数驱动方便你直接python harness.py看到完整流程。importjson,uuid,datetime,os# ---------- 1. 会话事件日志可回放 ----------classSessionLog:def__init__(self,path):self.pathpathdefrecord(self,event):event[ts]datetime.datetime.utcnow().isoformat()event[id]uuid.uuid4().hex[:8]withopen(self.path,a,encodingutf-8)asf:f.write(json.dumps(event,ensure_asciiFalse)\n)defreplay(self):ifnotos.path.exists(self.path):return[]withopen(self.path,encodingutf-8)asf:return[json.loads(l)forlinfifl.strip()]# ---------- 2. 权限门禁默认拒绝 ----------classPermissionGate:def__init__(self,allowNone):self.allowset(allowor[])defcheck(self,tool_name,args):iftool_namenotinself.allow:returnFalse,ftool {tool_name} not in allowlistreturnTrue,ok# ---------- 3. 真实工具函数 ----------deftool_read_file(path):withopen(path,encodingutf-8)asf:returnf.read()[:2000]# 只读前 2000 字符避免把大文件塞爆上下文TOOLS{read_file:tool_read_file}# run_shell 故意不注册演示默认拒绝# ---------- 4. 模拟 LLM生产替换为真实 API 调用 ----------defmock_llm(step):ifstep0:return{action:call,tool:read_file,args:{path:config.example.json}}ifstep1:return{action:call,tool:run_shell,args:{cmd:rm -rf /}}# 危险动作return{action:answer,text:已读取配置危险命令被权限门禁拦截任务安全结束。}# ---------- 5. Harness 主循环 ----------classHarness:def__init__(self,session_path,gate,max_steps10):self.logSessionLog(session_path)self.gategate self.max_stepsmax_stepsdefrun(self,user_goal):self.log.record({type:goal,text:user_goal})forstepinrange(self.max_steps):decisionmock_llm(step)# ← 生产: 真实模型决策ifdecision[action]answer:self.log.record({type:answer,text:decision[text]})returndecision[text]tool,argsdecision[tool],decision[args]ok,reasonself.gate.check(tool,args)# 权限门禁self.log.record({type:tool_call,tool:tool,args:args,allowed:ok,reason:reason})ifnotok:continue# 被拦截进入下一轮不执行iftoolnotinTOOLS:self.log.record({type:error,text:funknown tool{tool}})continuetry:resultTOOLS[tool](**args)self.log.record({type:tool_result,result:str(result)[:500]})exceptExceptionase:self.log.record({type:error,text:str(e)})returnmax steps reached3.3 权限门禁把工具调用关进笼子注意第 3 节代码里run_shell没有注册进TOOLS而且PermissionGate默认拒绝白名单外的工具。当mock_llm在 step 1 返回危险的rm -rf /时门禁check(run_shell, ...)返回False循环continue真实命令永远不会执行事件流里留下一条allowed: false的记录事后可审计谁、什么时候、想干什么、被拦了。这就是安全从感知层移到执行层的落地与其在提示词里求模型别干坏事不如在 Harness 这一层用代码物理阻断。3.4 可回放会话让调试可追溯SessionLog把所有事件写进 JSONL。出问题时不需要重跑一遍不稳定的交互直接replay()就能看到完整时间线if__name____main__:gatePermissionGate(allow[read_file])# 仅放行只读工具hHarness(session.example.jsonl,gate)print(结果:,h.run(读取配置文件并检查风险项))print(\n--- 会话回放事件流---)forevinh.log.replay():print(f[{ev[ts]}]{ev[type]}:{json.dumps(ev,ensure_asciiFalse)})运行后你会看到goal→tool_call(read_file, allowedtrue)→tool_result→tool_call(run_shell, allowedfalse)→answer。一条被拦截的危险调用清晰可查这就是 Harness 相对裸调 API的核心优势。四、把六件套装进 Harness社区这几年把 Agent 的各个能力点都磨得很成熟了记忆、工具协议MCP/A2A、Skills、可观测、评测、安全——单看都好用问题是怎么拼起来。Harness 恰好是那个控制平面把这些模块接成一张网。4.1 记忆 / Skills / 协议如何接入记忆在run()每轮开始前从记忆中心拉取与当前目标相关的上下文对话/文档/代码注入系统提示工具产出再写回记忆。跨会话复用靠它。Skills声明式技能把TOOLS从硬编码函数升级为元数据驱动的技能清单——每个 Skill 有名称、描述、输入 schema。模型按描述匹配Harness 懒加载避免把所有指令塞进上下文。协议MCP/A2ADispatcher不只调本地函数还能通过 MCP 连外部工具服务、通过 A2A 把子任务转发给另一个 Agent。协议是工具/Skill的 transport 层Harness 只管调度不关心工具在哪。4.2 可观测 / 评测 / 安全如何接入可观测把SessionLog的每一条事件加上trace_id/span导出到 OpenTelemetry 后端Langfuse、Phoenix就能看到每个工具调用的耗时、成本、成功与否。评测在run()外层包一个 Eval 循环——跑一批固定任务用确定性 启发式 LLM-as-Judge三层打分作为 CI 质量门禁防止改了 Harness 把准确率带崩。安全PermissionGate只是第一道。再叠加输入注入检测识别提示词攻击、输出脱敏拦截泄露的密钥、出口白名单只允许访问审批过的域名就构成执行层防护。一句话记忆给上下文、Skills 给能力、协议给扩展、可观测给眼睛、评测给标尺、安全给刹车——而 Harness 是把它们拧在一起的轴。五、生产避坑5.1 星标暴涨 ≠ 可生产deepseek-harness一周 1.4 万星很炸裂但星标衡量的是注意力不是可靠性。落产前请查四项贡献者分布是否健康、有无未解决的安全 issue、是否有打 tag 的正式 release、依赖风险与维护响应速度。任何能碰仓库或 shell 的 Agent都必须先过这几关再进生产。5.2 上下文污染与回放陷阱回放能还原发生了什么但还原不了当时的完整上下文——如果上下文里混入了错误的中间结论回放看到的是被污染后的决策链容易误判根因。对策回放时同时存快照版本号调试优先看tool_result原始值而非模型复述并定期做可恢复性演练确认日志真能重建现场。5.3 最小权限与默认拒绝永远从默认拒绝出发TOOLS白名单 PermissionGate双保险。不要因为模型一般不会乱来就放开危险工具。把危险动作写库、公网请求、删文件设为必须显式审批或 human-in-the-loop。可参考上一条原则安全要在执行层用代码物理阻断而不是在提示词里靠模型自觉。六、总结2026 年的 Agent 竞争已经从前两年的模型军备赛切换到系统工程赛。Harness 就是这场比赛里最关键的控制平面它用 ReAct 循环驱动模型、用 Dispatcher 落地工具、用 PermissionGate 物理阻断危险动作、用 SessionLog 让一切可追溯。本文给的最小实现只有几十行标准库代码却把四件核心职责跑通了。把它和记忆、Skills、协议、可观测、评测、安全这六件套接起来你就拥有了一个能生产落地、可审计、可恢复的 Agent 框架骨架——而不是又一个只能在 Demo 里惊艳的玩具。 动手建议先把本文的harness.py跑起来再逐步把mock_llm换成真实模型、把TOOLS换成你的业务函数最后接上一条可观测链路。欢迎在评论区聊聊你踩过的 Harness 坑。示例数据声明文中config.example.json、example.com、run_shell等均为通用化演示素材不对应任何真实系统或业务。