案例库/完整蓝皮书

东方屹腾 执行型 Agent 从零到稳定交付

案例提供 梁博


一、先把分野划清楚:执行型 Agent 不是内容生成型 Agent

东方屹腾是一家做 SaaS 的公司,原有产品是一套面向企业人事、组织、考勤、审批、薪酬的服务矩阵,往下打通银行端和税局,做一键算薪、网银代发、税局报税,已经稳定服务两万多家企业。大模型起来之后,团队最初的判断跟很多 SaaS 公司一样:把原有的各个 API 接口按 MCP 协议实现成 MCP Server,是不是就能搞出一个机器人,帮用户自动完成那些复杂的业务流程操作。

真正拿几个不算太复杂的核心业务场景去落地,这条路立刻就走不通了,而走不通的原因恰恰是 MCP 的开放和灵活。在 MCP 协议里,Agent 作为 Client 只感知工具、调用工具、把调用结果以文本形式塞回上下文,它不为参数的理解和准备负责,参数的理解和生成全部交给 LLM。这套设计让 Agent 能热拔插地注册各种 Server,在面向大量个人用户的通用助手场景里价值极大。问题在于,东方屹腾要落地的不是内容生成,而是执行。它要的是把用户口语化的业务意图,转成对一连串业务 API 的可靠编排调用——自动搭薪资组、自动搭考勤组、自动算薪并发起代发、自动跑完整套新员工入职办理。这些都是严肃的流程性事务,要准确维护系统里大量业务实体的状态,必须通过严格的 API 接口调用来完成。

开场举的报销例子把这道坎说得最清楚。在费控系统里报销通常是「先创建申请、再上传发票、再提交审批、再查询结果」。人在 GUI 上做这件事毫无难度,因为每个按钮调用哪个方法、绑定什么参数,程序早就钉死了,在刚创建的那条申请记录里上传发票,调用发票上传接口时自然带着这条申请的 id。交给 Agent 自动做,这些显式操作就没了,调哪个工具、准备什么参数全由 Agent 负责。连贯的几步之间不只有业务逻辑上的顺序,入参出参本身就有严格的绑定和传递关系——上传发票时绑定的申请 id 必须是上一步业务系统刚返回的那个 id,不能是任意 id,更不能让模型自己生成一个。按 MCP 那套玩法,调用参数全由 LLM 生成,而 LLM 的生成总是不稳定、会漂移的,加再多 JSON Schema 约束、换再强的模型,它都有出错和幻觉的时候。团队踩过这个坑:把每步调用结果像 tool_call 一样追加到上下文,让模型从上下文里解析绑定下一步参数。实测下来极度不可靠,有时成功有时失败,什么时候失败既不可控也无法预料。这跟 LLM 作为概率模型函数的本质一致——团队要的是确定,确定就不能只靠概率,这在根上就冲突。

这里要给 MCP 一个公道的定位。MCP 本身是极有价值的方案,不是不能做企业级场景,得看场景。像做二级市场股票投研的应用,搜信息、生成报告、生成意见、自动做 PPT,需要调很多外部工具,但每一步传递的主要是文本内容型结果,没有那种严格的机械状态参数绑定关系——先并行查资料、再总结、再喂给报告生成、再接一道评审质检,这跟「查地图→查天气→汇总生成旅行规划」的旅行助手在主干架构上是同一类,MCP 本来就是好方案。东方屹腾把这类归为内容生成型 Agent,把自己要做的归为执行型 Agent:在企业业务系统里自动化交付完整业务流程。两者的核心复杂性不在一个量级,这是整套架构后续所有取舍的起点。

二、业务目标:先否决伪需求,再锁定真痛点

技术架构由业务驱动,所以在谈技术细节之前,团队先解决了一个比技术更难的问题——到底落地什么场景才有意义,不是自嗨的伪需求。

最初讨论时,内部不少同事下意识提的还是生成型任务,尤其是「让 Agent 辅助企业做分析决策」那一类:用工情况分析、薪酬结构优化建议、考勤薪资报表分析。这些能做,也容易出活,还能很快产出视觉漂亮的报告。但团队把它们全否决了。原因是这没抓住给用户带来显著价值的本质。东方屹腾服务的大多是中小企业,甚至本身日常经营里就不做数据分析、不做以数据为依据的决策,连深度服务的几千人规模的中大型企业,也鲜有真要 AI 帮着搞经营分析的。经营决策本质上产生于经营者主持日常经营时完整上下文里的直觉涌现,很少能靠某一块局部表象数据直接分析出有价值的东西。

