Expand guides with worked examples for intents, runs, and squads
Why: 补充实例让导览可对照实操:意图打分/填槽/多意图裁决给出 intentctl explain 实测轨迹(含样例意图、歧义、优先级 tie-break、 能力目录),任务执行给出工具清单与典型回合走查(含 ClaimGate 三类拦截),小队给出 agent-squad demo 全流程实测与真实工作区 目录树/TASK.md 实拍;并修正事实:默认意图目录为空、插件 overlay 与 registry loader 两种文件形态不同。 Evidence: intentctl explain/catalog 与 agent-squad demo 为 2026-10-08 本地实测输出(命令见各节);锚点仍为 Dev R0 218fc4b1;git diff --check 通过;五篇互链全部可解析。SRC=SELF。 Impact: 仅文档增补(02/03/04/05 四篇),无代码影响。 Refs: Dev 任务分支 feature/architecture-guides。
This commit is contained in:
@@ -83,6 +83,121 @@ clarify / chitchat / handoff`;规则漏斗只产出 start/set_slot/clarify(`
|
||||
(`intent/catalog.go:36,68`)把启用意图渲染为 Markdown,供小队规划者/Leader 提示词注入
|
||||
(`deps/agent-squad/adapters/intent/catalog.go` 消费)。
|
||||
|
||||
## 4.5 内置与默认意图:默认是空目录
|
||||
|
||||
**系统默认不内置任何意图**:backend 组合根 `intentgate.New()`(`app.go:309`)起步是空注册表,
|
||||
`g.Match` 在空闸门下直接透传(未启用 = 行为回退,所有消息走普通回合)。意图只能经两条
|
||||
overlay 路径进入,且**两种路径的文件形态不同**:
|
||||
|
||||
| 路径 | 文件形态 | 装载方 |
|
||||
|---|---|---|
|
||||
| 插件 overlay(产品路径) | **裸数组** `[ {…IntentSpec…}, … ]` | `plugins/host.go:216-220` 按元素透传 → `gate.Rebuild`(gate.go:104)逐个 unmarshal 成 IntentSpec |
|
||||
| registry/loader(库路径:intentctl、BuildFS) | 包装对象 `{"intents":[…], "disable":[…]}` | `intent/loader.go:21` `overlayDoc`,严格 JSON(未知字段报错) |
|
||||
|
||||
仓库自带两份样例意图(即"默认能看到的意图"上限——装载对应插件/配置后生效):
|
||||
|
||||
- `plugins/example/intents/demo.json`(插件形态):`demo.show`(命中"示例/演示",无槽位)、
|
||||
`demo.brief`(命中"简报",必填槽位 `topic`,抽取正则 `主题[::]\s*(\S+)`,缺槽问"主题是什么?")。
|
||||
- `deps/agent-intent/examples/specs/demo.json`(loader 形态):`demo.run.status_query`
|
||||
(命中"进度/状态"、排除"配置",槽位 `run_id`,base=0.8/threshold=0.7,handler=`taskrun.query_status`)、
|
||||
`demo.run.restart`(需同时含"重启"+"任务",`requires_confirm=true`,risk=medium)。
|
||||
|
||||
---
|
||||
|
||||
## 4.6 实测:一句话怎么被打分、填槽、命中
|
||||
|
||||
以下全部为 `intentctl explain` 在样例配置上的**真实输出**(2026-10-08 实测;例 5/6 的配置目录
|
||||
= 两份样例意图合并)。打分公式:`score = base + (正则命中 ? pattern_bonus : 0)`(封顶 1.0),
|
||||
前两名分差 < `margin`(默认 0.1,`intent/registry.go:55`)判 ambiguous。
|
||||
|
||||
**例 1|命中 + 抽到槽位**(输入"查一下任务 run_42 的进度"):
|
||||
|
||||
```
|
||||
分支:matched
|
||||
Top:demo.run.status_query 置信度=0.8000 风险=low 确认=false handler=taskrun.query_status
|
||||
槽位 run_id="run"
|
||||
候选(1):
|
||||
0.8000 demo.run.status_query terms=进度
|
||||
裁决轨迹:
|
||||
margin=0.1000
|
||||
守卫:未评估
|
||||
规则 命中 demo.run.status_query 0.8000 进度
|
||||
规则 排除 demo.run.restart no_positive_match
|
||||
```
|
||||
|
||||
要点:`terms=进度` 命中词表加 0 分(base 已含);`restart` 因 `includes_all:["任务"]` 缺"重启"
|
||||
被排除(`missing_includes_all`)。槽位 `run_id="run"` 是真实结果——槽位正则
|
||||
`(?:run|任务)[:# ]*([A-Za-z0-9-]+)` 的字符类不含下划线,捕获在 `run` 后被 `_` 截断:
|
||||
**规则识别完全确定性,槽位 pattern 的质量决定抽取质量**(写 `[A-Za-z0-9_-]+` 即可取到 `run_42`)。
|
||||
|
||||
**例 2|命中但缺必填槽位**(输入"写一份简报",`demo.brief` 装载时):
|
||||
|
||||
```
|
||||
分支:matched
|
||||
Top:demo.brief 置信度=0.7000
|
||||
缺失必填槽位:topic
|
||||
裁决轨迹:
|
||||
规则 命中 demo.brief 0.7000 简报
|
||||
规则 排除 demo.run.restart missing_includes_all:任务
|
||||
规则 排除 demo.run.status_query no_positive_match
|
||||
规则 排除 demo.show no_positive_match
|
||||
```
|
||||
|
||||
`Missing=[topic]` 连同 spec 的 `question:"主题是什么?"` 一起随 route 进入工作流 run,
|
||||
由 HITL 输入卡向用户澄清(见调用链第 10 步)。
|
||||
|
||||
**例 3|槽位填上**(输入"主题:核能 写一份简报"):同一意图 matched,
|
||||
`槽位 topic="核能"`,Missing 为空——正则 `主题[::]\s*(\S+)` 命中,直接启动。
|
||||
|
||||
**例 4|什么都不像**(输入"随便聊聊今天的天气"):
|
||||
|
||||
```
|
||||
分支:fallback
|
||||
裁决轨迹:
|
||||
规则 排除 demo.run.restart missing_includes_all:任务
|
||||
规则 排除 demo.run.status_query no_positive_match
|
||||
```
|
||||
|
||||
无命中 → fallback;若装载了语义慢通道(`runtime.intentSemantic`,默认关)会先尝试 embedding
|
||||
重排,仍不达阈才 fallback。gate 把 fallback 折叠后 `route.Decide` 判 `KindTurn` → 普通对话回合。
|
||||
|
||||
**例 5|能力目录实测**(`intentctl catalog`,这段 Markdown 就是注入小队规划者/Leader
|
||||
提示词的内容,`squad/engine.go:44` 注释明示用途):
|
||||
|
||||
```
|
||||
# 系统能力目录(意图快照 revision=1)
|
||||
|
||||
以下能力可直接调用,无需派智能体执行。子任务命中其一时,输出携带 intent_id 的步骤并填齐必填槽位;
|
||||
必填槽位信息不足时不要编造,改为向用户澄清(优先使用各槽位的提问建议)。
|
||||
|
||||
## demo.brief — 写一份简报。必填槽位 topic,没写就问「主题是什么?」。
|
||||
- 风险:low;执行前需人工确认:否
|
||||
- 槽位 topic(必填,topic)
|
||||
- 提问建议:主题是什么?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4.7 一句话里有多个意图怎么办
|
||||
|
||||
意图层的契约是**一条输入只产出一个 Decision**(top-1),不做多意图拆分。多个候选的
|
||||
裁决顺序固定为:
|
||||
|
||||
1. **分差裁决**:唯一过阈,或第一名领先 ≥ margin → 直接 matched。
|
||||
2. **同分且 priority 不同 → 高优先级直接胜出**(I5,不标歧)。实测("帮我生成一份报告",
|
||||
两个意图 base 都是 0.7、词表都命中"报告"):template 设 `priority:10` 后
|
||||
`分支:matched,Top:demo.report.template 置信度=0.7000`。
|
||||
3. **分差 < margin(含同分同优先级)→ ambiguous**,先走可选语义重排 `semanticRerank`
|
||||
(`recognizer.go:292`,默认关)→ 再走 Classifier L2 重打分(backend 未接线)→ 都没有则
|
||||
**保持 ambiguous**。实测同配置去掉 priority 后:
|
||||
`分支:ambiguous,候选(2):0.7000 demo.report.generate / 0.7000 demo.report.template`。
|
||||
4. ambiguous 经 gate 折叠 → `KindTurn` → **交给普通 LLM 回合**:模型在一次 ReAct 循环里
|
||||
自行处理多个请求(这也是多数"一句话多个事"的实际归宿——意图层只接管高确定性的
|
||||
命令/工作流类请求)。
|
||||
5. 多轮场景:Stage 1 挂起预期(`ExpectationProvider`)让澄清中的输入优先回到挂起意图;
|
||||
HITL 自由输入命中其他意图时会**取消挂起 run 并转轨**(`runmgr.go:1261` `ResolveHITL`),
|
||||
相当于允许用户中途改道。
|
||||
|
||||
---
|
||||
|
||||
## 5. 端到端调用链:用户输入一条消息后发生了什么
|
||||
|
||||
@@ -84,8 +84,10 @@ tools/model/maxTurns 约束,**禁止子代理再持有派发类工具**,`int
|
||||
### 一条"不可达"的路径(设计预留)
|
||||
|
||||
意图识别绑定 `blueprint` 动作可路由到 `KindSquad`(`internal/route/route.go:96-97`),
|
||||
但当前 `server.go:664` 明确注释 `SquadReady 保持 false`(per-run entry 覆盖未就位),
|
||||
**该路径暂不可达**——小队的意图目录注入另走 `deps/agent-squad/adapters/intent/catalog.go`。
|
||||
但当前**双重不可达**:`server.go:664` 明确注释 `SquadReady 保持 false`(per-run entry
|
||||
覆盖未就位);且系统默认意图目录为空(见[意图识别](intent-recognition.md) 4.5 节),
|
||||
不装插件就没有意图可命中 blueprint。小队的实际启动走上面 A/B/C 三条路径;意图目录
|
||||
对小队的现实作用是注入规划者/Leader 提示词的能力目录(`deps/agent-squad/adapters/intent/catalog.go`)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -91,6 +91,90 @@ blackboard.json / pending.json / runstate.json / usage.json`
|
||||
|
||||
---
|
||||
|
||||
## 4.5 实测:离线小队演示(真实输出)
|
||||
|
||||
`deps/agent-squad` 自带离线演示(`cmd/agent-squad demo -keep`,stub 脚本成员 + 规划脚本 +
|
||||
自动应答 HITL,无需 LLM/网络),以下为其 2026-10-08 实测输出摘录。**引擎机制与产品完全
|
||||
同一套**,差异只有三处:成员后端是脚本(产品是 agent-native 内核)、规划器是 MockPlanner
|
||||
(产品默认 RulePlanner)、HITL 自动应答(产品走 HITL 卡片)。
|
||||
|
||||
```
|
||||
═══ agent-squad 离线演示(stub 智能体 + mock 规划器 + HITL)═══
|
||||
|
||||
[1] 注册角色(手动注册,backend=demo 脚本智能体)
|
||||
+ researcher 调研专员 + writer 撰写专员 + reviewer 审核专员
|
||||
|
||||
[2] 发起运行:调研便携式超声诊断仪并产出报告
|
||||
✔ step_01_research researcher 市场与技术调研,回填事实与缺口
|
||||
step_02_draft writer 汇总调研产出,撰写报告初稿
|
||||
step_03_review reviewer 一致性终审并产出终版
|
||||
|
||||
[3] ⏸ HITL 挂起(gap):发现 1 个阻塞缺口,需要人工补充信息后才能继续:
|
||||
- [gap_1] 目标年产量未提供,影响成本测算(owner=agent)
|
||||
→ 自动回应:choice="resolved" answer="年产量 10 万套"
|
||||
✔ step_01_research ✔ step_02_draft ✔ step_03_review
|
||||
|
||||
[4] 运行终态:completed
|
||||
步骤 3 个(完成 3/跳过 0/失败 0)。质检得分 100。
|
||||
交付物: <dataDir>/runs/run_20261008T090457.882598947/output.md
|
||||
黑板字段: {"annual_volume":"100000","budget":"15万","device_class":"二类",
|
||||
"review":"passed","target_market":"中国"}
|
||||
```
|
||||
|
||||
对应真实落盘的工作区(`runs/<run_id>/`)——与第 4 节调用链逐项对应:
|
||||
|
||||
```text
|
||||
runs/run_20261008T090457.882598947/
|
||||
├── context/goal.md, context/index.json # 9. 目标与材料快照
|
||||
├── tasks/01_researcher/ # 9. 每步一个子工作区
|
||||
│ ├── TASK.md # 步骤任务书(角色、期望产出、资源权威等级、黑板快照、产出要求)
|
||||
│ ├── AGENTS.md # 角色指令
|
||||
│ ├── context/ # 快照进来的目标/材料
|
||||
│ ├── notes.md fields.json gaps.json # 成员产出(黑板来源)
|
||||
│ └── execution.log
|
||||
├── tasks/02_writer/{TASK.md,AGENTS.md,context/,output.md,...}
|
||||
├── tasks/03_reviewer/{TASK.md,AGENTS.md,context/,output.md,fields.json,...}
|
||||
├── blackboard.json # 11. 黑板(字段在步骤间累积)
|
||||
├── workflow.json squad.json runstate.json # 7. 拆解结果与运行态(磁盘即权威)
|
||||
├── checkpoints/{001,002,latest}.json # 11. superstep 检查点
|
||||
├── output.md manifest.json # 14. 聚合交付物 + sha256 清单
|
||||
└── .lock # 6. acquire 的 flock 文件锁
|
||||
```
|
||||
|
||||
`tasks/01_researcher/TASK.md` 实拍(节选):
|
||||
|
||||
```markdown
|
||||
# 步骤任务:市场与技术调研,回填事实与缺口
|
||||
- 角色:调研专员(researcher)
|
||||
- 期望产出:[notes.md fields.json gaps.json]
|
||||
## 任务上下文资源与权威等级(已快照到本目录,只引用本地路径)
|
||||
| 资源路径 | 权威等级 | 用途说明 |
|
||||
| `context/goal.md` | **authoritative** | 运行目标 | 不可推翻 |
|
||||
## 黑板快照(共享状态)
|
||||
## 产出要求
|
||||
1. 按期望产出文件名落盘到本子目录;
|
||||
2. 结构化事实回填 `fields.json`(字符串键值);
|
||||
3. 发现信息缺口且无法假设时写 `gaps.json`([{"item":"…","blocking":true}])。
|
||||
```
|
||||
|
||||
产品的默认拆解(RulePlanner 四阶段骨架,`squad/planner_rule.go:79` 起)与演示计划同构,
|
||||
真实代码里的步骤与交付约定:
|
||||
|
||||
```go
|
||||
// 通用四阶段骨架:梳理 → 专项 → 成文 → 终审
|
||||
{"step_01_organizer", "梳理目标背景与输入材料,产出事实与缺口", "organizer"},
|
||||
{"step_02_specialist", "围绕目标开展专业分析与推演", "specialist"},
|
||||
{"step_03_writer", "汇总各角色产出,撰写交付物初稿", "writer"},
|
||||
{"step_04_leader", "一致性终审与交付把关", "leader"},
|
||||
// 非末步 targets = ["notes.md","fields.json"](事实经黑板传给后步);末步 = ["output.md"]
|
||||
```
|
||||
|
||||
注册表缺角色时 `Registry.Derive` 现场派生(名为"organizer 专员"等)并置
|
||||
`NeedsConfirmation` → `awaiting_confirmation` 挂起等用户确认编制。意图目录注入规划器/
|
||||
Leader 的形态见[意图识别](intent-recognition.md) 4.6 节例 5 的 catalog 实测输出。
|
||||
|
||||
---
|
||||
|
||||
## 5. 小队如何"协作"
|
||||
|
||||
- **黑板(Blackboard)**是协作中枢:Facts(已确认事实)/Gaps(信息缺口)/
|
||||
|
||||
@@ -125,6 +125,53 @@ prefixHash)作为可观测 `ContextObservation`。记忆注入在内核按请
|
||||
|
||||
---
|
||||
|
||||
## 5.5 主对话模型手上有哪些工具
|
||||
|
||||
模型每轮请求能看到的工具分三类(全部在 `LLMRunner.Execute` 声明阶段组装,`llm.go:267-315`):
|
||||
|
||||
| 类别 | 工具名(实测常量/注册名) | 来源 |
|
||||
|---|---|---|
|
||||
| **编排型**(在 runner 内消化,不走通用执行器) | `update_plan` / `update_todos`(维护右栏计划/待办)、`delegate_task`(派子代理)、`squad_orchestrate`(发起小队)、`run_workflow`(发起工作流)、`review_findings`、`submit_card`、`card_begin`/`card_append`/`card_commit`(流式产卡三段式) | `internal/runtime/llm.go:56-70` 常量 |
|
||||
| **内置产品工具** | `time_now`、`knowledge_search`(项目/插件知识全文检索)、`write_artifact`(写工件)、`quality_review`(交付物打分)、`ask_user`(主动提问=HITL)、跨会话 `peers` 系列 | `internal/tools/registry.go:112` `RegisterBuiltin` |
|
||||
| **内核工作区工具**(经 hostbridge 注入内核) | `read_file` / `write_file` / `edit_file` / `multi_edit` / `list_dir` / `grep` / `glob` / `load_skill` / `run_python` / `run_command` / `web_search` / `tavily_search` / `fetch_url` / `delegate_task` | `internal/runtime/hostbridge.go:15-21` `kernelToolNames`;`web_search`/`tavily_search` 仅在配置了搜索密钥时注册 |
|
||||
|
||||
实际可见集 = 以上与**画像三清单**(allow/deny/confirm,`core/profile.go`)过滤后的交集;
|
||||
计划模式下 `filterPlanDecls`(llm.go:332)会再收窄。
|
||||
|
||||
---
|
||||
|
||||
## 5.6 实例:一个典型回合的机制走查
|
||||
|
||||
> 走查基于上文全部代码锚点;模型输出为示意,机制、工具名与顺序均为代码实测。
|
||||
|
||||
用户输入:"把我会话里刚上传的季度数据整理成一份摘要文档,并告诉我三个关键结论。"
|
||||
|
||||
1. **进入回合**:`postMessage` → 意图 fallback(没有装匹配意图)→ `route.Decide` 判
|
||||
`KindTurn` → 抢会话槽位 → `startClaimedRun` 建 `Run{pending}` → 选 `LLMRunner` →
|
||||
`go execute()`(`runmgr.go:1023, 918`)。
|
||||
2. **上下文组装**:`ctxasm.AssembleInput`(ctxasm.go:45)——system 段(base/env/task 提示词
|
||||
模块,`prompts.ResolveSystem`)→ 历史窗口(默认 40 条)→ 当前轮文本 + **附件解析全文**
|
||||
(ingest 已把 xlsx/csv 解成 ParsedDocument,默认 48000 字符截断)→ knowledge 块。
|
||||
3. **第 1 轮 LLM**:模型看到数据后先调 `update_todos`(拆 3 个待办)+ `read_file`(读附件
|
||||
解析物)。两个工具经内核 `runTool` 回落宿主执行,结果以 `Role=tool` 消息回填转录
|
||||
(loop.go `executeTools` 段),UI 侧聚成工具过程部件。
|
||||
4. **第 2 轮 LLM**:模型调 `write_artifact`(把摘要写成工件)。宿主执行 → `artifact.created`
|
||||
事件 → 工件登记进会话。
|
||||
5. **第 3 轮 LLM**:模型输出三个结论的纯文本(无工具调用)→ 内核判定无工具调用 →
|
||||
follow-up drain → **Stop 钩子**:宿主做交付物门禁(`deps/agent-native/runtime/gates/gates.go:52`
|
||||
`ClaimGate`)——它抓三类"说谎":① 回复正文出现工具调用标记但本轮没有真实调用;
|
||||
② 引用了不存在的工件 ID;③ **声称"已生成/已登记文件"但这轮没有产出对应工件**。
|
||||
本例模型确实产出了工件,门禁放行;若模型只写了结论却声称"文件已生成",
|
||||
门禁拒绝结算并附原因让模型续跑(最多 3 次续跑,`loop.go` stopDecision + 宿主接线)。
|
||||
6. **收口**:可选用主模型 `composeFinal` 重写最终回复 → `finishRun`(runmgr.go:1087)→
|
||||
`SettleRun` 单事务落 run 终态与助手消息树 → 发 `run.completed`(带 ContextObservation)。
|
||||
|
||||
子代理变体:若第 2 轮模型改调 `delegate_task {agent:"researcher", task:"分析季度数据"}`,
|
||||
则走 `llm_direct.go:493` → `runmgr.go:1348` 派生 `Kind=subagent` 子 run(任务树 + `agent.spawn`
|
||||
事件)→ `SubLLMRunner` 用同一内核循环独立跑完 → 结果回填父轮。
|
||||
|
||||
---
|
||||
|
||||
## 6. HITL(人工介入)
|
||||
|
||||
- 契约:`modules/core/hitl.go:33-36` 四种卡(choice/input/confirm/form)。
|
||||
|
||||
Reference in New Issue
Block a user