Pentagi:五阶段引导式交互,让AI Agent长链路任务稳定可控
2026/9/17 21:55:45 网站建设 项目流程

我去年年底接手了一个半成品的 Agent 项目,核心痛点就一句话:模型一旦要在多步骤任务里连番调用工具,状态就乱成一锅粥。后来我把整套交互流程按“五个阶段”重构了一版,顺手开源了它,名字就叫 pentagi。这个名字我拆着念:penta 是五,gi 是 guided interaction,也就是“五阶段引导式交互”。它不是什么花哨的框架,本质上就是给智能体任务装了一套清晰的状态流转规则:从接收任务到最终交付,每一步都走固定的生命周期。今天这篇就是我自己的完整复盘,从设计思路到能跑通的配置单,再到我踩进去过的几个深坑,一次性写清楚。

这个方案特别适合三类人:一类是正在做大模型工具调用、但总被“模型乱调参数”“中途跑飞”折磨的工程师;第二类是想要一套可落地、可审计的 Agent 流程规范,不想从零发明的技术负责人;第三类是看了 LangChain 之类现成框架,但不想被框架套死、想自己掌控状态流的人。如果你只是想让聊天机器人陪聊,那 pentagi 用不上,但只要你开始给模型接数据库、接 API、接代码解释器,它就能帮你把后半段路走稳。

1. 先搞明白:pentagi 到底在解决什么问题

1.1 一个典型的“长链路智能体”翻车现场

我先描述一个场景,你大概率遇到过。你丢给一个基础版 Agent 一个任务:“帮我把这份销售数据 CSV 处理一下,算出各区域环比变化,再画一张柱状图,最后把结论写进 Markdown 报告。”模型一开始很兴奋,先调 pandas 读文件,接着开始算数据,然后它会自作主张去调一个画图函数,可这时候它已经忘了前面中间变量的确切列名,于是代码出错。更麻烦的是,出错之后它进入了一种“自我修复循环”:反复换库重装、反复改参数名,甚至开始一本正经地编造出“数据处理完成”的假象,但实际上输出文件根本不存在。

这类现象的根因不是模型智力不够,而是整个执行过程缺少阶段约束。每一步该做什么、该输出什么结构、该往哪个状态桶里写结果,都没有人告诉模型。模型就像被放进一个没有分区的办公区,什么资源都能碰,但每件事都干到一半。pentagi 的解题思路就是强行把这条长链路切分成五个专门步骤,每一步都有明确入口和出口,并且所有中间状态都以固定格式落盘。状态一清晰,追溯和回滚就都有了依据。

1.2 我把它当成“协议”而不是“框架”

很多 Agent 项目一上来就是配置 Agent 基类、注册工具链、跑 Action 循环。pentagi 不太一样,它更像一套协议。它关心的不是某个具体工具怎么实现,而是工具调用这件事在流程中处于哪个阶段,前一个阶段产出什么,后一个阶段希望收到什么。

这套协议的五个阶段从设计图上看非常规整:P1 解析原始输入;P2 输出结构化的行动规划;P3 进入工具调用执行环节;P4 对执行结果做验证与修正;P5 汇总成最终交付物。命名上我沿用了“阶段+意图”的组合,P1-P5 既是数字序号,也是状态机里的强 ID。任何一条请求,一旦进入 pentagi 的运行管道,就必须按这个次序走完,不允许跳级。想要在中间插入一个外部干预接口?可以,但只能挂在某个阶段内部,不能打破阶段顺序。

之所以称之为协议,是因为它不限定上层有多少个 Agent、底层用哪种大模型推理、工具是基于函数还是基于 MCP。上层业务可以把十几个子 Agent 铺满,底层今天用 GPT、明天换本地模型,协议层始终保持不变。这也是我后来推荐给团队时最有说服力的点:替换组件不会引发流程重构,廉价且安全。

2. 五阶段设计与背后的“为什么”

2.1 阶段一:任务解析(P1)——先让模型学会“复述确认”

很多 Agent 项目的默认第一反应是问模型:“你要干什么?”然后直接让它干活。pentagi 在 P1 阶段强调的是“复述确认”和“要素抽取”。模型拿到一段不规范的原始需求后,不能直接开始调工具,必须先输出三个结构化的字段:任务目标、约束条件、可用的资源项。如果原始需求缺某个字段,模型要主动向调用方请求补齐,而不是自作聪明地猜。