真痛点在另一头,在那些琐碎的事务操作里。有了这套 SaaS,企业已经不用每月手工拉 excel 核算薪资社保个税了,配置一次之后每月数据没变就一键算薪、一键代发。但仍有用户反馈操作太繁琐、软件学起来太累。深度访谈发现,问题就出在那「一次」配置上——冷启动时要把企业原有薪酬结构配成系统里的薪资组和薪资项,搭好员工和组织、给每人定薪调薪,要想每月高度自动化还得搭考勤组、考勤规则、审批规则,因为这些都是算薪用得上的数据要素。这一整套对新用户常常望而却步,售前演示介绍完就有人头大。有意思的差异是,凡是派了运营交付团队帮客户搭好的,用户第一个月真用起来之后反馈基本正向。而更极致的用户进一步希望,连每月进几个页面点「一键算薪」核对、再点「一键代发、一键报税」也省掉,授权给机器自己核对自己干。

这条线最终收敛成一个有明确价值的定位。很多小企业老板希望的薪酬管理场景就是一句话:「有这么一个员工,我希望以每月 1 万元的实际综合成本使用这个人力资源,具体薪资项、社保、公积金的细节是多少,我都不想了解也不想看到。」这才是该落地的服务定位。老板需要关注的就是「1 万元每月使用了一个人力资源」,而系统侧要保障业务数据清晰、用工合规——自动为这个人力资源配好基本工资、补贴、奖金这些薪资项,准确核算社保公积金,准确完成薪资发放、社保申报缴纳、个税申报缴纳,让没有专业 HR 技能、没聘 HR 的老板也能合规用工。把用户不想关注的复杂性封装起来,内部逻辑严谨完善,这是执行型 Agent 要兑现的价值,不是摆个漂亮报告在那里。

锁定目标之后还有一条工程纪律:大方向可以是「最终 Agent 无处不在、原有 GUI 交互彻底消失」,但实际落地必须先明确一个最先落地的核心目标场景,用它驱动整个框架和技术细节往下走。这个被选中的第一锚点场景,就是后面贯穿全篇的薪资组快速搭建。

三、渐进式起步:让问题推着思考走,前端尽早做精美,可观测性先行

后端语言选了 Go,不用任何现成的 Agent 开发框架,原因不展开。真正值得分享的是起步方法论:大目标锁定后,一次只落一小步,让出现的问题和与目标的差距推着思考走。一上来就把注意力放在复杂的工具编排和严格调用上,牵扯的复杂性太高,心智负担陡升,很容易做不下去。有经验的工程师都清楚,很多项目的难点恰恰在起步阶段——脑子里太多复杂性和场景考量,生怕考虑不周埋下早期技术债,对怎么迈第一步既踌躇又惶恐。第一步迈出去、工程获得良好起始之后,在明确核心业务目标的指引下,后续演化往往水到渠成。

第一步就从最简单的地方开始:先把用户对话和 Agent 答复这套基本数据管道接通,让人能和 Agent 连续对话即可。注意力不放在技能工具怎么定义、怎么注册、怎么被自主使用上,那些都往后排。

这里有两条来自企业落地的经验,跟个人开发者自由发挥很不一样。

第一条是前端要尽早同步做,而且要在交互和样式上多花精力做精美。个人开发者爱看命令行无可厚非,但在团队和企业里落地一个项目,尽早把展示界面按真实情况做漂亮,对提高开发效率、降低公司内部阻力至关重要。一个像样的前端会给团队提振信心,碰到长期攻坚的技术难题时减轻挫败感,因为每次看到它都觉得已经像个产品了。更现实的一面在企业内部:项目启动一个月后就会有人没耐心,业务侧、市场侧的同事也会开始关注,他们不会耐着性子听你在命令行或代码里讲落地了多牛的设计,只会从可展示的前端去体会。每个阶段都能看到美观像样的页面,外部阻碍就小很多,甚至能换来资源。反过来,废了九牛二虎之力实现复杂机制,可能只因一个页面样式不好看就被人觉得团队 going nowhere。现在有 AI IDE,尽早做个漂亮前端并不难,这事应该早做。

