news 2026/8/24 22:16:28

从0到1手写 AI Agent Harness:为什么护城河不在模型,而在工程外壳

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从0到1手写 AI Agent Harness:为什么护城河不在模型,而在工程外壳

从0到1手写 AI Agent Harness:为什么护城河不在模型,而在工程外壳

📖 摘要:本文从 2026 GitHub 趋势(deepseek-harness 周增 1.4 万星)与"护城河在 Harness 不在模型"讨论切入,讲清 Agent Harness 的定义、四大职责与手写最小可运行实现——ReAct 循环 + 权限门禁 + 可回放会话。并给出把记忆/协议/技能/可观测/评测/安全拼进同一控制平面的思路与三条生产避坑。读完你将拥有可跑的 Harness 骨架。

🏷️ 关键词:Agent Harness,AI Agent,工程外壳,工具调度,权限沙箱

目录

  • 一、背景与痛点:模型不再是瓶颈
  • 二、什么是 Agent Harness
    • 2.1 定义:Harness 是模型的"驾驶舱"
    • 2.2 Harness 的四大核心职责
    • 2.3 一个信号:GitHub 趋势从模型转向系统
  • 三、手写最小可运行 Harness
    • 3.1 整体架构设计
    • 3.2 ReAct 主循环 + 工具调度
    • 3.3 权限门禁:把工具调用关进笼子
    • 3.4 可回放会话:让调试可追溯
  • 四、把"六件套"装进 Harness
    • 4.1 记忆 / Skills / 协议如何接入
    • 4.2 可观测 / 评测 / 安全如何接入
  • 五、生产避坑
    • 5.1 星标暴涨 ≠ 可生产
    • 5.2 上下文污染与回放陷阱
    • 5.3 最小权限与默认拒绝
  • 六、总结

一、背景与痛点:模型不再是瓶颈

过去两年,大家的注意力都在"哪个模型更强"——榜单、参数、上下文长度。但 2026 年 8 月的一组信号很说明问题:GitHub Trending 周榜第一是deepseek-harness(一周暴涨约 1.4 万星),紧随其后的diagram-designprime-agentTencentDB-Agent-Memoryagent-skillscloudflare/computer几乎全在解决怎么把模型"框"起来、管起来、跑起来,而不是训练新模型。

社区里的共识正在收敛:模型质量趋同之后,真正的护城河是控制模型行为的系统。一个原始 LLM 只会"聊天",要让它"干活"——读写文件、调接口、跑命令、跨会话记住上下文、多人协作——你需要一层包裹模型的东西。这层东西,就是 Agent Harness。

💡 一句话:模型是发动机,Harness 是车架、方向盘和刹车。发动机再强,没有车架它上不了路。

二、什么是 Agent Harness

2.1 定义:Harness 是模型的"驾驶舱"

Agent Harness(工程外壳)是介于"裸 LLM"和"可用 Agent"之间的一层工程代码。它不直接产生智能,而是负责:循环驱动模型、调度工具、管理上下文、控制权限、记录过程。你可以把它理解为模型的"驾驶舱"——模型负责思考,Harness 负责让它安全地"踩油门、打方向、踩刹车"。

它和普通的"调一次 API 拿到回答"有本质区别:

维度裸 LLM 调用Agent Harness
交互方式一问一答多轮循环 + 工具反馈
上下文单次窗口可压缩、可持久、可回放
能力边界只有文字能读文件、跑命令、调外部服务
安全权限门禁、沙箱、审计
可调试重跑难复现事件日志可追溯、可回放

2.2 Harness 的四大核心职责