为什么要这么苛刻?因为大模型在处理模糊输入时,很容易把“最可能的解释”当成“唯一确定的解释”,进而带着幻觉进入后续所有环节。一旦任务目标在没有任何确认的情况下被执行,后面每一步的纠错成本都是指数级上升的。我在 P1 里加了模板约束,让模型必须输出一个 JSON 块,比如:

{ "task_goal": "计算2024年各季度销售额的环比变化率,输出柱状图", "constraints": ["输入数据来源为 sales_2024.csv", "输出图片为 png 格式", "禁止删除原始数据"], "resources": ["本地CSV文件", "Python运行环境", "matplotlib库"] }

这个模板看起来机械,但它能逼着模型在动手前和自己对峙一遍:我真的理解任务了吗?值得强调的是,P1 的输出要写入当前 request_id 对应的 state 文件,后续所有阶段都能回看。

2.2 阶段二:规划编排(P2)——不能用“感觉”,要用“行动清单”

任务确认之后,最考验 Agent 架构的其实就是 P2。这一阶段模型要做三件事:拆解子步骤、识别每个子步骤的依赖关系、选择每个子步骤期望调用的工具或能力。最后一个非常关键:模型在规划时就要提前“点名”,而不是等到执行阶段临时起意。

我从传统项目经理的 WBS 拆解方式里借鉴了很多经验。P2 的输出是一份带依赖关系的计划表,而不是一段自然语言描述的计划。这个计划的 schema 基本长这样:每个 step 都有 step_id、action、tool_hint、dependencies 和 expected_output。有了这五样,后续执行阶段才知道每个动作的存在意义,也才知道执行结果是否合理。如果 P2 没有产出这样的结构化清单,而是输出“我好,我准备处理文件”,那状态机不会放行。

操作中我还有一个心得:P2 阶段要给模型一个“最小动作”的强制意识。比如处理 CSV 的时候,一个完整的动作是“读取文件→检查表头→预览前5行→确认列名→再进入计算”,如果你不提前拆,模型会在一个动作里塞满十几个小操作,一旦中途报错,你很难定位到底哪一步出了错。我在设计里给每个 P2 动作加了“单步输出大小上限”,超过长度就必须再拆一层,这对后续排查非常有帮助。

2.3 阶段三:工具调用与执行(P3)——一切围绕“可恢复”展开

到了 P3,Agent 开始真正动起来。这个阶段要求模型严格按照 P2 计划表的顺序去调用工具,但现实世界总有不按计划走的事,所以 P3 里内置了一套执行中间的容错机制。我把代码里的工具调用层单独封装成一个 registry,每次工具执行都记录参数快照和返回结果摘要,然后把这三份数据一起追加到运行日志里。

这里有个容易被忽略的细节:参数快照不仅仅是把 JSON 打出来,还要记录执行前状态哈希、执行后状态哈希。这样一旦结果异常,可以快速判断是工具内部污染了状态,还是输入参数一开始就错了。P3 的执行上下文不单在内存里,我同时会周期性地序列化到磁盘中的状态文件。项目跑到一半机器重启了,我们还能从最近的快照恢复流程,而不是从头再来。

最后,P3 的每一步执行结果都要给模型一个“下一步选择”:继续执行、回退重试、执行修正计划。这三种分支让整个 P3 阶段具备了动态性,而不是一条路走到黑。但无论怎么分支,控制权始终牢牢锁定在状态机手中,不会出现模型随意绕过后续阶段直接宣布任务完成的情况。

2.4 阶段四:验证回环(P4)——不验证就等于白跑

在项目早期,我犯过一个很典型的错误:工具调用一成功,直接进入结果汇总,完全不检查结果合理性。然后出现了一个尴尬局面,模型调 Python 代码跑出了一个小数点错位的数字,但它还郑重其事地把这个数字写进最终报告,看起来自信满满。后来我把 P4 独立成一个强制阶段,并且加入了两层校验:结构校验和语义校验。

结构校验很简单,检查返回结果是否包含声明过的 expected_output 字段、格式是否符合 P2 定义;语义校验则更深一步,让模型基于原始任务目标和返回结果再交叉核对一遍,例如“用户要的是环比变化,你返回的却是同比,这一步就得打回”。

P4 里另一个设计点是“验证证据”。模型说“我验证通过了”,不能只是嘴上说说,必须把验证依据附在结果包上,比如“消费者代码返回的 JSON 里有 sales_summary 字段,我抽样了 east 和 west 两条记录手动比对,比例一致”之类。有了证据,这个流程对后续人工审核也非常友好,外人可以一眼看出模型是真正做了检验,还是在自欺欺人。