第二条是一开始就把可观测性搭足,这是重点推荐的经验。这里的可观测有特定语义,指的不是 Agent 对它所处世界的观测,指的是让 Agent 的意识和行为对开发者自己可观测——完整展现一次对话里 Agent 产生的一系列行动,以及驱动这些行动的思考和推理,即它的精神活动和躯体活动。具体落地是把一次对话的整个执行过程按时间轴清晰展示出来,而不是只在用户输入和最终回复这两层做展示、中间过程全黑盒。对每一步,既要看到 Agent 产生了什么动作,也要按时间顺序看到这一步的 LLM 调用细节——运行态实际用的提示词、LLM 的输出、这一步相关的各种成本。对动作这一侧,做法是把 Agent 的活动和程序逻辑全部封装抽象成带语义的事件,比如用户意图识别、意图网关路由判定、ReAct 执行。这些调试详情在生产投放时可以关掉,开发态时在前端打开。这样开发体验就接近于在一个透明玻璃罩里组装或修理一块瑞士机械手表——虽然复杂精细,但总能直接看到每个零件在哪里工作,系统越复杂越能压住心智负担。这一块的深度落地见 G5 可观测性切片

对话管道通了、附件能上传了,相当于 Agent 的主要输入进来了,再把完整的可观测基础设施铺好,就具备了往上逐步堆能力的地基。

四、二元论:先把活的不确定的,转成死的可控的

往上堆的第一个能力是意图识别。这属于感知,但这里要的感知更进一步——理解了用户对话不能就反馈对话结束,得在这里明确拿到控制信号,用来选择驱动 Agent 往下游走的逻辑分支。最核心的工程逻辑是:以用户对话为输入,用提示词引导 LLM 返回结构化输出,把用户意图收敛抽象到系统内可接纳的几个下游控制信号上。

早期落地时识别出三种基本意图。一是闲聊,专业垂直场景的 Agent 预算有限,要防止用户拿它当通用助手用,识别出明显与领域无关的闲聊就尽快拦截结束,不发起后面高成本的推理和行动。二是咨询业务知识,比如上传一张薪资表想让 Agent 分析分析,这类不需要复杂推理和行动规划,检索一下配套领域知识再结合输入调一次 LLM 即可。三是要理解意图并准确编排一系列工具完成目标任务,这才是核心场景,需要更复杂的推理和行动。这三种早期定为 chat、analyze、resolve(后来按更贴合下游业务逻辑演化成 task、information、produce、chat 等更丰富的信号)。因为 LLM 不可靠,这里设了兜底:意图没解析到就统一打成 unknown,下游配套 unknown 的兜底逻辑。

就在第一个意图识别环节落地时,团队已经看到了一件雏形——一个能力环节的输出里存在分离的不同平面。这会儿能识别出的就有控制平面和叙事平面。Agent 在各个推理和合成环节感知叙事平面,而 Agent 的运行逻辑靠稳定的控制平面来驱动,思想跟 K8S 里区分数据平面和控制平面是一样的。

这条二元论是整套系统的认知地基。对刚接触 Agentic 开发的人,理解它是一次关键突破:把自己从纷繁复杂的「智能」「不确定」思维里解放出来——先把活的、不确定的,转变为死的、可控的,因为只有死的东西才先能控制。控制平面必须机械化,所谓控制就是机械。叙事平面也有它的控制机制,但那是一系列语义压缩、拼装、写入、读取注入的事,不是严格的机械状态控制,是「驾驭」。驾驭的对象或多或少有你不能完全掌控的细节,像骑马,靠设备加骑术让它大部分时间按你的预期行动,但你不太确定它脑子里在想啥、会不会突然撂挑子。这两个平面并行,才构成基本的 Agentic 系统:没有明确控制信号系统工程就驱动不起来,而叙事上下文不断作为各环节推理的输入,又再次产出不同层次的控制信号。

意图识别本身怎么做深,见 R2 复杂度路由切片

五、Orchestrator:所有能力的家,加上意图网关的拦截路由

拿到意图识别的控制信号后,要根据不同信号走不同执行流分支,这里自然浮现出一个关键架构组件——Orchestrator,整个运行态执行流的编排器。它是 Agent 运行的核心骨架,一切能力都挂载注册在它上面:从拿到用户对话输入开始,解析获取链路上的控制流信号,按信号编排各环节动作,可能是调用 Agent 的其它能力、在某环节蒸馏记忆、检索外部知识、判断本次对话完成并合成最终回复。Agent 表现出的理解意图、有记忆、能总结经验、能调技能工具,本质上都是在幕后这棵严格精密的控制流树干上长出的枝叶——这是传统工程就熟悉的事,LLM 带来的增量是可以在各种边界上把自然语言信息收敛锚定到控制信号上,从而驱动看似无限自由的智能活动,但每一步其实都在不断给它套上枷锁。运行过程就是发散、收敛、再发散、再收敛。