一个合格的 Harness 至少承担四件事:

  1. 循环驱动(Loop):把"模型输出 → 解析动作 → 执行 → 结果回填 → 再问模型"串成一个闭环,直到任务完成或步数耗尽。这是 ReAct 模式落地的骨架。
  2. 工具调度(Dispatcher):把模型想用的"工具名 + 参数"路由到真实函数,处理序列化、异常、超时。模型只描述意图,Harness 负责落地。
  3. 权限控制(Permission)默认拒绝。只有当工具在白名单内、参数通过校验,才放行;危险动作(删库、公网请求)必须显式授权或 human-in-the-loop。
  4. 过程记录(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.path=pathdefrecord(self,event):event["ts"]=datetime.datetime.utcnow().isoformat()event["id"]=uuid.uuid4().hex[:8]withopen(self.path,"a",encoding="utf-8")asf:f.write(json.dumps(event,ensure_ascii=False)+"\n")defreplay(self):ifnotos.path.exists(self.path):return[]withopen(self.path,encoding="utf-8")asf:return[json.loads(l)forlinfifl.strip()]# ---------- 2. 权限门禁(默认拒绝) ----------classPermissionGate:def__init__(self,allow=None):self.allow=set(allowor[])defcheck(self,tool_name,args):iftool_namenotinself.allow:returnFalse,f"tool '{tool_name}' not in allowlist"returnTrue,"ok"# ---------- 3. 真实工具函数 ----------deftool_read_file(path):withopen(path,encoding="utf-8")asf:returnf.read()[:2000]# 只读前 2000 字符,避免把大文件塞爆上下文TOOLS={"read_file":tool_read_file}# run_shell 故意不注册,演示"默认拒绝"# ---------- 4. 模拟 LLM(生产替换为真实 API 调用) ----------defmock_llm(step):ifstep==0:return{"action":"call","tool":"read_file","args":{"path":"config.example.json"}}ifstep==1:return{"action":"call","tool":"run_shell","args":{"cmd":"rm -rf /"}}# 危险动作return{"action":"answer","text":"已读取配置;危险命令被权限门禁拦截,任务安全结束。"}# ---------- 5. Harness 主循环 ----------classHarness:def__init__(self,session_path,gate,max_steps=10):self.log=SessionLog(session_path)self.gate=gate self.max_steps=max_stepsdefrun(self,user_goal):self.log.record({"type":"goal","text":user_goal})forstepinrange(self.max_steps):decision=mock_llm(step)# ← 生产: 真实模型决策ifdecision["action"]=="answer":self.log.record({"type":"answer","text":decision["text"]})returndecision["text"]tool,args=decision["tool"],decision["args"]ok,reason=self.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":f"unknown tool{tool}"})continuetry:result=TOOLS[tool](**args)self.log.record({"type":"tool_result","result":str(result)[:500]})exceptExceptionase:self.log.record({"type":"error","text":str(e)})return"max steps reached"

3.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__":gate=PermissionGate(allow=["read_file"])# 仅放行只读工具h=Harness("session.example.jsonl",gate)print("结果:",h.run("读取配置文件并检查风险项"))print("\n--- 会话回放(事件流)---")forevinh.log.replay():print(f"[{ev['ts']}]{ev['type']}:{json.dumps(ev,ensure_ascii=False)}")

运行后你会看到:goaltool_call(read_file, allowed=true)tool_resulttool_call(run_shell, allowed=false)answer一条被拦截的危险调用清晰可查,这就是 Harness 相对"裸调 API"的核心优势。

四、把"六件套"装进 Harness

社区这几年把 Agent 的各个能力点都磨得很成熟了:记忆、工具协议(MCP/A2A)、Skills、可观测、评测、安全——单看都好用,问题是怎么拼起来。Harness 恰好是那个"控制平面",把这些模块接成一张网。

4.1 记忆 / Skills / 协议如何接入

  • 记忆:在run()每轮开始前,从记忆中心拉取与当前目标相关的上下文(对话/文档/代码),注入系统提示;工具产出再写回记忆。跨会话复用靠它。
  • Skills(声明式技能):把TOOLS从硬编码函数升级为"元数据驱动的技能清单"——每个 Skill 有名称、描述、输入 schema。模型按描述匹配,Harness 懒加载,避免把所有指令塞进上下文。
  • 协议(MCP/A2A)Dispatcher不只调本地函数,还能通过 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.jsonexample.comrun_shell等均为通用化演示素材,不对应任何真实系统或业务。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/24 22:14:22

AI Coding 一周速览:5个必学实用技巧 + 5个行业大事件,程序员别错过

大家好,我是你们的技术博主。过去一周AI Coding领域又发生了不少大事,从SpaceX豪掷600亿美元收购Cursor,到Claude Code的多会话协作升级,再到国产AI编程工具的崛起……今天我就用最通俗易懂的方式,帮大家梳理出最值得关…

作者头像 李华
网站建设 2026/8/24 22:09:02

系统设计第一天决策卡

场景:每日签到 玩家登录后,再活动签到页面打卡获得奖励,需记录每日打卡记录。 选型 简单记录打卡日期和次数redis的bitmap记录 决策 方案1,理由: 不需额外部署逻辑简单 批改 如果DAU超过10万或实时统计,可迁…

作者头像 李华
网站建设 2026/8/24 22:08:28

UniGetUI 离线安装包制作完全指南:4步搞定无网环境部署

UniGetUI 离线安装包制作完全指南:4步搞定无网环境部署 【免费下载链接】UniGetUI UniGetUI: The Graphical Interface for your package managers. Could be terribly described as a package manager manager to manage your package managers 项目地址: https:…

作者头像 李华
网站建设 2026/8/24 22:02:49

G-Helper 笔记本风扇控制:5 分钟画出专属 ROG 散热曲线

G-Helper 笔记本风扇控制:5 分钟画出专属 ROG 散热曲线 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, E…

作者头像 李华