2.5 阶段五:结果交付与上下文沉淀(P5)——把“跑完”变成“交付完”

P5 不是简单地把结果打印出来就算结束。它承担的职责是“翻译”和“归档”:把内部工具产生的原始输出、JSON、代码返回值,翻译成用户真正能消费的语言或文件格式;同时把这次任务的运行轨迹、重要决策、结果摘要写入记忆库,方便下次同类任务做参考。

这背后的思考是,很多 Agent 项目每天都在重复造轮子。用户让你处理十份不同日期的销售报告,你如果每次都是从头开始理解“文件长什么样、CSV 表头叫什么”,那效率一定很低。P5 会把每次任务的 schema 特征、工具参数偏好沉淀成一个可复用的“任务档案”。下一次模型看到类似请求,可以直接从记忆库调出相似方案做类比,减少了大量重复的前期探索。

我也在 P5 里加了交付格式的自适应逻辑。如果任务目标是“写报告”,P5 自动把内部结果组装成 Markdown;如果是“调接口”,P5 会把接口返回的原始 JSON 做精简、脱敏、格式化后输出。这步就像公司的产品经理,把研发的技术语言翻译成客户听懂的方案。少了这个翻译层,技术结果再正确,用户端的体验永远是割裂的。

3. 从零到一:完整实操记录与关键配置

3.1 环境准备与最小文件结构

跑通 pentagi 对环境要求不高,我日常工作目录大概是这样的:Python 3.10+,一个 .env 文件,一个存放状态文件的 runtime 目录,还有一个主要是工具注册表的 workspace 目录。结构上不堆叠任何重量级数据库,简简单单一张文件系统就能承载状态管理。

我自己会在项目根目录放一个 config.yaml,统一管理模型提供方、模型名称、超时时间和 token 预算。核心配置长这样:

model: provider: openai-compatible name: gpt-4o-mini temperature: 0.2 max_tokens: 4096 state_store: path: ./runtime/state archive_after_done: true execution: max_steps: 8 step_timeout_seconds: 120 token_budget: 80000 auto_retry: true retry_limit: 2

有一个点值得强调,temperature 千万别调太高。我在规划阶段跑过一次对比实验,同样一个复杂任务,温度 0.7 的时候模型会得出两个完全不同的工具名称,然后很自然地开始幻想一个不存在的 API。后来我把全局温度压到 0.2,规划阶段的稳定性明显大幅提升。如果你像 ChatGPT 那样需要闲聊性质,可以单独给聊天入口加高温度参数,但 Agent 的内部管道必须保守。

3.2 第一阶段跑通:观察状态文件的变化

我把整个 pipeline 的核心入口叫 dispatcher.py,它负责读取请求、实例化状态机、逐个阶段推进。第一次调通的时候,我并没有盯着终端输出看,而是直接去查看 runtime/state 下面生成了什么文件。这是 pentagi 比较直观的一点:所有阶段运行状态都会形成一个以 request_id 为前缀的快照,比如req_001_P1_parsed.jsonreq_001_P2_plan.json

P1 跑完生成的文件里除了任务解析结果,还会带一个 completed 时间戳;P2 跑完会出现一个 steps 数组和 dependency_map;P3 跑完会有 execution_trace;P4 出现 validation_report;P5 则生成 final_delivery 和 archived_summary。我每次跑完一个任务,会先按时间戳把这一系列文件串起来看一遍,整个 Agent 的决策链几乎没有死角。这也是为什么我一直推崇文件化状态,比只存在内存里更容易“看见”和排查。

如果你在自己项目里复刻这套,给你一个直接的抄作业建议:状态文件里至少要包含三个字段,request_id 用于串联,stage 用于标记当前阶段,success 标记是否通过。哪怕其他字段先都不写,先把这三个字段铺满,后面再丰富时就不容易乱。

3.3 自定义一个最小工具并注入注册表

工具注册是 pentagi 日常最频繁的操作之一。我提供了一个统一的 decorator 风格注册接口,新增工具时只需要在 workspace/tools 下定义函数,然后用 @tool.register 标注一下它叫什么名字、要求哪些参数、期望返回什么结构。

下面是一个非常简化的工具定义示例:

from pentagi import tool @tool.register( name="read_csv_head", description="读取CSV文件,并返回列名与前n行数据", parameters={ "file_path": {"type": "string", "required": True}, "n": {"type": "integer", "required": False, "default": 5} }, output_schema={ "type": "object", "properties": { "columns": {"type": "array"}, "preview": {"type": "array"} } } ) def read_csv_head(file_path, n=5): import csv with open(file_path, newline="", encoding="utf-8") as f: reader = csv.reader(f) rows = [r for r in reader][: n + 1] return { "columns": rows[0] if rows else [], "preview": rows[1:] }