工程实现上 Orchestrator 不必暴露在最外层。最外层封装一个 MessageHandler 薄门面,它承接用户输入再转给 Orchestrator,并专职负责给用户展示层的能力。Orchestrator 执行时自由发出符合统一结构规范的活动事件,MessageHandler 在一个通道里监听这些事件、用 SSE 渲染输出,让用户看到打字机效果的执行流和对话流。这些「表演逻辑」不耦合进 Orchestrator,让它专注控制。这正好体现选 Go 的好处——用原生协程和通道实现这种事件发布订阅非常容易,其它主流语言当然也能做,但要写更多代码。

有了编排者,意图识别又产出了控制信号,下一步是定义信号的消费者。这很自然映射到一种拦截和路由模式:消费者是一个意图网关组件。有了它,chat 直接以编排好的机械式对话结束(只要愿意,连回复都不必调 LLM 合成),analyze、resolve、unknown 各自编排不同的下游执行链。意图网关的输入是控制信号,输出是明确的下游活动编排链。大的入口边界总是确定的。总入口接原始对话、先定意图,是 pre 阶段。结尾合成返回用户的对话,是 post 阶段。中间的 middle 阶段才是可灵活编排的部分。Orchestrator 落地之后,各项能力单元就都有了家,可以专注往上堆。

六、推理:链式推理,每步既贡献叙事又产出控制信号

意图 resolve 代表要具体理解用户意图、完成交代的任务。但意图只是粗略信号,没有清楚描述也没收敛到可执行的控制信号,所以下一步要进一步理解意图、尽快映射到能解决的问题空间,这就要落推理和行动。

推理这一环用的是链式推理(Chain of Thought):引导 Agent 一步一步思考,观察上一次的思考结果再思考,直到超出设定步数或 LLM 认为推理完成。到这一步能清楚体会叙事平面的定位——推理的原料不只是几个控制信号,而是完整的上下文语义。从上游往下传的既有控制信号,也有完整的叙事状态:调用 LLM 做推理的输入既包括用户原始输入,也包括意图识别阶段产生的结论。泛化讲,凡是调 LLM 唯一干的事就是对话和推理,复杂的控制流和操作都得自己在程序里实现。所以这一环在输入上既接上游控制信号,也接叙事内容,团队把组装好的叙事输入命名为 ReasonContext,是一个包含各语义层次内容的复杂结构体(最早只有两三个字段)。输出仍是老套路——收敛回结构化输出,才能准确驱动再下游的行动。

这里有一条关键约束:链式推理产出的控制信号要明确指明下一步能先做什么行动,并且能跟程序里的可调用逻辑映射起来(检索知识库、调某个工具技能、进一步规划任务、继续推理、或直接结束对话)。注意只产出「下一步行动」,不必产出全部行动——一旦行动发生世界状态就变了,要结合目标和最新上下文再决定下一步,过早决定既没必要也定不出来。任务和目标是一步步渐渐清晰的。链式推理怎么做深,见 R1 思维链切片

七、行动:ReAct,工具调用封装在行动能力之内

推理推出了「下一步」就要交给行动来承接。直接用对应函数承接当然能编码,但不符合这个场景的演绎——推理只推了一步、还要干一步看一步,所以行动能力本身得兼具推理和行动,干一步、看一步、没达目标再干,不断趋近目标。这意味着工具调用要封装进行动能力里,而不是裸调。这是工程演进里自然长出来的,也正是 ReAct 行动模式。

落地上,ReAct 的每一轮有明确的 Thought、Action、Observation 数据结构,三件套作为一个 block 追加到一块叫「草稿纸看板」(scratchpad)的结构上,后面的步骤通过读 scratchpad 的 block chains 沿着之前完成的事继续推理。每一步根据推理产出的控制信号在 Orchestrator 中完成一个实际操作——可以是调工具技能、检索知识库、甚至再调一次 LLM 推理——干完了对照用户目标看进展如何,循环进行。所以技能、工具调用都不在 Orchestrator 层裸调,而是封装在行动能力中,因为一次调用其实有环绕它的很多能力和场景要处理。控制信号怎么设跟自己场景最相关,理论上设一个「有内鬼,终止交易」之类的信号都行,下游可以直接关闭通信流、连对话都不返回——有了 Orchestrator 这很容易做到。工具调用与机械状态坐标声明怎么做深,见 A1 工具调度切片

