第一次在项目里引入Agent开发时,我几乎被一堆概念名词淹没了。“Harness”“Loop”“Graph”“编排”“循环”“载体”,这些词每个看起来都知道,放在一起就完全不知道该先搭什么、后搭什么。后来踩了不少坑、重写了两个版本,才理清楚:这三个词根本不是互相替代的关系,而是三个不同层面的工程抽象。Harness是Agent的运行容器,Loop是Agent的认知内核,Graph是Agent的协作拓扑。这篇文章就用我的实际项目经验,把这三层拆开讲清楚,顺便聊聊在生产环境里到底该怎么落地。
1. 先弄清楚三层架构的边界:Harness管壳、Loop管脑、Graph管协作
很多文章把Agent框架和Agent混着说,一会讲LangGraph怎么编排,一会讲ReAct循环怎么设计,最后读者根本不知道这些组件是装在一个系统里还是只能选一个。我在项目里重写第二版的时候,把整个系统拆成了三个独立模块,每个模块单独演进,才算是解决了这个问题。
1.1 Harness不是“提示词工程”,是Agent的运行环境
Harness这个单词直译是“马具”,工程里更多指的是“控制台”“鉴定装置”这层意思。放到Agent工程里,我把它理解为:Agent跑在什么环境里、由谁去驱动它、它对外暴露什么接口。一个最简单的Harness就是命令行工具,比如Claude Code、DeepSeek Harness这类产品,本质都是先搭一个“人能指挥Agent干活”的壳子。
这个壳子至少要做三件事:
- 定义Agent的入口和退出条件,比如用户输入什么触发思考、什么情况下算任务完成;
- 管理Agent运行时的外部资源,包括模型接口、工具调用权限、知识库检索通道;
- 承载会话上下文,保证多轮交互中Agent的记忆不丢。
我在第一个版本里犯的错误就是:把Harness和业务代码揉在一起,直接在调用大模型的地方写死提示词模板和工具函数,结果每次换场景都要改源码,维护成本极高。后来我把Harness单独做成一个运行时层,对外暴露统一的Stdio接口,内部再挂载模型驱动、工具注册表、会话状态管理,才真正体会到“壳”和“脑”分离的好处。
1.2 Loop是Agent的思考循环,不是网络请求重试
Loop这个词在网络编程里经常表示“重试循环”,但在Agent工程里,它指的是Agent在完成一个任务时进行“观察—思考—行动—再观察”的往复过程。这是Agent区别于传统RAG问答、普通API调用的关键。大模型本身是“单次推理”机制,你给它一段输入,它吐出一次输出,没有“我看看结果对不对、不对再改”的能力。Loop就是人为地给模型加上这个反馈回路。
举一个我在写代码智能体时遇到的例子。第一次产品原型里,Agent调用代码解释器执行生成的Python脚本,脚本报错了,整个任务就中断。原因就是我只做了一次“生成—执行”,没有让Agent看到错误信息后再生成修复版本。后来我把“执行结果回传→模型分析→再次生成”这个过程包成一个while循环,Agent才真正具有了连续解决问题的能力。
1.3 Graph是多个能力节点之间的路由拓扑,不是数据流图
Graph在这里和“图数据库”“图神经网络”没有任何关系,至少不是在讲那些东西。它指的是以有向图形式描述Agent系统中各个节点(Node)之间的连接关系、条件判断和状态转换。也就是说,一个环节跑完后下一步该走哪个环节、哪个分支,是由图的结构决定的。
早期做Agent只有一条链路:用户提问→模型生成→工具调用→返回结果。这是标准的单Loop,不需要Graph。但等到我接的任务开始涉及多个工具串行调用、条件分支、多个子Agent并行协作时,单条Loop根本表达不了这种复杂度。比如一个数据分析Agent,可能需要先检索数据库、再调用画图脚本、最后汇总结论,而其中“画图失败”和“画图成功”应该走两条不同的后续路径。这种场景就是Graph登场的时刻。
1.4 三个层次如何协同:一个工厂的比喻
我一直用“工厂”来给同事解释三层分工。Harness是整个工厂的车间外壳——它负责供电(模型API)、通风(工具调用权限)、安保(沙箱隔离),以及工人在哪个工位干活(会话上下文)。Loop是车间里最核心的工人作业循环——看图纸(读输入)、动脑筋(推理)、上手操作(调工具)、检查成品(观察反馈),做完一个循环再决定要不要返工。Graph则是整条生产线上的工序拓扑——第一道工序完成后是走质检分支还是直接包装,哪两道工序可以并行,哪道工序必须要等前一道完成。
一个小Agent可以只有Harness+Loop,就像一个小作坊,一个工人从头做到尾。复杂系统才需要Graph,因为生产线变长了,需要有调度、分支和并行能力。搞明白这个边界,选型的时候就不会纠结“用Harness还是用LangGraph”这种问题。
下面是三层架构的职责对照,方便大家按图索骥做选型:
| 层次 | 核心职责 | 典型问题 | 一句话定位 |
|---|---|---|---|
| Harness | 运行环境、权限边界、上下文管理、接口暴露 | Agent跑在哪、怎么被调用、能碰什么资源 | 壳与地基 |
| Loop | 观察—思考—行动—反馈的循环推理 | 如何让模型“知道自己做错了并改正” | 认知内核 |
| Graph | 节点编排、路由分支、并行调度、状态快照 | 多个环节/Agent之间如何协作成流水线 | 协作拓扑 |
2. Loop是Agent认知的发动机:理解ReAct循环与常驻循环
如果说Harness决定了Agent能不能跑,Loop就决定了Agent聪不聪明。我在生产实践中发现,大部分初代AgentDemo的失败,都是因为Loop设计得太简单——要么根本没有反馈,要么反馈给模型的信息不完整。
2.1 从一次推理到多次推理:ReAct模式的工程化
ReAct是Reasoning and Acting的缩写,论文里提出的核心概念是:让模型交替进行推理(Thought)和行动(Action),每次行动后都会收到一个Observation,模型再根据Observation继续推理。我用一句话概括:模型不是在一次性回答,而是在和工具对话。
在工程实现上,这个循环至少要有以下四个阶段:
- 感知(Perception):接收用户输入和系统状态,把外部信息序列化后交给模型。比如把当前屏幕截图转成文本、把上一步工具结果转成消息。
- 规划(Planning):模型在上下文中生成推理步骤。这里要注意,现在的大模型推理输出经常长,生产环境里最好让它输出结构化JSON,避免去解析自然语言。
- 执行(Action):从模型输出中提取工具调用参数,通过Harness层注册的工具网关真正执行操作,比如执行Shell命令、发HTTP请求、打开文件。
- 观察(Observation):把工具执行的返回结果(包括报错、超时、空结果)作为Observation追加到上下文中,回到阶段2,继续循环。
2.2 无限循环不是目的,要有终止策略和预算管理
很多人听到“循环”就头疼,怕Agent陷入死循环。实际工程里确实要防这个问题——模型有可能在同一个工具调用上反复横跳,也可能会输出大量无意义推理。我处理这类问题用的是四层防线:
- 任务完成判断:模型主动输出
FINISH标记,或者识别到用户问题的答案已经生成完毕,循环自然终止; - 循环次数上限:设置最大迭代次数,比如执行阶段最多运行15次,超过就强制结束,并把已有结果整理给用户;
- 时间预算:整个Loop运行有硬性时间窗口,比如一个任务最多跑120秒,超时则进入降级流程,返回已完成的中间结果;
- 异常逃生口:一旦工具调用返回严重的系统级错误(比如文件系统崩溃、授权失效),循环要能中断而不是盲恢复。
有一个很典型的坑:循环里只判断“工具执行成功”就去调用下一个工具,忽略了“工具执行成功但返回结果为空”的情况。空结果会导致模型在下一个循环里不知道该说什么,于是它反复调用同一个工具。必须在观察阶段就做数据校验,把“空结果”变成一个明确的Observation,告诉模型“这次没有查到你想要的东西,请换个思路”。
2.3 Loop内的记忆管理:上下文是真的会撑爆的
先放一组我自己的实测数据:一个中等复杂度的开发任务,调用模型完成一次代码修改,Loop大概会迭代8~12轮;每轮追加的中间观察结果,比如文件读取内容、命令输出、错误堆栈,加起来可能有几千到几万token。如果任务再复杂一点,用不了几轮就会冲破模型的上下文窗口。这也是刚接触Loop工程的人最容易忽略的。
我现在的做法是两层记忆管理:
第一层是滑动窗口压缩。Loop运行过程中,系统会维护一个“核心记忆区”,只保留完整的最近3轮交互信息;更早的轮次会被摘要化,用一段话概括“这一步做了什么、得到什么关键结论”。这个策略类似于做会议纪要——会议开久了,不需要每一句话都记住,记住关键决议就够了。
第二层是外部记忆库。把工具执行输出中的结构化数据(比如数据库查询结果、代码扫描报告)写入文件或向量库,Loop上下文中只保留“写入位置”和“摘要”。需要精确内容时,再通过检索工具重新加载。
2.4 多窗口与常驻Loop:从单次任务到持续服务的跨越
我在相关热搜词里看到“loop 多窗口”这个词,正好是生产实践里绕不开的场景。单轮回Loop适合一次性问题解答,但很多Agent产品需要“常驻”——启动后一直挂在后台,用户随时可以和它对话,它还能在某些触发条件下主动唤醒执行任务。这就不能每次对话都新建Loop上下文了,而是要在Harness层维护一个持久化的会话状态,Loop在会话上反复循环。
举个例子,我做过一个运维助手,它的运行方式就是常驻后台监听工单消息。用户发来一个“帮我排查所有慢SQL”的请求,Loop被唤醒后开始迭代分析;分析完,Agent并不会退出,而是保留上下文继续等下一个请求,同时定期把数据库状态变化主动汇报给用户。这种模式就是常驻Loop,实现上需要额外处理并发:多个用户跑来触发任务时,不能让它们的上下文互相污染。我采用的方案是为每个会话分配独立的SessionRunner实例,Loop跑在各自独立的上下文中,Harness层再做统一的调度和资源限制。
3. Harness是生产环境的承载者和守门员:从SDK到内网部署的细节
Loop解决“Agent怎么想”的问题,Harness则解决“Agent在哪里跑、能碰什么、怎么被调用”的问题。这一层在生产实践里所有细节都会暴露,包括工具权限边界、沙箱隔离、进程生命周期、以及热搜里反复提到的“deepseek harness附带skill怎么部署到内网服务器”这类需求。
3.1 Agent从哪里获得“手和脚”:工具网关设计
Agent不能像人一样真的用电脑,它所有对外操作都必须经过工具网关。工具网关是Harness里的一个重要子系统,本质是一个函数的注册表和调用器。我在系统里定义了这样一个结构:
type Tool struct { Name string Description string Parameters map[string]ParameterSpec Permission string // 权限标记,比如 read / write / admin Handler func(args map[string]interface{}) (ToolResult, error) } type ToolResult struct { Output string MimeType string IsFinal bool Retryable bool DurationMs int64 }每个工具都必须声明权限级别,Handler执行前Harness会检查当前会话是否有权调用。这样做的好处是:Agent在Loop里疯狂想“操作”时,Harness可以冷静地把守着权限边界。比如代码Agent可以读文件、执行Python脚本,但绝对不能直接删库、改生产配置。所有高权限操作,一律要求用户二次确认。
我在实际项目里还遇到过工具调用的“潜伏失败”问题——工具本身没有报错,但返回的结果结构不符合预期,比如执行了git pull却没有检查返回的exit code,代码还在旧版本上继续写。所以工具网关的Handler里,每个执行命令都要把退出码、stdout、stderr一起作为结构化结果返回给Loop,让Agent可以基于完整信息做判断。
3.2 沙箱与隔离:Agent跑在生产服务器上到底安不安全
搞Agent工程的人迟早会被问一个问题:“你敢让Agent直接在服务器上执行命令吗?”我的答案从来都是“分环境”。本地调试、测试环境里可以让Agent有点权限,但生产环境必须上沙箱,至少要做到以下几点:
- 使用独立用户运行Agent进程,禁止root权限;
- 通过容器或轻量虚拟化隔离工具执行,例如把Shell命令塞进Docker容器里跑,宿主机只监听被允许的网络端口;
- 网络层面默认拒绝外联,需要外网请求时通过白名单代理访问;
- 文件系统做可写区限制,Agent只能写特定目录。
真正的Agent生产环境还要考虑命令超时和资源上限。比如我在Harness层给每个工具调用设置默认超时时间,脚本执行超过30秒就由Harness强制终止,而不会让一个失控的执行一直占着CPU和内存。
3.3 内网部署的实操要点:离线模型、技能包推送、密钥管理
热搜里有“deepseek harness Linux”“附带skill怎么部署到内网服务器”这类词,我猜很多人是公司内部要求数据不出域,要把Agent能力部署到内网。这块我踩过不少坑,整理几个关键点:
第一,模型服务要换成内网可达的推理端点。最稳妥的方案是直接在Harness配置里改model_provider的地址,指向内网中部署的推理服务,比如vLLM、Ollama或别人搭好的OpenAI兼容网关。注意不要漏掉“兼容格式”这个词,Harness一般要求的是OpenAI聊天格式API,内网部署的推理框架只要支持这个格式就能无缝对接。
第二,“某个技能包”部署到内网,本质上就是把Agent的技能资源(Prompt模板、工具定义、知识文件)分发给每台内网机器。我现在的做法是把这些技能做成目录包,通过Git仓库分发,服务器启动Harness时从本地目录加载,不再依赖外部下载。
第三,密钥和证书管理。内网环境经常没有外网证书信任链,访问内部API时要用自签证书,而很多Agent框架默认会做TLS校验,导致请求失败。对应的办法是设置环境变量跳过校验或者导入内网CA到系统信任区。这条不展开细说,但属于内网部署最容易被卡住的点之一。
3.4 Harness的并发与运行控制:怎么扛多用户服务
入选热搜的“ai agent怎么扛并发”问题,本质上是Harness层的调度问题。Loop是单个Agent的思考过程,但Harness要接待十个、一百个Agent实例同时跑Loop。一个经典的架构做法是:
- 每个会话一个协程/线程,互不阻塞;
- Loop运行所需的模型API调用通过连接池复用;
- 工具执行放入独立工作池,避免CPU密集型脚本阻塞会话响应;
- 全局加上并发令牌桶,限制同时激活的Agent数量,防止下游系统被打爆。
我测试下来的数据是:单机配置32核CPU加足够内存,采用并发限制在8个Agent实例、加上连接池复用之后,QPS比无限制并发反而稳定很多。原因很简单,模型API并发过高时会触发限流和排队,工具执行过于密集时会让机器负载飙升,反而拖垮整体吞吐。生产里我宁可让一个请求排队等两秒,也不想让整个系统雪崩。
4. Graph不等于工作流的“豪华版”:什么时候必须引入Graph架构
我在标题里把Graph放进三层架构,并在开篇先澄清了它不是图神经网络,但仍然会遇到一种提问:“我现在就用一个Loop加几个工具,也能完成80%的需求,为什么还要上Graph?”这个问题问得很对。Graph引入的根本动因,不是“显得架构高级”,而是单条Loop处理不了条件分支、并行协作和状态回溯。
4.1 从单Loop到Graph:分支和并行是如何自然出现的
一个纯Loop结构其实是一条直线:Agent自己决定“下一步调用什么工具”。但遇到下面这些情况时,直线结构就开始别扭:
- 条件分支:同一个输入,可能需要A分支做代码分析、B分支做文档检索。模型一条上下文里做出选择当然也行,但这样会让每个分支的上下文互相干扰。
- 多个步骤有先后依赖:第二步的执行结果决定了第三步走哪个分支,这正好是Graph节点间的边。
- 多个Agent并行工作:让一个Agent同时写前端和后端不现实,更自然的是拆成两个子Agent并行执行,分别在两个Loop里跑,然后在汇聚点合并结果。
- 状态回溯:某个步骤失败后,并不想从头跑,而是想回到某个特定节点重新执行。这在Graph里就是“有向边的回溯”,在纯Loop里很难表达。
我还记得自己第一次重构的场景:一个报告生成Agent,原来靠一个超大Prompt加十几条工具规则硬撑;后来任务量上来以后,提示词越来越长、越改越脆,每次新增一个数据源都要调整一长串指令。改成Graph后,我把“数据导入→清洗→生成分析→生成报告”拆成四个节点,每个节点内部再跑自己的Loop。新增数据源时只加一个节点、连一条边,其他部分完全不用动。
4.2 状态管理与快照:Graph的可恢复性从哪来
Graph相比于Loop的一个巨大优势是可恢复性。Loop只有“当前上下文”,一旦循环中间异常崩溃,重启后很难恢复到之前的状态;而Graph有明确的节点边界和边关系,每个节点跑完后可以把状态做一次快照,挂掉后从最近的快照节点重新拉起。
我实现一个简单的状态快照表时,大概是这样的结构:
| 字段 | 作用 |
|---|---|
graph_id | 当前Graph运行的全局标识 |
node_id | 当前节点唯一标识 |
status | 节点状态:pending / running / done / failed |
input_snapshot | 节点接收的输入快照,存储为JSON |
output_summary | 节点输出的摘要,用于后续节点加载 |
memory_key | 该节点产生的上下文消息在存储中的键值 |
Graph的每个节点只需要知道“我要用什么输入、我该输出什么给下游”,它并不需要把整个会话历史都Load进上下文中。这和人类开会的道理一样——每个环节的负责人只需要拿到上环节的产出,而不是旁听整场会议。
4.3 不是所有“画线”都是Graph:编排工具的真正价值
很多Graph编排工具,比如LangGraph、Snap Graph Builder之类,本质上是在帮开发者管理节点逻辑和边逻辑。但工具本身不能替你解决两个问题:
第一个是节点粒度。把整个Agent业务放在一个节点里,Graph就只有一层皮;把每个工具调用拆成独立节点,又会出现“节点爆炸”——海量小节点让图本身变得不可维护。我经验里比较好的粒度是“一个节点完成一个完整的业务步骤”,比如“数据预处理”是一个节点,内部可以跑一个小Loop做多次清洗尝试;而“数据预处理的某一行代码”不应该成为节点。
第二个是图与Loop的嵌套关系。Graph不是替代Loop,而是Loop的容器。每个Graph节点内部完全可以是一个完整的ReAct Loop。生产实践里最舒服的形态是:外层用Graph管理“步骤之间的依赖与分支”,内层用Loop管理“每个步骤内部的试错与反馈”。
4.4 可视化与可观测性:给Graph装上仪表盘
Graph的另一个生产价值在于可观测性。纯Loop跑起来是一长串对话日志,很难让人快速定位“现在卡在哪个环节”;Graph天然有节点和边,每个节点都可以埋点输出运行指标。我现在的做法是:
- 每个节点启动时记录
start_time和输入摘要; - 节点结束记录
end_time、状态、输出摘要; - 节点间传递的消息全部落库;
- 在DashBoard上按运行ID查询整张图的状态,快速看到哪些节点耗时高、哪些节点失败频发。
这套可观测性在Graph刚上线时救过我一次。那时候经常有用户抱怨“生成的报告有时完整、有时残缺”,通过图状态追踪发现,问题不是生成环节,而是某个上游数据源在特定时段返回空值,导致下游节点缺输入还硬着头皮跑。纯Loop时代,这类问题靠日志根本查不出来,Graph把环节边界暴露出来之后就好排查太多了。
5. 生产落地的选型决策与实战路线图
最后把三层架构放到“从一个想法到生产系统”的整个流程里,梳理一下怎么在实际项目中做选择、排优先级、控制成本。这一章没有标准答案,但希望给有同样困惑的人一些参照。
5.1 一张表判断你现在该用哪套方案
我用一套自评标准来帮团队快速定架构,不妨直接抄:
| 项目特征 | 该用哪层方案 | 建议架构 |
|---|---|---|
| 单轮问答,无工具调用 | 只需要基础模型API | 什么都不用,RAG即可 |
| 多轮对话+单工具调用 | Harness+单Loop | 一个Runner,保留会话上下文 |
| 多工具连续调用,偶尔分支 | Harness+Loop+简单条件判断 | 优先考虑在Loop里内联逻辑,不急着上Graph |
| 多个工具协作,任务有明确阶段/流水线 | Harness+Loop+Graph | 外层Graph编排,节点内各跑Loop |
| 多Agent并行协作,角色分工明确 | Harness+Loop+Graph+消息总线 | 增加子Agent隔离、通信协议、结果聚合层 |
一个反直觉的结论:对中小型项目,Graph往往是最后才需要引入的东西。先用Loop把单个Agent的认知能力跑通,再拿Graph去组织多个能力,是一条比较稳的演进路径。我见过太多团队一上来就铺开一个庞大Graph,结果节点太多、边界模糊,后期维护比单Loop还难受。
5.2 Loop精调的实战参数:迭代上限、温度与上下文窗口配置
既然Loop是认知内核,它的参数配置直接影响出品质量。放一组我折腾过的经验值供参考,不是标准答案,但可以作为起点:
max_iterations: 6~10次足够覆盖“初次回答—出错—修复—确认”的典型周期。超过10次还没结果,通常不是思考不够,而是方向不对或者工具链路有问题;temperature: 执行代码或处理结构数据时调低,建议0.2~0.4;做创意生成时再调高到0.7以上。但要注意,很多工具类Agent在低温度下表现更稳;context_window_usage: 上下文使用率超过80%时,强制进入摘要模式,避免越界;timeout_per_step: 单次工具执行30~60秒比较合理,太长会拖垮交互体验;observation_truncation: 单次工具返回内容超过20000字符就做截断并保存外部文件,然后给Loop放一个文件路径让它按需读取。
这些数字来源于我在不同模型上的多次对比,模型换代以后数值容易变,但原则不变:给Loop设上限、设超时、设降级策略,别让认知循环无限膨胀。
5.3 成本构成与并发控制的平衡
生产环境里Agent的账单结构通常有三块:模型推理token费用、工具执行计算资源、外部API调用费用。我做过一次成本拆分,对一个“数据分析+报告生成”任务,单次完整流程大约是15万到25万token(含中间观察结果),其中Loop反馈产生的观察结果占大头。
降低成本最有效的手段就是减少无效Loop。比如在“观察阶段”就做结果质量判断,如果发现上一步返回的数据与预期偏差太大,可以提前终止后续分支,不用让Agent继续硬编。另一个手段是缓存——对于频繁重复的工具结果,比如查询某个固定配置、读取某个静态文件,直接在Harness层做结果缓存,Loop不需要每次都真实执行。
并发控制与成本是直接挂钩的,因为没有限制的并发会让模型API调用出现尖峰,不仅推高账单,还容易触发限流。一个生产系统上线初期的保守配置可以是:全局最大并发4~6个Agent任务,单Agent内Loop串行执行,工具执行Worker池不超过4个。等监控数据跑顺了,再逐步放大。
5.4 三层架构中最容易翻车的三个“细节税”
讲了这么多方法论,最后说三个每天都在偷偷增加系统复杂度、却被忽略的细节。
第一个是上下文里堆了太多“漂亮话”。很多Agent提示词模板喜欢写“你是一个乐于助人的AI助手”“请认真思考”“如果用户输入不明确请主动询问”,这些指令在单轮对话里没问题,但放进Loop后每一轮都会重复消耗token,还会让模型在已接近目标时不断“礼貌地确认”,导致循环迟迟不结束。我现在倾向于让提示词走极简风格,目标指令和工具说明用最简短的表达,translated到生产里的效果反而更干净利落。
第二个是工具的返回消息没有统一规范。Loop里的模型是根据Observation内容来做下一步决策的,如果不同的工具返回格式五花八门,一会儿JSON、一会儿纯文本、一会儿Markdown,模型推理的成功率会直线下降。我要求所有工具返回都统一成声明式的结构,包含success、summary、data三个字段,模型决策就不容易被噪声干扰。
第三个是多个Harness实例共享同一个内存状态库。如果你部署了多副本Agent服务,又用了本地文件作为会话存储,用户请求被负载均衡到不同副本时就会遇到上下文丢失。解决起来倒也不难,把会话状态放到Redis或数据库共享层即可,但这个问题出现得太隐蔽,经常是在上线后被用户投诉“Agent失忆”才发现。
5.5 踩坑之后我给新项目定的“上线前自检清单”
项目我一般会走一遍自检清单,简单但很有效:
- Loop有没有设置次数上限和超时?
- 工具返回结果是否结构化、是否每条都有
success标记? - 观察阶段要不要做结果截断和摘要?
- Harness有没有做权限隔离?高危工具是否需要二次确认?
- Agent在生产环境沙箱里能执行Shell吗?网络策略是否限制外联?
- 会话状态存哪里?多副本部署时是否会串号?
- Graph节点有没有埋点和状态快照?
- 任务中途挂了能不能从最近节点恢复?
- 并发跑满时下游系统会不会被打爆?
这些问题看着琐碎,但任何一个在生产里爆炸都会牵动整个系统。三层架构的价值从来不是“概念上的优雅”,而是“每个环节都能被独立测试、独立恢复、独立观测”。记住这句话,Agent项目就能少走很多弯路。
我之前一直觉得“Agent工程”是个很虚的词,但把Harness、Loop、Graph这三层拆开以后,发现它完全可以像普通后端工程一样被设计、被压测、被运维。Loop里面的每一步意图传递,Harness里的权限拦截,Graph里面的分支状态,全都是有明确归属的工程问题。现在如果有人再问我要不要上Agent,我一般只问一句话:你的系统能不能跑通一个Loop?跑通了,我们再加Graph;跑不通,先把Harness和Loop打磨干净。这条路走下去,生产落地是真的会被执行出来的。