mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-09-20 12:13:38 +08:00
Polish s16 READMEs into flowing essay voice
Rewrite EN/ZH/JA for tea-conversation cadence: soft transitions, insight before jargon, fewer checklist piles — same design spine, warmer prose. Co-authored-by: Xinlu Lai <CrazyBoyM@users.noreply.github.com>
This commit is contained in:
@@ -6,62 +6,55 @@ s01 → ... → s14 → [s15](../s15_integrated_harness/) → `s16` → [s17](..
|
||||
|
||||
> *“一轮轮聊天,像每隔十秒给厨师发一条短信。Workflow 是厨房能照着做的菜谱。”*
|
||||
>
|
||||
> **Harness 层**: 编排 — 在单 agent 循环之上,跑一套多 agent 脚本。
|
||||
> **Harness 层**: 编排 — 单 agent 循环之上,再跑一套多 agent 脚本。
|
||||
>
|
||||
> 信任模型,工程化 harness。Workflow 就是编排层上的 harness 工程。
|
||||
> 信任模型,工程化 harness。Workflow,就是把这句话落到编排层。
|
||||
|
||||
---
|
||||
|
||||
想象你和朋友用微信一起做饭。你发“先切洋葱”,等他回,再问“切好了吗?”,然后“热锅……”。一道菜还行;要办二十桌宴席,聊天就成了瓶颈:步骤记丢、反复叮嘱,手机一死还得从头来。
|
||||
想象你跟朋友用微信一起做饭。“先切洋葱。”等回音。“切好了吗?”然后热锅、放盐。一道菜还能撑住这种节奏;二十桌宴席就不行了——步骤会丢,话会重复,手机一死还得从头来。
|
||||
|
||||
普通“模型当总指挥”的对话就是这样。**Workflow** 是写好的菜谱:厨房(runtime)按谱做,帮手(子 agent)负责判断,中间结果放在台面上的碗里 —— 不塞进群聊记录。
|
||||
模型既当厨师又当记事本时,感觉就是这样:计划与动手挤在同一段对话里。**Workflow** 则是写好的菜谱。厨房(runtime)按谱做,帮手(子 agent)负责尝和判断,半成品放在台面上的碗里,而不是塞进群聊记录。
|
||||
|
||||
## 为什么需要 harness?
|
||||
## 为什么还要另一层 harness?
|
||||
|
||||
默认的 Claude Code harness 很擅长“写代码那种形状”的工作:改、跑、看报错、再试 —— 都在同一个循环里。
|
||||
默认的 Claude Code harness 已经很擅长“写代码那种形状”的活:改一点、跑一下、看报错、再试。一个循环、一颗脑袋,能做出不少工艺。
|
||||
|
||||
有些活需要**叠一层定制 harness**:深度调研、安全分析、agent teams、大规模 code review。你可以事先用 SDK 手写那层 harness;也可以 —— 这就是动态的想法 —— 让 Claude **为这次任务现场写一个 harness**,跑完,好用的再存下来。
|
||||
可有些活是另一种形状——深度调研、安全排查、agent teams、要铺开审查一整片改动。这类事,人们早就习惯在上面再搭一层定制 harness。你当然可以事先用 SDK 手写;也可以——这才是有意思的地方——让 Claude **为这次任务**起草一个 harness,跑起来,好用的再留下来。
|
||||
|
||||
课程的口号往上提一层:每一步里信任模型;步骤之间的结构,靠工程来定。
|
||||
课程那句口号往上提一层:每一步里信任模型;步骤怎么排,由你来定结构。
|
||||
|
||||
## 问题:一个窗口,三种走偏
|
||||
## 长对话里你会看见的走偏
|
||||
|
||||
从 s01 到 s15,模型在**同一个**上下文里既规划又执行。当“下一步取决于刚才发现了什么”时,这很合适。当任务又长、又要大规模并行、又要求死板结构、或需要对抗验证时,就会变脆。
|
||||
从 s01 到 s15,计划与执行共享同一个上下文。下一步取决于刚才的发现时,这很舒服。
|
||||
|
||||
Claude Code 的设计者给单窗口里常见的三种失败起了名字。用大白话说:
|
||||
可一旦任务变长、要大规模并行、结构又死板,或需要一个挑剔的第二意见,它就会发脆。你若耐心看一段很长的聊天,会撞见熟面孔:做到五十项里的三十五就宣布完工;让它批改自己的作业,分数总是偏甜——狐狸给鸡窝打分;多轮对话和压缩过后,那句轻轻的“别动 X”渐渐听不见了。
|
||||
|
||||
| 失败模式 | 感觉起来像什么 |
|
||||
|----------|----------------|
|
||||
| **Agentic laziness(偷懒收工)** | 五十项审查做到三十五,就说“做完了” |
|
||||
| **Self-preferential bias(自我偏爱)** | 让它检查自己的结论时,总觉得自己更对 —— 狐狸给鸡窝打分 |
|
||||
| **Goal drift(目标漂移)** | 原来的“别动 X”在多轮对话和压缩之后渐渐淡掉 |
|
||||
Claude Code 的设计者把这些叫做 agentic laziness、self-preferential bias、goal drift。名字不如感觉重要:同一个窗口既要干活,又要记住计划。对话历史太软,扛不住并行、稳定的结果形状,以及崩了还能续上。审查很多文件、先调研再验证、按同一方式迁移 N 个模块——这些活的形状事先就清楚。软记忆不够用。
|
||||
|
||||
对话历史也很难同时扛住并行、稳定的结果形状、以及续跑。审查很多文件、先调研再验证、按同一方式迁移 N 个模块 —— 这些活的**形状**事先就知道,更需要那三样。
|
||||
## 点子落下的那一下
|
||||
|
||||
## 一句话说清想法
|
||||
假如计划住在代码里呢?
|
||||
|
||||
**把编排从“靠聪明”挪到“靠结构”。**
|
||||
帮手仍然负责想——每人一张干净桌子,一件专注的事。**脚本**掌管循环、分发和合并。中间结果待在变量和 journal 里,不进对话。想偷懒提前收工的习惯,更难叫停整支队伍;自我检查的偏心,会撞上一个不是作者本人的第二帮手;漂移也难下手,因为拓扑不再由一个疲倦的叙述者每轮改写。
|
||||
|
||||
子 agent 仍然负责判断 —— 各自干净的上下文、专注的目标。**脚本**负责循环、分发和合并。中间结果存在变量(和 journal)里,不进对话。分开的帮手 + 脚本掌握的控制流,就是对抗偷懒、自我检查偏差和漂移的办法。
|
||||
一句话:workflow 把编排从“靠聪明”挪到“靠结构”。模型仍在每次 `agent()` 里做判断;地图归脚本管。
|
||||
|
||||

|
||||
|
||||
一次 `Workflow` 工具调用启动这次脚本运行。运行中会发出生命周期和进度事件;最后一条工具结果带回启动信息、结果和任务状态。
|
||||
一次 `Workflow` 工具调用启动这次运行。进度在旁边轻轻响;最后一条工具结果带回启动信息、结果和任务状态。
|
||||
|
||||
## 两扇门 — 以及动态 vs 静态
|
||||
## 同一间厨房,两扇门
|
||||
|
||||
Claude Code 用两扇门走进同一间厨房:
|
||||
Claude Code 对入口说得很直白。
|
||||
|
||||
| 门 | 你传什么 | 什么时候用 |
|
||||
|----|----------|------------|
|
||||
| **动态(Dynamic)** | 一段编排用的 JavaScript(`script`,或之后的 `scriptPath`) | 模型为**这次任务**现写菜谱 |
|
||||
| **已保存(Saved)** | `name` + `args` | 好用的菜谱放进例如 `.claude/workflows/`,按名字再跑 |
|
||||
有时模型为*这次*任务写一段编排用的 JavaScript,以 `script` 交出来(或之后改 `scriptPath`)。这是**动态**那扇门——问题还热着,就裁出一件合身的 harness。
|
||||
|
||||
同一间厨房。动态是“现在写菜谱”;已保存是“从卡片盒里抽一张”—— 一次漂亮动态运行留下来的可复用残渣。
|
||||
有时好脚本已经进了例如 `.claude/workflows/`。你用 `name` 和 `args` 再请它出来。这是**已保存**那扇门——一次值得留下的运行,沉淀成可复用的卡片。
|
||||
|
||||
本课之外还有表亲:**静态** harness(事先写好的 Agent SDK / `claude -p` 编排)。静态的要覆盖所有边角,所以往往更泛用。动态的是为*这次*任务量身定做;合身了再存成 saved。
|
||||
本课之外还有表亲:**静态** harness,用 Agent SDK 或 `claude -p` 事先写好。它们得扛住所有边角,所以往往更泛。动态的是为这块布现裁的;合身了再存。
|
||||
|
||||
**本课是一个 Python 教学运行时。** 同样的想法,每行你都能读懂。演示按名字注册一个已保存的 workflow;概念和 Claude Code 的脚本世界一一对应。我们**不会**再说“模型不能提交可执行代码”——那是对 Claude Code 的误述。这里只是不嵌入完整的 JS 解释器。
|
||||
**这一章是 Python 教学运行时。** 同样的想法,每行都能读。演示按名字挂了一个已保存的 workflow;概念和 Claude Code 的脚本世界一一对应。我们不会再说“模型不能提交可执行代码”——那从来不是 Claude Code 的真相。这里只是不嵌入完整的 JS 解释器。
|
||||
|
||||
```python
|
||||
# 教学适配器:已保存这扇门(name + args)。
|
||||
@@ -81,44 +74,35 @@ WORKFLOW_TOOL = {
|
||||
}
|
||||
```
|
||||
|
||||
## 原语:用一次义卖来讲
|
||||
## 厨房里的几个动词
|
||||
|
||||
学校义卖要烤很多蛋糕。每张桌子都要:搅拌 → 烘烤 → 装箱。帮手负责尝和判断;菜谱决定顺序。
|
||||
想象学校义卖要烤许多蛋糕。每张桌子都是搅拌 → 烘烤 → 装箱。帮手负责尝;菜谱决定先后。
|
||||
|
||||
| 原语 | 在厨房里的意思 |
|
||||
|------|----------------|
|
||||
| `agent(prompt, {schema, label, phase})` | 请一个帮手做一件事 |
|
||||
| `pipeline(items, *stages)` | **默认。** 每块蛋糕自己走完搅拌→烘烤→装箱。A 在装箱时,B 可能还在搅拌 |
|
||||
| `parallel(thunks)` | 等**所有**托盘都回来 —— 只有下一步真的需要全部结果时才用 |
|
||||
| `phase(title)` | 在进度板上宣布“现在进入烘烤” |
|
||||
| `log(message)` | 喊一句短状态 |
|
||||
| `workflow(name, args)` | 套用一份更小的菜谱(只嵌一层) |
|
||||
| `args` | 这次运行的“食材清单” |
|
||||
| `budget` | 还能烧多少“烤箱分钟”(token) |
|
||||
`agent(...)` 是请一个帮手做一件事。`pipeline(items, *stages)` 是默认:每块蛋糕自己走完各阶段,所以一块在装箱时,另一块可能还在搅拌。`parallel(...)` 是等齐——所有托盘都回来才往下——只有下一步真的需要全部结果时才值得,比如尝完再写评分表。
|
||||
|
||||
默认用 `pipeline`。只有下一步必须凑齐上一阶段全部结果时,才用 `parallel` —— 比如要先尝完所有托盘再写评分表。
|
||||
旁边还有更轻的词:`phase` 在进度板上报站,`log` 喊一句短话,`workflow` 嵌一份更小的菜谱,`args` 是食材清单,`budget` 是还能烧多少烤箱分钟(token)。
|
||||
|
||||
```python
|
||||
# 每个审查维度独立走 审计 → 验证(阶段之间不等齐)。
|
||||
# 每个审查维度自己走完 审计 → 验证。
|
||||
results = await ctx.pipeline(DIMENSIONS, audit, verify)
|
||||
confirmed = [f for r in results if r for f in r["confirmed"]]
|
||||
```
|
||||
|
||||
## 有品味的模式(不是清单倾销)
|
||||
## 模式:用得着才拿
|
||||
|
||||
把模式想成菜谱风格。示例 `review-changes` 主要用了三种:
|
||||
不必背目录。看清示例在干什么,手里就有三种风格。
|
||||
|
||||
| 模式 | 大白话 | 在示例里 |
|
||||
|------|--------|----------|
|
||||
| **Fan-out-and-synthesize(分发再汇总)** | 拆开干,每人一张干净桌子,再合并 | 四个维度在 `pipeline` 里审计,最后合成确认列表 |
|
||||
| **Adversarial verification(对抗验证)** | 第二个帮手专门来挑刺 | 每条 finding 先过 verify agent 才作数 |
|
||||
| **Generate-and-filter(生成再过滤)** | 先产出候选,只留通过检验的 | findings 进来 → 只留 `isReal` |
|
||||
它把改动**分发**到各个审查维度,每人一张干净桌子,再**汇总**成一份确认列表——fan-out-and-synthesize。碎片若挤在同一个嘈杂上下文里会互相串味时,这一招值钱。
|
||||
|
||||
同一工具箱里还有别的风格,以后会遇到:**classify-and-act**(按类型分流)、**tournament**(比武再选冠军)、**loop-until-done**(直到没有新发现再停)。只有当额外成本能换来更清楚或更稳妥的结果时,才上模式。
|
||||
验证阶段里,第二个帮手专门来挑每条 finding 的刺——adversarial verification,结构上回答“别给自己的作业打高分”。
|
||||
|
||||
## 让答案机器能读
|
||||
留下来的,是对生成物做过滤。Generate-and-filter:候选进来,过关的留下。
|
||||
|
||||
如果帮手回来写散文,下一阶段就很难把 finding 和 verdict 一一对应。传入 `schema`:运行时要求 JSON、做校验,不对就**重试一次**。再不对,这次调用报错(见下面的空值隔离)。
|
||||
同一工具箱里还有 classify-and-act、tournament、loop-until-done,以后都会遇见。只有额外成本能买到更清楚或更稳妥的结果时,才去借一种风格。
|
||||
|
||||
## 让下一阶段接得住的答案
|
||||
|
||||
帮手若回来写散文,下一阶段很难把 finding 和 verdict 对齐。传入 `schema`。运行时要 JSON、做校验,并给**一次**重试。再不对,这次调用报错——而舰队在失败时怎样仍然温和,下一节就说到。
|
||||
|
||||
```python
|
||||
out = await ctx.agent(
|
||||
@@ -126,60 +110,49 @@ out = await ctx.agent(
|
||||
schema=FINDINGS_SCHEMA,
|
||||
label=f"audit:{dimension}",
|
||||
)
|
||||
# out 是带 "findings" 的字典,不是一段话
|
||||
```
|
||||
|
||||
跟你聊天可以用自然语言;流水线需要接口对得上。
|
||||
跟你聊天可以继续用自然语言。流水线需要接口对得上。
|
||||
|
||||
## 一个帮手失败时
|
||||
## 一个托盘糊了的时候
|
||||
|
||||
不能因为一个托盘糊了,整支队伍停工。
|
||||
不能因为一个帮手烤箱失手,整支队伍停工。
|
||||
|
||||
- **`parallel`**:失败的 thunk 在该槽位变成 `null` / `None`;整个 gather 不会因此拒绝。
|
||||
- **`pipeline`**:某个 stage 失败时,**该 item** 变成 `null` / `None`,并跳过它后面的 stage;其他 item 继续。
|
||||
|
||||
合并前要小心过滤 —— 常见写法是 `if r` / `.filter(Boolean)`。
|
||||
在 `parallel` 里,失败的 thunk 在该槽位变成 `null` / `None`,gather 本身不会拒绝。在 `pipeline` 里,某个 stage 失败会把**那个 item** 置成空,并跳过它后面的 stage;别的 item 继续往前走。合并前小心过滤——`if r`,在 JS 里常见 `.filter(Boolean)`。
|
||||
|
||||
```python
|
||||
verdicts = await ctx.parallel([...]) # 有些位置可能是 None
|
||||
verdicts = await ctx.parallel([...]) # 有些格子可能是 None
|
||||
confirmed = [
|
||||
f for f, v in zip(findings, verdicts)
|
||||
if v and v.get("isReal")
|
||||
]
|
||||
```
|
||||
|
||||
## Journal 与续跑
|
||||
## 一本可以重开的笔记本
|
||||
|
||||
每次运行都有一个 `runId`。每个 `agent()` 结束后,运行时往磁盘上的 journal 追加一行。把它想成笔记本:按你**召唤**帮手的顺序记,而不是按他们从烤箱回来的先后。
|
||||
每次运行都有一个 `runId`。每个 `agent()` 结束,磁盘上的 journal 就多一行——按你**召唤**帮手的顺序记,而不是按他们从烤箱回来的先后。
|
||||
|
||||
续跑时(`resume_from_run_id` / `resumeFromRunId`),脚本仍从开头执行,但是:
|
||||
续跑(`resume_from_run_id` / `resumeFromRunId`)仍从脚本开头走,只是更客气:按调用顺序,与下一条 journal 比对;最长未改前缀直接从缓存回放;碰到第一个改过或未完成的调用,前缀断开——之后全部实跑,即便笔记本更后面还躺着旧 key,也不能跳过裂缝偷懒命中。
|
||||
|
||||
1. 按调用顺序,把每次 `agent()` 和下一条 journal 记录比对。
|
||||
2. **最长未改前缀** → 缓存命中(直接回放)。
|
||||
3. 遇到**第一个**改过或未完成的调用,前缀断开。
|
||||
4. **之后全部实跑** —— 即使 journal 更后面还躺着旧 key,也不能偷懒命中。
|
||||
|
||||
所以真正的 JS workflow 运行时会禁止 `Date.now()`、`Math.random()` 和裸的 `new Date()`:不确定的时钟和骰子会改 prompt 或调用顺序,笔记本就对不上了。这个 Python 演示不会完整沙箱这些 —— 但脚本仍应写成确定性的。
|
||||
这也是真正的 JS workflow 运行时禁止 `Date.now()`、`Math.random()` 和裸 `new Date()` 的原因。时钟和骰子会让 prompt 或调用顺序晃一下,笔记本就对不齐了。这个 Python 演示不会完整沙箱那些东西。脚本仍写成确定性的吧。
|
||||
|
||||
```text
|
||||
journal: [A ✓] [B ✓] [C ✓] [D ✓]
|
||||
续跑: A 命中 → B 命中 → C 改过 → D 实跑(不会悄悄命中旧的 D)
|
||||
续跑: A 命中 → B 命中 → C 改过 → D 实跑
|
||||
```
|
||||
|
||||
## 跟着示例走:`review-changes`
|
||||
## 跟着 `review-changes` 走一圈
|
||||
|
||||
四个审查维度走同一条两阶段路径 —— 先分发,再对抗验证,再过滤:
|
||||
四个维度共用一条两阶段路径——先铺开,再对抗验证,留下活下来的:
|
||||
|
||||
```text
|
||||
correctness ── 审计 ── 验证 ──┐
|
||||
security ── 审计 ── 验证 ──┤── 合并确认过的问题
|
||||
security ── 审计 ── 验证 ──┤── 确认过的问题
|
||||
performance ── 审计 ── 验证 ──┤
|
||||
style ── 审计 ── 验证 ──┘
|
||||
```
|
||||
|
||||
1. **Review** — 每个维度的审计员返回结构化 findings(干净桌子 → 少串味)。
|
||||
2. **Verify** — 每条 finding 交给对抗性检查(在 verify 阶段里用 `parallel`),作者不当裁判。
|
||||
3. 只保留被标成真实的问题,再按严重程度排序。
|
||||
Review 让每个审计员坐自己的桌子,正确性的闲聊不至于淌进安全性。Verify 把每条 finding 交给不是作者的怀疑者。只留下真的,再按严重程度排好。那三种走偏,会感觉自己最爱的座位被撤了。
|
||||
|
||||
```python
|
||||
async def sample_workflow(ctx, args):
|
||||
@@ -190,64 +163,46 @@ async def sample_workflow(ctx, args):
|
||||
return {"confirmed": confirmed}
|
||||
```
|
||||
|
||||
## 怎样接到 s15
|
||||
## 挂在 s15 上,并不取代它
|
||||
|
||||
s15 仍是宿主循环。s16 只多一个工具:`Workflow`。模型(或你)给出已保存的名字;适配器查 registry,再跑脚本。
|
||||
s15 仍是宿主循环。s16 只多了一个名叫 `Workflow` 的工具。你(或模型)报一个已保存的名字;适配器找到脚本再跑。
|
||||
|
||||
| | Claude Code / Pi(产品) | 本课教学 CLI |
|
||||
|--|--------------------------|--------------|
|
||||
| 脚本语言 | 沙箱里的 JavaScript | 可读的 Python 函数 |
|
||||
| 动态门 | 模型写 `script` / 改 `scriptPath` | 文档说明;演示走已保存的 `name` |
|
||||
| 运行时宿主 | 后台 + 通知,会话保持可响应 | `demo` / `resume` 前台跑,方便观察 |
|
||||
| 想法 | 同一套原语、journal、前缀续跑 | 教学模型 —— 简化处会说清楚 |
|
||||
在真正的产品里,这次运行可以待在后台、带着通知,会话照样能应你。教学 CLI 把 `demo` / `resume` 放在前台,好让你看清阶段和缓存命中。想法相同;简化之处我们会明说。
|
||||
|
||||
主循环不会变成 workflow 引擎。它只是多借一把工具,就像借 `bash` 或 `task` 一样。
|
||||
主循环不会变成 workflow 引擎。它只是多借一把工具,就像借 `bash` 或 `task`。
|
||||
|
||||
## 邻居们:谁握着计划?
|
||||
## 转一转这颗宝石:谁握着计划?
|
||||
|
||||
Workflow 不是“多派几个 agent”。它改的是**谁拥有拓扑结构**。
|
||||
看看邻居,同一件东西会露出新的面。有用的问题不是“几个 agent?”,而是**谁拥有拓扑**,半成品的碗放在哪。
|
||||
|
||||
| 邻居 | 谁握着计划 | 中间结果住哪 | 最适合 |
|
||||
|------|------------|--------------|--------|
|
||||
| [s06 子 Agent](../s06_subagent/) | 模型,一次性 | 除最终摘要外丢掉 | 隔离一个脏的子任务 |
|
||||
| [s13 Agent Teams](../s13_agent_teams/) | Lead 模型逐轮 + 邮箱 | 共享任务 / 消息 | 长跑同伴、偏人类协作 |
|
||||
| [s06 子 Agent](../s06_subagent/) | 模型,一次性 | 多半丢掉 | 隔离一个脏的子任务 |
|
||||
| [s13 Agent Teams](../s13_agent_teams/) | Lead 逐轮 + 邮箱 | 共享任务 / 消息 | 长跑的同伴 |
|
||||
| [s15 Agent Harness 集成](../s15_integrated_harness/) | 模型在一个循环里 | 对话 `messages[]` | 累积型 coding agent |
|
||||
| **s16 Workflow** | **脚本** | **脚本变量 + journal** | 已知 / 大规模结构化分发 + 验证 |
|
||||
| [s17 Goal Loop](../s17_goal_loop/) | 停止边界上的判断器 | 对话当证据 | “整个目标做完了吗?” |
|
||||
| **s16 Workflow** | **脚本** | **变量 + journal** | 结构化分发与验证 |
|
||||
| [s17 Goal Loop](../s17_goal_loop/) | 停止时的判断器 | 对话当证据 | “整个目标做完了吗?” |
|
||||
|
||||
更便宜的替代方案经常就够用:skill / prompt 当软计划、一小段多 agent 闲聊、手写静态 SDK 编排,或者干脆更大的单轮模型调用。当结构必须比单个上下文活得更久时,再伸手去拿 workflow —— 不是因为“专家团”听起来很酷。
|
||||
更便宜的路经常就够:skill 当软计划、一小段多 agent 闲聊、手写静态编排,或更大的单轮模型调用。当结构必须比单个上下文活得更久,再伸手去拿 workflow——不是因为“专家团”听起来很酷。
|
||||
|
||||
## 什么时候*别*用 workflow
|
||||
## 什么时候先放回架子上
|
||||
|
||||
Workflow 要花 token,也有协调成本。大多数普通写代码的活,**不需要**五人评审团。
|
||||
Workflow 要花 token,也有协调成本。大多数普通写代码,并不需要五人评审团。
|
||||
|
||||
问问自己:这件事真的需要更多算力和定制 harness 吗?如果普通的 s15 一轮(或一个 s06 子 agent)就够,就停在那儿。克制也是设计思想的一部分 —— 并行和分工必须赚回自己的成本。
|
||||
动手前问一句:这活真的想要更多算力和一层定制 harness 吗?若普通的 s15 一轮——或一个老实的 s06 子 agent——就够,就停在那儿。克制也是思想的一部分:并行和分工得赚回自己的位置。
|
||||
|
||||
## 试一下
|
||||
|
||||
```bash
|
||||
python s16_workflow_runtime/code.py # s15 宿主 + Workflow 工具(真实 API)
|
||||
python s16_workflow_runtime/code.py demo # 固定数据:观察阶段和 agent
|
||||
python s16_workflow_runtime/code.py resume # 同一个 runId;前缀应全部缓存命中
|
||||
python s16_workflow_runtime/code.py # s15 宿主 + Workflow(真实 API)
|
||||
python s16_workflow_runtime/code.py demo # 固定数据;看阶段
|
||||
python s16_workflow_runtime/code.py resume # 同一 runId;期待缓存命中
|
||||
```
|
||||
|
||||
留意这些:
|
||||
看 Review 让给 Verify;看完整续跑时 agent 从 `done` 翻成 `cached`。结尾是一份短短的确认列表——干净续跑会显示 `agents=0 tokens=0`,像笔记本在说:没有什么需要重新加热。
|
||||
|
||||
- `workflow_phase`:先 Review,再 Verify
|
||||
- 每个 `workflow_agent`:第一次是 `done`,完整续跑变成 `cached`
|
||||
- 结尾有一份简短的确认列表;全命中续跑显示 `agents=0 tokens=0`
|
||||
## 接下来
|
||||
|
||||
## 相对 s15 → 下一站 s17
|
||||
s16 讲一批活怎么跑。[s17 Goal Loop](../s17_goal_loop/) 在门口问另一个问题:该停,还是再来一轮?可重复的菜谱若还需要硬性的“做完”,可以和它一起用。
|
||||
|
||||
| | s15 Agent Harness 集成 | s16 Workflow Runtime |
|
||||
|--|------------------------|----------------------|
|
||||
| 循环 | 单个、模型驱动 | 同一循环;一个工具跑脚本 |
|
||||
| 谁决定下一步 | 模型逐轮决定 | 脚本规定整批形状 |
|
||||
| 多 agent | 一次性子 agent | 可脚本化、可续跑的 `agent()` |
|
||||
| 失败 / 续跑 | 靠对话记忆 | 空值隔离 + journal 前缀 |
|
||||
|
||||
**s16 = 一批活怎么跑。s17 = 整个目标算不算做完。**
|
||||
|
||||
[s17 Goal Loop](../s17_goal_loop/) 会问一个独立判断器:该停,还是再来一轮?可重复的 workflow 若还需要硬性完成条件,可以和它配对。
|
||||
|
||||
<!-- translation-sync: zh@v12, en@v12, ja@v12 -->
|
||||
<!-- translation-sync: zh@v13, en@v13, ja@v13 -->
|
||||
|
||||
Reference in New Issue
Block a user