跳到主要内容

AI Agent 骨架范式参考 v2 — 内外循环 call-graph 实证

0. 这份文档是什么 + 与 v1 的关系

v1(七仓实地核证)模块级静态阅读(每仓一个 sub-agent 出 ≤800 字报告)得出结论。owner 2026-06-07 晚指出:v1 缺内循环 call-graph 实证,把「外循环是 ReAct」过度外推成「整骨架无静态流水线 / 无 Plan-and-Execute」,且「结构化与表现负相关」是印象推断而非分层核证。

v2 是对 6 个真 agent 仓做逐层调用图追踪(每仓一个独立 sub-agent,跟着实际 call graph 走到原子操作,每个判定带 file:line + 控制流代码片段,区分外循环与各内循环、外内可不同范式)的重核结果。

v1 仍成立的部分:6 仓外循环都是 ReAct。 v2 修正的部分:内循环不全是 ReAct;「负相关」是过度概括;Opencode 是 P&S 不是 P&E;静态流水线/结构化作 inner-loop 工具可行且被采用。

核证对象:martin-FinClaw、Hermes Agent、Claude Code(fork claude-code-best v2.6.11,与 v1 同一份代码)、Opencode、Openclaw、Chelae-FinClaw(aifinlab 是 skills 包非 agent,不计)。

1. 方法论升级(v1 → v2)

维度v1v2
阅读深度模块/类/docstring 级摘要跟 call graph 进被调函数直到原子操作
循环分层只判主回路(outer loop)外循环 + 工具执行 + subagent + 规划态 + 反思 + 输出(A–F 六层)各自判
范式判定grep plan/reflect 命中计数每层引 file:line + 粘控制流代码 3–8 行
默认 vs opt-in未区分每层标注「默认触发 / opt-in」
内外一致性默认假设一致明确允许外内不同范式