八、规划执行:被 ReAct 的跨步漏步逼出来的

ReAct 和上层编排器到位后,一个能推理、能行动的 Agent 已经活了。这时先用 mock 接入工具、技能、知识库的调用契约——接口按生产级别完整设计确定下来,数据和调用先模拟,等能力齐了再接真实外部能力。重点先放在 Agent 能不能在语义上正确召回该找的信息、工具和技能上。

就在 mock 阶段,团队验证薪资组快速搭建场景时发现了下一个要落的能力。这个场景是:用户表达薪资组诉求后,通过向量数据库匹配到语义最贴近的薪资组模板,先给企业原有薪资组数据建快照、确认快照建立后再导入模板、导入失败用快照回滚。这一串顺序不能乱、有严格递进依赖,跟报销那个例子是同一类。最初设想很自然:把所有 API 描述成工具,在技能里描述每个场景该怎么编排,把「先调哪步、再调哪步」作为叙事上下文喂给 Agent,期望它在 ReAct 里自己跑出正确顺序。听上去合理,实测不行——技能编排作为叙事上下文给到模型后,它有时跑对、有时明显跨步或漏一步,导致任务不符合预期。根因还是 LLM 的不确定性,把执行顺序交给概率模型临场判断,没法保证每次都对。

于是识别出还缺一种行动模式——规划执行,把要完成的几步先明确规划下来钉死,而不是走一步看一步。它的落地复杂度比 ReAct 高一个量级。ReAct 的核心控制结构本质是一个带退出边界的链式循环,概念懂了数据结构容易写。规划执行要明确规划并管理连续多个任务的调度与依赖,得维护更复杂的任务规划与调度状态。核心构件有任务 DAG 图、规划器、执行器、验收器,以及任务状态机和任务图状态的动态维护机制。最花功夫的是任务状态机模型——每个节点有自己的状态,下游节点能被调度启动的前提是它依赖的上游节点全部 completed、且本节点为 ready,整套调度语义靠这台状态机驱动。书里给得了概念抽象、降了不少心智负担,但给不了这种底层工程细节,这块是团队额外花了较多设计心血才做好的。控制权在 Orchestrator 和具体行动模式之间流转——ReAct 跑着跑着发现脉络清晰了,可以规划成若干并行或串行任务,就把控制权交还 Orchestrator、切到规划执行。两种模式不必二选一,按任务的清晰程度切换就行。这一块怎么做深,见 A2 规划执行切片

九、治理:HITL 关键任务阻塞与人审续作,借状态机水到渠成

实现了那套复杂的任务状态机制后,有一个绕不开的企业级场景顺理成章就能接上去——对敏感或危险操作做人在回路(HITL)的控制:执行流走到某个关键位置要阻塞等待人工审批,审批通过后能完整恢复刚才中断的上下文执行状态,由 Agent 最终完成执行。

这个泛化场景常见,但不同业务下复杂度不一样,可细分成两种形态。一种是人审续作只涉及叙事状态——像 AI Coding IDE 里 Agent 形成了方案但担心破坏原有逻辑,本轮对话结束、问你是否确认,你在下一轮输入「继续」或「确认」,它根据会话里完整的叙事上下文继续完成。这种本质还是根据叙事上下文生成内容(写代码就是维护文本文件内容),工程上容易实现,只要结束本轮、让用户在下一轮继续发起叙事性自然语言对话即可。另一种更复杂——Agent 此刻要在本地终端跑脚本或命令,它不结束本轮对话,而是阻塞当前执行流、弹出看板问你是否 Accept,点了 Accept 执行流从阻塞处恢复。这种要先建任务状态模型、落任务状态机,还要维护一次规划产出多个任务时某个任务阻塞后任务图全局和下游节点的状态。如果只有 ReAct,要实现这套机制得专门思考一整套。而落地规划执行后已经天然有了任务 DAG、状态机、调度器、执行器,进一步实现关键任务或关键工具调用时的阻塞和人审续作就很容易,水到渠成,还能用声明式配置来维护哪些关键任务或工具调用需要阻塞人审。这一块怎么做深,见 G1 审批门切片

十、机械状态平面:这套系统最核心的复杂性