这里面最花心思的其实是 output_schema。早先我的工具定义只写入了参数,没写输出结构,结果 P4 验证阶段永远不知道返回结果是否合格。后来我给每个工具都补上了 output_schema,验证阶段就可以拿实际输出和 schema 做一个 JSON Schema 的格式校验,一报错就能精准定位到是工具内部坏了,还是模型调用参数传错了。

3.4 完整跑通一个任务需要关注的调度时序

第一次跑完整流程时,我更关心的是调度时序是否合理。我的 dispatcher 核心逻辑非常简单:循环调用阶段函数,每执行完一个阶段就写一次状态快照,然后读取下一阶段状态继续执行。但这里有一个很容易被忽略的细节:每个阶段函数是阻塞还是非阻塞?

我一开始天真地把所有阶段同步阻塞,结果 P3 工具执行遇到一个外部 API 响应特别慢,整条链路卡了五分钟。后来我给 P3 内部做了异步超时控制,单个工具不能超过配置里的 step_timeout_seconds,超时直接进入 retry 分支,连续重试两次仍失败就把该步骤标记为 failed 并决定回退到 P2 重新规划。这个“回退到规划”的动作是整个调度最值得学的一笔,因为它不会在错误的工具选择里反复钻牛角尖,而是承认规划出错、重新思考思路。

如果你也想在自己项目里做类似的回退,一定要记录清楚回退原因。Pentagi 的状态文件里会写一个rollback_reason字段,比如tool_call_timeoutvalidation_conflict。有了这个原因,后面看日志时就不需要猜当时为什么回退了。

4. 我踩过的坑:常见问题与排查思路

4.1 问题速查表

做迁移和日常维护的时候最烦的就是看到了问题但不知道是哪一层出的。我把一段时间里出的高频问题整理成一个速查表,每次排查先对着这张表过一遍,省很多时间。

表面现象可能根因排查手段
P3 执行完 P4 报字段缺失工具 output_schema 与实际返回不一致对比执行快照中的 raw_output 与 schema
模型反复重试同一个错误调用P2 规划时未给足依赖约束检查 P2 plan 的 dependencies 是否写成并行
状态文件出现错位覆盖多请求共用了同一份 runtime 目录确认 request_id 隔离是否生效
P4 验证通过但结果明显错误语义校验阈值设置过低手动抽查验证证据日志里的抽查记录
任务跑一半 token 超预算MAX_TOKENS_BUDGET 写得太小或 P3 无超时查看 P3 执行 trace 里消耗 token 最多的工具

这套速查表实际操作中有个附加价值:新人接手项目时,照着现象找根因,即使不深入理解所有代码,也能快速定位大部分问题。

4.2 深坑一:模型在 P2 规划时“点名”了一个不存在的工具

这是我最早踩的坑里记忆最深的。模型在规划阶段写出use_tool: read_sales_from_db,但我注册表里根本没有这个名字。当时我在 P3 执行阶段直接抛异常,整个任务挂了。后来我加了一个“工具预检”机制:P2 生成的计划表在进入 P3 之前,先由调度器拿着所有 tool_hint 去 registry 里做一次存在性检查,不存在的直接在 P2 阶段打回重新规划。

其中还要考虑一部分工具名虽然存在,但模型给的参数名和实际注册参数不一致,比如工具里定义的是 file_path,模型给出的是 path。这个问题靠模糊匹配和别名配置来解决。每个工具在注册时可以配置一个 alias 数组,把常见的参数名变体写进去,P2 预检时做归一化拆解。这个改动一上线,因为“参数名幻觉”引发的失败率下降了非常多。

4.3 深坑二:上下文窗口被 P3 执行历史撑爆

另一个困惑比较久的问题是,P3 阶段明明只调了四五个工具,但上下文很快就用完了。后来翻了执行日志才发现,每个工具返回结果我都原封不动塞进后续模型请求里,而有些数据查询工具返回了几万字符的原始记录,模型真正需要的信息可能就百来个字。这个问题的根源是我把“工具返回”和“模型输入”混为一谈,对工具输出没有做尺寸控制。