2. 核心发现(修正版)

  1. 外循环 6 仓全 ReAct,确认(跨 Python/TS,跨通用/coding/金融)。无一例外。
  2. 内循环不全是 ReAct:工具执行层多为静态流水线 / 并发 fan-out(B 层);规划态层出现 Plan-and-Solve(D 层);反思层出现 Reflexion(E 层)。
  3. 「静态流水线 / 结构化」作 inner-loop 工具可行且被强 agent 采用:Claude Code WorkflowTool(静态步骤 + 主 LLM 推进)、Opencode 按需 forced structured output。被否决的只是「静态流水线当 outer-loop 主路径 + 绕过 ReAct + plan 编译期写死」(= FinBayes 旧版的三重叠加错误)。
  4. 「结构化与表现负相关」是过度概括:Chelae 弱于 martin 的真因是 router-of-routers 嵌套同 tier LLM + 工具收拢(B 层),不是 pre-router(A' 层不改写用户原文,最无害)。结构加在「控制流 / 工具收拢」上才弱,加在「inner-loop 工具 / 输出 schema」上不弱。
  5. 6 仓无一个真 Plan-and-Execute:Opencode 的 plan/build 是同一 agent 换权限帽(P&S),非 Planner/Executor 角色分离。

3. 六仓逐层 call-graph 表(A–F × 6 仓)

范式缩写:RA=ReAct,SP=静态流水线,P&S=Plan-and-Solve,RFX=Reflexion,FS=forced structured output。

martinHermesClaude CodeOpencodeOpenclawChelae
A 外循环RA loop.py:318RA conversation_loop.py:814RA query.ts:460RA prompt.ts:1225RA agent-loop.ts:229RA loop.py:224
B 工具执行原子 dispatcher macro.py:67原子 tool_executor.py:1027SP 分区并发 toolOrchestration.ts:106原子/SP tools.ts:87SP+并发 fan-out agent-loop.ts:545见 B'
B' router 内循环Tool-Search(无状态BM25) tool_search.py:378bounded RA(max4)+收拢 llm_router.py:143
C subagent递归RA(opt-in) subagent.py:123递归RA(opt-in,深度1) delegate_tool.py:1557递归RA runAgent.ts:776递归RA(opt-in) task.ts:175递归RA(异步轮询) agent-harness.ts:663递归RA(opt-in) subagent.py:137
D 规划态无(todo被动) todo_tool.py:25Plan-mode(prompt脚手架) query.ts:760 + WorkflowTool(SP+主LLM推进) WorkflowTool.ts:245P&S(双权限帽) agent.ts:155+plan.ts:46无(planner=确定性工具排序) planner.ts:40无LLM planner
A' pre-routerSP规则dispatch(不改原文) intent.py:193+loop.py:454
E 反思RFX(16步RA daemon,默认开) background_review.py:402opt-in RFX(fix→verify→PASS) prompts.ts:372retry.ts:35无(compaction非反思) agent-loop.ts:355无(cache非反思) cache.py:57
F 输出散文 loop.py:362散文 conversation_loop.py:4134散文 query.ts:1633按需FS(唯一) prompt.ts:1378散文(仅工具入参强类型) types.ts:449硬编码强制表格 router.py:42

4. 三个实质修正(带 file:line 实证)

修正 1 — Opencode 是 Plan-and-Solve,不是「最严格 Plan-and-Execute」

v1 称 Opencode plan/build 双 agent 是「最严格的 P&E」。重核(agent/agent.ts:155-159 + tool/plan.ts:46-69 + prompt.ts:1306):

  • plan 与 build 是同一个 agent 在同一个 while(true) 循环换权限帽:plan 帽用路径门控只允许写 plans/*.md,build 帽放开。
  • plan 是 LLM 用普通 write 工具动态写进文件,不是独立 Planner 角色产出的 artifact 单向传给 Executor
  • plan_exit 工具注入 agent:"build" 合成消息切换,下一轮外循环 agents.get(lastUser.agent) 读到 build。

P&E 的定义要件是 Planner/Executor 角色分离 + plan 作为 artifact 在两者间传递。这里只有「同一 cognitive agent 换权限帽」,所以是 Plan-and-Solve(先整体产 plan、再执行)外壳跑在 ReAct 上。6 仓里没有任何一个是真正的 Plan-and-Execute。

修正 2 — 静态流水线作 inner-loop 工具可行(Claude Code WorkflowTool 实证)

v1 称「静态流水线当主路径 = 6 仓零例,连 P&E 都不如」,被读成「静态流水线一律不可取」。重核 Claude Code WorkflowTool(WorkflowTool.ts:138-322):

  • 步骤从 .claude/workflows/*.md|.yaml 静态解析(拓扑写死,非 LLM 产物)—— 流水线特征。
  • WorkflowTool.call 是纯状态机 CRUD(start/advance/status/cancel/list),从不调 query/runAgent/LLM
  • control 每步显式回主 ReAct 循环start 返回 step0 文本 + "调 advance 继续";LLM 在主循环用普通工具执行该步,自己决定何时调 advance 取下一步 —— ReAct 特征。

即「静态步骤序列 + 靠主 ReAct LLM 手动推进的游标」。这是结构化流程作为 ReAct 内循环工具的真实工程实现,否决「静态流水线」必须限定在「当 outer-loop 主路径 + 绕过 ReAct」,不能波及 inner-loop 工具化形态。

(Tier 2 已确认并纠正:WorkflowTool 默认编入第三方 build(官方包 v2.1.167 二进制里 WorkflowTool×5 + 完整 workflow VM boundary),开关是服务端 GrowthBook flag tengu_workflows_enabled(非 v1 假设的 feature('WORKFLOW_SCRIPTS')),本账号取值 ON。「ant-only 默认关」旧判定推翻。详见 §8 T2-1。)

修正 3 — Opencode 按需 forced structured output 是 FinBayes「按需结构化」的完整参照

prompt.ts:1378-1448 实证两条 path:

  • 默认(不传 format)toolChoice:undefined,模型自由产散文,自然 stop。
  • format:{type:'json_schema',schema}:① 注入合成 StructuredOutput 工具(用用户 schema 作 inputSchema);② 追加 STRUCTURED_OUTPUT_SYSTEM_PROMPT;③ toolChoice:"required" 强制调工具;④ 捕获结构化输出后立即 break。schema 校验复用 AI SDK 不自写。

这正是 FinBayes 该走的「一套 ReAct,两种输出」:用户端散文(= martin 等价,D1/D2/D3/D5 对标 martin)+ 机器端 forced schema(慢循环 / eval / case 入库可机读,D6 + 慢循环可挂接),由调用方决定。

5. Chelae「为什么弱于 martin」的真因

owner 原假说「ADR-025 证据只测 outer-loop pre-router」—— 重核(intent.py + llm_router.py + router.py)结果部分证伪、方向更坐实

  • A' pre-router 是最无害的一层intent.py:193 纯规则分类,唯一副作用是 prepend 一段 routing prompt(loop.py:454),不改写用户原文(原文 100% 保留并单独存档)。「pre-router 改写原文致弱」假说证伪。
  • 真因在 B' router-of-routers:把 ~30 个扁平工具收拢成 6 个 router,每个 router 内部再跑同 tier 主模型的 bounded ReAct(max 4 turn,llm_router.py:143)。后果三重:
    1. 嵌套 LLM 串行延迟放大(一次提问 = 1 + N×(≤4) 次 LLM 往返);
    2. 外层 LLM 自主性降级成「填 query 字符串」,不能直接选数据工具;
    3. equity/economics/meme/prediction 四个 router 内层退化成单工具,纯净开销。
  • F 层硬编码强制表格(router.py:42You MUST...Do NOT write prose)剥夺答案形态自由,次要拖累。

精确结论:Chelae 弱不是「加了结构」,而是加的是「嵌套同 tier LLM 路由 + 工具收拢」这种特定坏结构(剥夺主 LLM 对工具的直接控制 + 多层语义转译)。这跟「静态 workflow 步骤作内循环工具」「按需结构化输出」是不同的东西,不能一并否决。

6. 范式三分(v2 提出的精确框架)

把「结构」按所在层分三类,分别评价,取代 v1 的「结构化程度」单轴:

结构位置实测评价对 FinBayes
控制流 / outer-loop 结构Chelae pre-router 改写、router 收拢、FinBayes 旧版绕过 ReAct 静态 DAG负面(Chelae 实测弱 + FinBayes 旧版反例)(ADR-025 头号铁律成立且强化)
inner-loop 工具化结构Claude Code WorkflowTool、子 agent fork、Plan-mode中性偏正(强 agent 采用,control 仍归主 LLM)可用(复杂金融分析作可选 workflow / 子 agent)
输出 schema 结构Opencode 按需 forced structured output正面(机器端可挂接,用户端不强制)采用(按需 forced schema = MP-4 task→字段矩阵的注入点)

7. 对 FinBayes 的设计含义(修正 ADR-025/028)

旧结论(v1 / ADR-025/028)v2 修正
主回路必须纯 ReAct✅ 不变(6 仓全确认,强化)
结构化与表现负相关❌ 过度概括 → 改为「控制流加结构弱 / inner-loop 与输出加结构不弱」(§6 三分)
静态流水线 / P&E 一律否决❌ 范围过宽 → 收窄到「静态流水线当 outer-loop 主路径」;inner-loop 工具化结构允许
17 字段×7 任务结构化认知只能留输出 schema✅ 有两条新实证路径:① WorkflowTool 式可选 workflow(复杂多步金融分析);② Opencode 按需 forced schema(机器端)

FinBayes 旧版 cognition 的错 = 三重叠加(① 静态流水线当 outer-loop 主路径 ② 绕过 ReAct ③ plan 编译期写死),可分开修,不必把「结构化」整个抛弃。「目的保留、实现重构」的 ADR-025 §决策 3 立场不变,但「重构成什么」多了 inner-loop 工具化这条被实证的路。

矫正 A(owner 2026-06-07 晚)— martin 是「地板」不是「目标」

martin 只在 martin vs Chelae 两个金融 agent 对比里体验好一些,横向比强通用/coding agent 也就及格线。martin「把 report 降级成 prompt 脚手架」是及格线选择,不是最优解。「比 martin 只强不弱」是阶段 1 底线闸门,不是 FinBayes 真实目标。FinBayes 真实对标的是强通用/coding agent(Claude Code 的 WorkflowTool + subagent fan-out + plan-mode、Hermes 的 tool-search + background-review、Opencode 的 plan-mode + 按需结构化)。inner-loop 工具该上就上,按金融任务复杂度,不以 martin 极简为节奏标尺。

矫正 B(owner 2026-06-07 晚)— 结构是「展示层投影 + 软质量指引」,不穿透内循环、不牺牲质量

内循环(认知核) = 纯 ReAct + 扁平工具(+ 按需 inner-loop 工具: WorkflowTool/subagent)
↓ 唯一目标 = 内容质量(对标强 agent),不被任何输出结构约束、不为填 schema 降质
高质量内容(LLM 自由 synthesis 产物)
↓ project(按任务 + 按渠道, downstream, 不回灌内循环)
├─ Web/Desktop/Mobile → 动态 widget(丰富结构化可视化)
├─ CLI/TUI/MCP/API → 清晰结构化段落排版(或纯散文)
└─ 机器消费者(慢循环/eval/case 入库) → 读结构化字段

owner 四点:① 不是所有任务都要结构化展示(投影按任务定);② 不是同一套固定结构元素(MP-4 7 任务×17 字段矩阵本就按任务变字段);③ widget 是可视化端的事,CLI 只是清晰排版,不穿透内循环;④ 结构化只是高质量内容的一种用户友好组织角度,不能降质量

对旧版代码的重新切分

旧版组件v2 判定
orchestrator.py static DAG抛弃——「绕过 ReAct 生成内容」,§6 第一行的 outer-loop 结构错
projections.py(build_widget_updates / UserAnswerProjection)保留复用——正是「质量内容 → 分渠道投影」层,旧版唯一做对的部分
models.py StructuredCognitionResult作投影载体保留,不作内循环强制生成目标
MP-4 17 字段×7 任务矩阵降为内循环软质量指引(system prompt 提示)+ 投影层字段选择依据,不作 forced toolChoice

forced schema 使用边界(吸收 §8 T2-2 警示):forced schema(toolChoice:required)只用机器路径(慢循环/eval 需结构化数据且接受约束);用户质量路径不 force——ReAct 自由产质量内容后投影。机器路径若用 Opencode 式 forced schema,须加保护:json_schema 模式剥离其它工具 OR 保留 error-retry 兜底。

8. Tier 2 实跑 trace 结论(owner 终端,2026-06-07)

执行受限说明:nested claude -p 子进程被 harness proxy 挡 401(正是「sandbox 不通 proxy」)、opencode 默认 provider 掉鉴权,故 T2-1/T2-2 走「静态 bundle/源码 + 活体旁证」,T2-3 走「源码 + 12 轮实跑 + session 库取证」。全程未落盘任何 key。

T2-1 · Claude Code WorkflowTool 默认开关 —— 实质纠正

  • 官方包 @anthropic-ai/claude-code v2.1.167 二进制里 WorkflowTool×5 + "Workflow"×3 + 完整 workflow VM boundary 机制全部编入第三方 build,非编译期 ant-only 裁掉。
  • 真正的 gate 名是服务端 GrowthBook flag tengu_workflows_enabled(不是 v1/Tier1 假设的 feature('WORKFLOW_SCRIPTS')),按账号/灰度取值;本账号取值 ON(本会话工具列表里 Workflow 可用即活体旁证)。
  • 纠正旧判定:「WorkflowTool ant-only 默认关」推翻。WorkflowTool 默认编入第三方 build,开关在服务端 GrowthBook,本账号 ON。「是否对所有第三方默认开」取决于服务端配置,本地二进制看不到。
  • 双源印证:Tier 1 读的 claude-code-best fork v2.6.11 源码 + Tier 2 看的官方包 v2.1.167 二进制,两个不同来源都有 WorkflowTool。

T2-2 · Opencode forced schema 多工具行为 —— 确认 + 借鉴警示

  • 确认 toolChoice:"required" = 「必须调某个工具」非「必须调 StructuredOutput」(prompt.ts:1429,类型 "auto"|"required"|"none" llm.ts:47)。
  • 多工具同在不被剥离prompt.ts:1378-1384),唯一推向 StructuredOutput 的是系统提示(prompt.ts:1418)。
  • 多步循环兜底(prompt.ts:1439,1441-1447):调别的工具 → 循环继续、下一步重挂 StructuredOutput;空手纯文本 → 抛 StructuredOutputError
  • 结构稳健但末步选对工具是 prompt 依赖、概率性的。FinBayes 借鉴建议(已并入 §7 forced schema 使用边界):json_schema 模式剥离其它工具 OR 保留 error-retry 兜底。

T2-3 · Hermes background_review 频率 + 子循环深度 —— 确认 + 新发现

  • 默认频率 = 每 10 user 轮(memory,agent_init.py:1063,本机 config 同值)/ 15 tool-迭代(skill,本机 config 覆盖默认 10)。第 10 轮计数器重建到触发点(12 轮实跑确认)。
  • 子循环上限 16 步确认(background_review.py:398 review fork max_iterations=16,fork 自身 nudge 置 0 不递归)。
  • 不阻塞确认run_agent.py:1132 daemon 线程不 join,conversation_loop.py:4152 注释「runs AFTER the response is delivered」)。
  • 新发现(源码读不出,实跑才挖到):成功的 background review 静默——成功路径用 _safe_print(quiet fork 里被抑制),只有失败/危险命令才 logger.warning;60k 行 agent.log 0 条 bg-review 是假象。54 个历史 session 中 14 个达 ≥10 user 轮(触发实际发生多次),但 session 库无 review-fork row成功的后台自省在日志和 session 库都不留痕,唯一足迹是写进 memory store 的条目。
  • 对 FinBayes 的含义:Hermes 的「成功即静默」对「可观测的后台自省回合」是明确缺口。FinBayes 慢循环(事后复盘线)的产品诉求恰恰是可审计的校准跟踪,所以强化 ADR-025 §决策 4「默认进 dashboard」——dashboard 正是 Hermes 缺的那层可观测性,FinBayes 必须把后台复盘回合显式落 dashboard,不能学 Hermes 静默。

Tier 2 未决次要项

  • T2-4(Opencode AI SDK v5 无 stopWhen=单步)+ T2-5(plan agent ruleset findLast 顺序)未跑(opencode SDK 受阻 + 优先级低)。T2-5 可纯源码读 anomalyco/opencode 补,不阻塞主结论。
  • 遗留:Hermes 6 个测试 session 待 owner 手动 hermes sessions delete(安全分类器拦了自动删)。

9. 状态 + 待决

  • v2 定稿:§1–§7(Tier 1 内外循环 call-graph + 三修正 + Chelae 真因 + 范式三分 + owner 两条矫正)+ §8(Tier 2 三项实跑结论已回填)—— 完整证据基,可作修订 ADR-025/028 之用。
  • Tier 2 实质纠正 2 条:T2-1(WorkflowTool 非 ant-only,gate=tengu_workflows_enabled,本账号 ON);T2-2(forced schema 多工具不剥离,借鉴需加保护)。T2-3 新增「Hermes 后台自省静默 → FinBayes 慢循环须 dashboard 可观测」。均不改 §2–§6 内/外循环范式定性。
  • pivot 形态已拍(owner 2026-06-07 晚,记入 ADR-028 §重核结论 D-9):阶段 1 = 纯 ReAct + 扁平工具 + MP-4 软指引(认真编码金融 procedure)+ α/δ 末答提取双口子(30-case A/B 定默认)+ 扩展点预留;WorkflowTool / subagent fan-out / 慢循环 daemon 阶段 2 gated on 实测 need。Step 1.2 解暂停。
  • 下游动作:本 v2 落定后,按 owner 决策修订 ADR-025/028(收窄否决范围 + 引入 §6 范式三分)。

关联资产