把真实 API 接上、配上真实技能和知识库去交付薪资组搭建场景时,跑不通。问题在于到这一步为止,Agent 虽然能规划出有依赖关系的几个任务,但在任务之间的状态一致性和传递上,仍处于类 MCP 的形式——第一个任务调成功后把结果组装进对话上下文,让第二个任务从最新上下文里获取并绑定参数,依次推进。旅行助手型 Agent 可以这么玩,因为它传递的参数偏文本。从一长段聊上海的上下文里让模型生成一个 city 参数,很难出错。天气数据结构稍复杂,从「中雨」漂移成「有雨」也问题不大,因为它是作为下游叙事性输入参与生成型任务的,语义偏差不致命。

东方屹腾的场景不一样。薪资组搭建的第一步根据用户 id、企业 id 等会话信息加上用户输入的业务目标,调模板匹配接口,匹配到合适模板会返回 template_id,下游导入模板时必须准确以这个 template_id 作为入参。差异就在这个 id 上——企业里各种 id 普遍是雪花算法生成的 64 位甚至 128 位随机字符串。让模型感知对话内容后准确原样生成出这种 id 极具挑战,相当于问它「strawberry 里有几个 r」那道经典题难上百倍,等于问它这个 id 里每一位具体是啥、一位都不能错。纯调大模型原样生成一个 64 位随机 id,到今天仍不能顺利完成,这是 LLM 的本质决定的——它是无状态的概率模型函数,每次调用都是一次新的生成,你即便在上下文里告诉它 id 值,它也不会「取用」你的参数,它只会「尝试生成」你的参数。「上海」这种 token 在各模型里权重极大,而那种随机字符串模型很可能生平第一次见,让它生成出错概率极大。在这个场景里 id 缺一位会校验失败导致执行失败,错一位更严重——可能 Agent 执行「成功」,实际却破坏了业务数据,且没有完成期望的状态改变和场景交付。

这块怎么解,设计模式书里没讲,市面现成资料里也找不到现成方案——资料里几乎都是 MCP 那套让 LLM 按 JSON Schema 生成参数的玩法。所以这是东方屹腾落地过程中曾面对的最核心复杂性,是它自己场景特有的、前人还没公开解过的问题。

经过一段时间的思考、设计和试错,最终的解法是严格识别并分离出 Agent 整个运行过程中的机械状态平面,把业务 API 调用里的状态读写和绑定传递完全跟 LLM 参与的内容分离,也不让 LLM 生成,而是在 Agent 各执行环节根据工具调用回执机械性地准确维护。这些参数和状态值不再混在叙事上下文里由模型感知再生成绑定,而是在全局状态里明确划出一个专门负责状态值读写取用的平面,命名为机械状态平面,因为这些值是严格、稳定、一致的。

这个解法能成立,前提是这套系统是一个企业级封闭体系——不需要也不希望用户任意接入外部工具,所有工具都由团队自己管理和注册。这意味着 Agent 启动时就能确定它所感知世界里所有可能的状态键字典:有系统级的(用户登录会话里的身份、权限信息),有 API 接口级的,此外几乎没有别的需要写入读取的状态键。所以只要定义规范好技能和工具注册时的描述协议,在所有工具技能注册环节把所有可能的键在机械状态平面注册好即可。系统级的状态(如用户会话信息)则在相应关键事件处写入,比如用户登录时。

更关键的是坐标。每个工具声明自己的机械状态参数依赖坐标——它需要哪个参数、key 是什么、该由哪个工具在哪个运行层级产出。每个工具既是机械状态平面的生产者也是消费者。机械状态平面只负责键名和作用域共同确定的键坐标的唯一性,以及键最新状态的维护。每个工具需要取哪个坐标的参数,由它自己声明和校验。可以想象成 Agent 启动时就维护好一整墙小格子,每个格子对应一个机械状态参数,每个 key 用「参数供给者 + 产出的运行时环节」唯一描述,每个格子里按会话时间轴维护最新值即可,消费者要哪个状态就自己去对应格子里读。运行态里每个参数都对应一个 Provenance 结构体,是由各项规范和描述解析组装成的唯一坐标,是这套机制能可靠稳定工作的核心。配套的执行链路是:Skill 声明 SOP,Workspace 保证顺序,Tool 声明状态的生产与消费,SessionState 存值加 Provenance,RunPipeline 统一解析。