现在 pentagi 的 P3 阶段会给每个工具输出加一个 summary 提取步骤:第一次把完整结果存入状态文件,再让模型对结果做一次摘要,摘要长度限制在几百个 token 以内,之后模型上下文里带的是摘要和完整结果的引用路径。这样一来,长任务对上下文的压力一下子小了很多。这也是我强烈建议别人做工具层设计时要提前规划的点,否则上下文膨胀会非常快地影响模型质量。

4.4 深坑三:P4 语义校验里“放水”的 prompt 陷阱

我之前写语义校验 prompt 时,在末尾加了一句“如果你觉得结果合理,直接输出 valid”。结果模型几乎全都输出 valid,哪怕结果和任务目标八竿子打不着。后来复盘发现,模型对“合理”这种抽象词倾向于顺从,它本质上还是在迎合 prompt 的期待。后来我把校验 prompt 改成更严格的输出协议,强制要求模型先回答三个分论点:1. 原始任务要求什么;2. 执行结果是什么;3. 两者之间是否满足一一对应。最后才允许输出验证结论,而且结论必须给出材料依据。

改完之后验证质量提升特别明显,模型会真的去对照原始任务的每个字段检查输出,而不是一句“合理”就把流程糊弄过去。这也让我意识到,验证环节的 prompt 设计本身也需要被验证,必须有足够强的约束去对抗模型的“正确性幻觉”。

5. 让这套方案越用越顺:调优方向与长期经验

5.1 给 P2 增加计划对比的“记忆缓存”

跑了几周的 pentagi 后,我逐渐发现有一类任务天天都在重复:读 Excel、算指标、画图、写报表。P2 每次还是在用大模型的 token 去重新想一遍行动计划,实在是浪费。后来我给 P2 前面加了一个“模板匹配层”:每次任务完成后,P5 归档的 summary 会生成一个任务指纹,下次遇到相似指纹的任务,直接复用上次的规划骨架,只更新数据源和参数。

这个策略包含一个非常重要的边界:复用计划不代表跳过验证,P4 仍然对新执行结果做全量校验。这样既省 token,又不放松质量要求。我实测下来,在“周报处理”这类重复任务场景,单次任务 token 消耗能降低三四成,而且执行结果更稳定,因为模型不再每次重新发挥规划创意了。

5.2 从单工具执行走向多 Agent 协作的铺垫

pentagi 的五阶段协议天然适合扩展成多 Agent 协作。我最近的实验是把 P2 的规划权从单个模型手里拿出来,改成“规划 Agent + 执行 Agent”分离:规划 Agent 只负责拆解任务生成行动清单,执行 Agent 负责具体调用工具,两边的上下文完全隔离。这样规划 Agent 不会被工具返回的细节污染,执行 Agent 也不会被规划阶段的大段文本占满上下文。

五阶段的边界刚好作为两个 Agent 之间的交接口:P2 计划表是规划 Agent 交给执行 Agent 的契约,P3 执行记录是执行 Agent 交回给规划 Agent 的报告。这种松耦合结构还带来一个额外好处:你可以让执行 Agent 用更便宜的模型,规划 Agent 用更强的模型,让整个成本结构更精细。不过这个方向需要你对任务依赖关系梳理得足够清晰,否则两条角色线一乱,排查起来难度更大,我建议先单 Agent 跑稳再上多 Agent 协作。

5.3 关于状态快照的储存细节

最后分享一个经验值:状态快照既不要只放内存,也不要整段塞进一个数据库里。我采用的方案是本地 JSON 文件配合可选的历史归档桶。流程运行时只读写文件,速度很快;任务结束后,把 archive 后的状态快照推到一个集中的对象存储里,供后续审计或微调训练时使用。完全不建议把每步中间状态实时写进数据库,那样会引入不必要的依赖,还会拖慢整个链路的执行速度。

如果单机跑不了太多并发任务,文件系统的状态方案其实很稳。但如果你打算做高并发服务,建议加一个简单的文件锁,或者直接用 SQLite 做状态表,别一上来就上 Redis 这类重量级组件。Agent 项目的瓶颈往往不在存储,而在推理链路本身,存储先用最朴素的方案兜底就行。

根据我个人这段时间折腾 pentagi 的体会,最重要的一句话其实是:Agent 的稳定不是靠提示词写得妙,而是靠流程边界划得清。只要你把五个阶段的状态管住了,大部分“模型抽风”的问题都可以在系统层面被接住,而不是让用户去面对一个失控的黑盒。如果你也在搭类似的智能体项目,不妨先试着把自己的链路按阶段拆开,哪怕不用这个名字,也会发现结构的力量比你想象的还要大。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询