这样这个场景就拿到了极其稳定健壮的解——一切交给严格的上下文数据结构和程序负责,不再由会漂移的 LLM 生成参数。而且原有的所有 SaaS API 不需要任何改造,只要通过网关暴露出来就能被 Agent 感知使用,按不同场景灵活编排组合任意数量、连贯调用的 API,完成复杂业务场景的完整交付,不会发生参数写入读取绑定的错误。这一块的工程切片对应在 A1 工具调度 里。

十一、会话统一状态平面:三权分立

随着叙事平面和机械状态平面被明确识别并具象落地,团队对整个运行态上下文体系有了更清晰的划分,最终稳定成主干设计——一套三分法的会话统一状态平面。除了前面已定义的叙事状态平面和机械状态平面,第三个平面其实早已实现,只是之前没把它作为一种上下文状态单独定义出来,那就是规划执行模式里负责任务状态和调度的那套上下文。最早建这套上下文时叙事状态混在里面,每个节点的任务结果详情也在里面读写传递。现在做了明确分离,任务执行过程中产生的副产物分别进叙事平面和机械状态平面,而任务调度状态只管调度编排语义。

三权分立各管一段,边界清楚。

叙事状态平面(SessionNarrative)用自然语言始终汇集整理发生过的事,回答「用户要什么、做到哪了」。有些信息全量保存,有些压缩蒸馏后保存,有些只在内存,有些持久化到 DB 甚至建嵌入向量索引存进向量库。它由锚表和账表做持久真源,写入方是 AnchorRepository 和 appendLedgerEvent,读取方是 Distill 投影出的 LLM 前缀和最终回复。它不负责调度态、机械状态和参数校验契约,只负责 Agent 对世界和当前状况的感知理解。这一平面的核心三件套见下一节,深度切片见 M3 进度追踪P1 上下文分诊

机械状态平面(SessionState)专管整个 Agent 的机械参数字典,回答「API 参数从哪来、对不对」。存的是 Cell 模型——scope、key、value、producer、provenance,数据性格是严格键值和契约,持久真源是 Timeline 事件物化成的 Cell,在各环节监听机械状态参数事件、通过 SessionState Manager 更新。读取方是 RunPipeline、治理和前置条件校验。它不负责调度图、叙事和记忆。

任务调度状态平面(Workspace)只关心任务 DAG 图里节点的顺序和状态,回答「先跑哪步、跑完没有」。下游任务能被并发调度启动,前提是上游节点全部 completed、且本节点为 ready 这样的调度语义。

把这三件事分开——「用户要什么做到哪了」用自然语言、「API 参数从哪来对不对」用机读、「先跑哪步跑完没有」用调度图——是这套系统能稳定交付的根本。企业级执行型 Agent 的难点从来不是会不会调 API,而是在不可改造接口的前提下让每一步 API 的参数都有唯一、可审计、可 fail-fast 的机械来源,会话统一状态平面就是这套来源的工程答案。

十二、叙事平面的核心三件套:锚、账、集

叙事平面从意图识别阶段就出现了,对没深度上手 Agent 落地的人比较抽象,它的核心语义内涵可以概括为一种「目标与进展的描述」,像一份工作笔记——Agent 一边执行一边记录都干了什么,同时提醒自己不忘初心牢记目标。它由三个核心要素构成。

锚(anchor)锚定用户每个会话和对话的原始输入作为不变的顶层目标。为什么要这个锚?因为这是解决复杂业务场景交付的 Agent,执行链路很长,从入口接到原始请求开始一路经历推理、行动、任务规划,信息向下传递时不断被加工扩写或压缩蒸馏。如果叙事内容纯粹是上一步输出作为下一步输入的链式单程传递,路径一长就会慢慢偏离原始目标——到任务规划阶段,用于生成计划的输入可能已经变成推理过程里的思绪内容,而用户目标反而占比很小。还有一种常见情形:先完成一轮对话问用户是否继续,用户下一轮只发了「继续」两个字,Agent 开始推理时很可能偏离本质目标,要么理解不了什么是「继续」,要么按自己理解的「继续」直接瞎干。所以每一次推理上下文里都要把用户原始目标作为固定数据传下去。

账(ledger)是一个连续摘要追加记录的关键进展纪要——对完成的关键里程碑推理或行动做语义压缩摘要后存储。靠后的步骤在知道用户目标的同时,还必须知道前面干过什么、取得了什么成果,以此推理本步要完成什么。

集(collection)是在一些关键推理环节,对账这个台账再做一次蒸馏投影形成的内存临时信息。即便账已经是蒸馏后的信息,链路一长仍会堆出较长上下文,不可能把全量塞进 prompt。所以在关键推理环节,根据当时要注入的场景从账里投影裁剪出一套临时信息,与锚一起注入。这样 Agent 既掌握之前的重点里程碑,又不占过大上下文——就像接手工作时,前面步骤由别的同事分别完成,你需要了解的是他们完成了哪些关键里程碑,而且你只关注跟手头任务最相关的那些。这个「关键推理入口处做蒸馏投影、注入裁剪后 collection」的动作,深度切片见 P1 上下文分诊,锚-账-集三件套的进度语义见 M3 进度追踪

十三、记忆体系:L1/L2/L3 分层与经验教训召回

让 Agent 在企业级场景里更好地工作,还要各种配套体系,记忆体系是必不可少的一块。团队把记忆分成 L1、L2、L3 三层。这里值得提的是 L3——它保存的是经验教训类语义信息,在任务执行成功或失败时对当时的叙事上下文状态蒸馏总结后产出。这些信息对推理有帮助。某个场景之前已发现用哪个 skill 能解决,这次推理就能很快收敛,是一种似曾相识的同类任务检验。反过来,如果之前某个中间环节接口调用失败了,这次任务规划可以先调健康检查接口确认 API 已恢复再编排执行,免得一些重量级场景的前序任务白白执行。

落地经验是不要每一步推理都召回记忆,那成本太大。做法是在流程的关键推理入口处做 L3 召回——链式推理的首次推理、ReAct 的首次推理、执行任务规划时,这些大的能力边界入口最需要全面参考信息,第一步在更全面的信息下走对了就容易一步对步步对。另外,L2 记忆持久化在 DB,L3 记忆在向量库里用嵌入语义索引,L3 的数据结构里可以保存指向 L2 原始记忆事实的 id,需要 L3 经验片段当时的具体源信息时再召回详情。这跟设计模式里那套类似操作系统内存页卸载与加载的理念是一致的,是那个模式的一种具体实现。L3 经验教训与关键边界召回怎么做深,见 M1 分层保留切片

十四、架构全貌与迁移指南

把这条线从头看下来,整套系统是这样长出来的。先划清执行型与内容生成型的分野,否决伪需求、锁定真痛点。再从一个 ChatLoop 起步,前端尽早做精美,可观测性先行。在意图识别处发现控制平面与叙事平面的二元论,立起 Orchestrator 作为所有能力的家,配上意图网关的拦截路由。往上堆链式推理(每步贡献叙事又产出控制信号)和 ReAct(工具封装在行动能力内)。被 ReAct 的跨步漏步逼出规划执行(任务 DAG 加状态机),又借这台状态机水到渠成接上 HITL 关键任务阻塞与人审续作。最后面对最核心的机械状态参数绑定问题,立出机械状态平面(Provenance 坐标 + 生产者消费者 + 工具注册声明依赖坐标,原 API 无需改造、fail-fast),把整个运行态上下文收敛成会话统一状态平面的三权分立,再配上叙事平面的锚账集和 L1/L2/L3 记忆体系。这套东西可以算作 Agent 设计模式的一次具象实现——感知、推理、行动、记忆、反思、协作、治理这些能力在书里有概念抽象,团队做的是把抽象落成真实的数据结构和代码,再补上书里没法面面俱到的底层工程细节(任务状态机、机械状态平面这些)。

什么条件下别的 SaaS 可以迁移这套架构。最硬的判据是看你的场景是不是执行型——任务步骤明确、步骤间有严格的依赖和状态参数传递、且跨步漏步或参数错一位会直接导致交付失败或破坏业务数据。满足这些,控制平面与叙事平面二元论、Orchestrator、规划执行、尤其是机械状态平面这一整套就值得照搬。机械状态平面能成立还要再加一条前提:你的系统是一个企业级封闭体系,工具由你自己管理注册、不让用户任意接入外部工具,这样才能在启动时确定所有可能的状态键字典,把参数坐标钉死。

反过来,如果你的场景是内容生成型——查资料、总结、生成报告那一类,步骤松散、容错度高、步骤间传递的是文本内容而非严格机械参数,那 MCP 本来就是好方案,不必引入任务图、状态机、机械状态平面这套重机制,硬上是过度设计。两者的核心复杂性不在一个量级,迁移之前先把自己的场景归到正确的那一类,是用好这套架构的第一步。


这是 ADPS 蓝皮书(企业落地实践)。返回 案例库模式矩阵