Use official harness-essay figures in s16 chapter

Pull Anthropic essay PNGs (primitives, dynamic-vs-static, six patterns,
quarantine triage) into images/, wire them into EN/ZH/JA with captions,
and add a short untrusted-input beat. Drop substitute SVGs for those four.

Co-authored-by: Xinlu Lai <CrazyBoyM@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-08-12 13:59:31 +00:00
parent 4c4160a2df
commit 02c93c8616
17 changed files with 60 additions and 502 deletions

View File

@@ -56,9 +56,9 @@ Claude Code は入口について率直です。
外にはいとこもあります。Agent SDK や `claude -p` で先に書く **static** harness です。あらゆるエッジケースに耐える必要があるので、どうしても汎用になります。dynamic はこの布のための裁断です。形が合ったら保存します。
![Static harness vs dynamic workflow](images/dynamic-vs-static.svg)
![Static harness vs dynamic workflow](images/dynamic-vs-static.png)
*同じ問い。左: いつも汎用レポートに終わる汎用パイプライン。右: 自分のコードを読み、自分の取引量で値段を見、devil's advocate を呼特注レシピ。*
*Claude Code の設計エッセイより。同じ問い、ふたつの harness。左 — 固定の検索→検証→要約で、汎用レポートに終わる。右 — billing コードを読み、分岐し、devil's advocate を呼んでから具体的な推奨を出す特注レシピ。*
**この章は Python の teaching runtime です。** 同じアイデアを、1 行ずつ読める形で示します。デモは名前で一つの saved workflow を登録します。概念は Claude Code の script 世界と一一対応です。「モデルは実行可能コードを渡せない」などと言いません——それは Claude Code については初めから正しくありませんでした。ここでは、完全な JavaScript インタプリタを埋め込まないだけです。
@@ -84,9 +84,11 @@ WORKFLOW_TOOL = {
学校のバザーでケーキをたくさん焼くとします。どのテーブルも 混ぜる → 焼く → 箱詰め。助手が味見をし、レシピが順番を決めます。
![Workflow primitives](images/workflow-primitives.svg)
![Workflow primitives: agent, parallel, pipeline](images/workflow-primitives.png)
`agent(prompt, {schema, label, phase})` は、助手ひとりに一つの仕事を頼むことです。`schema` を付ければ、答えは検証済み JSON になり——次の段が受け取れるソケットになり——最初が雑なら一回だけやり直せます。
*公式のプリミティブ・カード。ひとつの `agent` と、多くを走らせる二つのやり方 — `parallel`barrierと `pipeline`(各 item が自分の stage を流れる)。*
`agent(prompt, opts?)` は、助手ひとりに一つの仕事を頼むことです。`schema` を付ければ、答えは検証済み JSON になり——次の段が受け取れるソケットになり——最初が雑なら一回だけやり直せます。本物の Claude Code では `model``isolation`worktree / remote`agentType` も選べます。この teaching runtime は表面を小さく保ち、1 行ずつ読めるようにしています。
`pipeline(items, *stages)` は多段仕事の既定です。各ケーキが自分で段階を歩き、一方が箱詰めのあいだに、もう一方はまだ混ぜていてもよい。stage 間に barrier はありません。
@@ -113,9 +115,9 @@ resume: A hit → B hit → C 変更 → D は live
動詞は小麦粉と火加減です。人が何度も発明し直すのは、少数の*形*です。道具箱だと思ってください。必点メニューではありません。
![Six Workflow Patterns](images/six-workflow-patterns.svg)
![Six Workflow Patterns](images/six-workflow-patterns.png)
*人が何度も発明する六つの形。トポロジーは script が持ち、このレッスンでは `agent` / `parallel` / `pipeline` / `phase` / journal で話します。*
*公式の六パターン格子 — 道具箱であり、必点メニューではない。トポロジーは script が持ち、このレッスンでは `agent` / `parallel` / `pipeline` / `phase` / journal で各形を話します。*
**Classify-And-Act。** 痛み: 万能の助手は何でもそこそこ。形: classifier が見て、専門家 A / B / C へ振り分ける。ここ: `agent({schema})` がラベルを返し、script が続く `agent`(または入れ子の `workflow`)へ分岐。全部が本当に同じ扱いでよいなら使わない。
@@ -140,7 +142,17 @@ resume: A hit → B hit → C 変更 → D は live
| Tournament | pairwise 審判 `agent` | 順位/味に鋭い物差しがない |
| Loop Until Done | `while` + 停止 + `budget` | どれだけ埋まっているか不明 |
組み合わせはふつうです。深い調査はしばしば fanout → filter → verify → synthesize と重ねます。トリアージでは **quarantine** を足すこともあります。信頼できない内容を読む agent は read-only のまま、trusted な actor だけが PR を開きます。私たちのサンプルは、二つの音の小さな和音です。
組み合わせはふつうです。深い調査はしばしば fanout → filter → verify → synthesize と重ねます。私たちのサンプルは、二つの音の小さな和音です。
### 信頼できない入力に workflow が出会うとき
道具箱のそばにもう一つ残しておきたい形があります。**quarantine triage** です。サポートチケット、bug 報告、ユーザーフィードバックは信頼できません。それらを*読む* agent に、PR を開ける鍵まで持たせたくはありません。
![Quarantine triage](images/quarantine-triage.png)
*Reader は read-only の quarantine に留まり、分類と dedupe をし、構造化 summary だけを渡します。高権限ツールは trusted 側に住み — summary にだけ作用し、生本文には触れません。バックログが眠らないなら `/loop` と組んでもよいです。*
このレッスンのプリミティブでは、それも script と agent です。低権限 reader `agent``pipeline``parallel`、変数に入った構造化 summary、それから書く側の別 actor `agent`(または入れ子の `workflow`)。面白いのはエアロック — 誰が生テキストを見てよいか、です。
## `review-changes` を歩く — ひとつの composition
@@ -211,4 +223,4 @@ Review が Verify に道を譲るのを見てください。完全な resume で
s16 はバッチの回し方です。[s17 Goal Loop](../s17_goal_loop/) は戸口で別の問いをします。止めるべきか、もう一ターンか。繰り返せるレシピに硬い「完了」も要るときは、そちらと組んでください。
<!-- translation-sync: zh@v15, en@v15, ja@v15 -->
<!-- translation-sync: zh@v16, en@v16, ja@v16 -->

View File

@@ -56,9 +56,9 @@ Sometimes a good script has already been saved under something like `.claude/wor
There is also a cousin: **static** harnesses you write ahead of time with the Agent SDK or `claude -p`. Those must survive every edge case, so they stay generic. Dynamic ones are cut for *this* cloth; save them when the fit is right.
![Static harness vs dynamic workflow](images/dynamic-vs-static.svg)
![Static harness vs dynamic workflow](images/dynamic-vs-static.png)
*Same question. Left: a generic pipeline that always ends in a generic report. Right: a tailor-made workflow that reads your code, prices your volume, and invites a devils advocate.*
*From Claude Codes design essay: same question, two harnesses. Left a fixed search→verify→summarize pipeline that ends in a generic report. Right a tailor-made workflow that reads your billing code, branches, and invites a devils advocate before recommending.*
**This chapter is a Python teaching runtime.** Same ideas, every line readable. Our demo registers one saved workflow by name; the concepts map one-to-one onto Claude Codes script world. We will not pretend “the model cannot submit executable code” — that was never true of Claude Code. We simply do not embed a full JavaScript interpreter here.
@@ -84,9 +84,11 @@ WORKFLOW_TOOL = {
Imagine a school bake sale. Every table needs mix → bake → box. Helpers taste; the recipe decides order.
![Workflow primitives](images/workflow-primitives.svg)
![Workflow primitives: agent, parallel, pipeline](images/workflow-primitives.png)
`agent(prompt, {schema, label, phase})` asks one helper to do one job. With a `schema`, the answer comes back as validated JSON — a socket the next stage can hold — with one retry if the first reply is messy.
*Official primitive card: one `agent`, then the two ways to run many — `parallel` (barrier) vs `pipeline` (each item streams its stages).*
`agent(prompt, opts?)` asks one helper to do one job. With a `schema`, the answer comes back as validated JSON — a socket the next stage can hold — with one retry if the first reply is messy. Real Claude Code also lets you pick `model`, `isolation` (worktree / remote), and `agentType`; this teaching runtime keeps the surface smaller so every line stays readable.
`pipeline(items, *stages)` is the default for multi-stage work. Each cake walks its stages alone, so one can be boxing while another is still mixing. No barrier between stages.
@@ -113,9 +115,9 @@ resume: A hit → B hit → C changed → D runs live
The verbs are flour and heat. What people keep reinventing are a handful of *shapes*. Think of them as a toolbox, not a mandatory menu.
![Six Workflow Patterns](images/six-workflow-patterns.svg)
![Six Workflow Patterns](images/six-workflow-patterns.png)
*Six shapes people keep reinventing. The script owns the topology; this lesson speaks them with `agent` / `parallel` / `pipeline` / `phase` / journal.*
*The official six-pattern grid — a toolbox, not a mandatory menu. The script owns the topology; this lesson speaks each shape with `agent` / `parallel` / `pipeline` / `phase` / journal.*
**Classify-And-Act.** Pain: one generic helper is mediocre at everything. Shape: a classifier looks, then routes to specialist A, B, or C. Here: one `agent({schema})` returns a label; the script branches to the right follow-up `agent` (or a nested `workflow`). Skip it when every item truly needs the same treatment.
@@ -140,7 +142,17 @@ After a few have faces, the toolbox fits in one glance:
| Tournament | pairwise judge `agent`s | Ranking / taste without a sharp scale |
| Loop Until Done | `while` + stop + `budget` | Unknown amount of buried work |
Compositions are normal. Deep research often stacks fanout → filter → verify → synthesize. Triage sometimes adds a **quarantine**: readers of untrusted content stay read-only; only a trusted actor opens PRs. Our sample is a smaller chord of two notes.
Compositions are normal. Deep research often stacks fanout → filter → verify → synthesize. Our sample is a smaller chord of two notes.
### When workflows meet untrusted input
One more shape is worth keeping near the toolbox: **quarantine triage**. Support tickets, bug reports, and user feedback are untrusted. You do not want the agent that *reads* them to also hold the keys that open a PR.
![Quarantine triage](images/quarantine-triage.png)
*Readers stay in a read-only quarantine, classify and dedupe, and pass only a structured summary across. High-privilege tools live on the trusted side — they act on summaries, never on raw content. Pair with `/loop` if the backlog never sleeps.*
In this lessons primitives that is still just scripts and agents: a `pipeline` or `parallel` of low-privilege reader `agent`s, a structured summary in a variable, then a separate actor `agent` (or nested `workflow`) that may write. The interesting part is the airlock — who is allowed to see the raw text.
## Walking `review-changes` — a composition
@@ -211,4 +223,4 @@ Watch Review give way to Verify. Watch agents flip from `done` to `cached` on a
s16 is how a batch runs. [s17 Goal Loop](../s17_goal_loop/) asks a different question at the door: should we stop, or take another turn? Pair them when a repeatable recipe also needs a hard “done.”
<!-- translation-sync: zh@v15, en@v15, ja@v15 -->
<!-- translation-sync: zh@v16, en@v16, ja@v16 -->

View File

@@ -56,9 +56,9 @@ Claude Code 对入口说得很直白。
门外还有表亲:**静态** harness用 Agent SDK 或 `claude -p` 事先写好。它们得扛住所有边角,所以往往更泛。动态的是为这块布现裁的;合身了再存。
![静态 harness 与动态 workflow](images/dynamic-vs-static.svg)
![静态 harness 与动态 workflow](images/dynamic-vs-static.png)
*同一个问题。左边:永远通向一份泛泛研究报告的通用流水线。右边读你的代码、按你的量计价、再请来魔鬼代言人的特制菜谱*
*来自 Claude Code 设计文:同一个问题,两套 harness。左边——固定的搜索→验证→摘要终点是一份泛泛研究报告。右边——读你的 billing 代码、分叉、再请来魔鬼代言人,最后给出具体建议*
**这一章是 Python 教学运行时。** 同样的想法,每行都能读。演示按名字挂了一个已保存的 workflow概念和 Claude Code 的脚本世界一一对应。我们不会再说“模型不能提交可执行代码”——那从来不是 Claude Code 的真相。这里只是不嵌入完整的 JS 解释器。
@@ -84,9 +84,11 @@ WORKFLOW_TOOL = {
想象学校义卖要烤许多蛋糕。每张桌子都是搅拌 → 烘烤 → 装箱。帮手负责尝;菜谱决定先后。
![Workflow 原语](images/workflow-primitives.svg)
![Workflow 原语agent、parallel、pipeline](images/workflow-primitives.png)
`agent(prompt, {schema, label, phase})` 是请一个帮手做一件事。带上 `schema`,答案会变成校验过的 JSON——下一阶段接得住的接口——第一次不对还给一次重试。
*官方原语卡片:一个 `agent`,以及两种“跑很多”的方式——`parallel`(等齐屏障)与 `pipeline`(每个 item 自己流过各阶段)。*
`agent(prompt, opts?)` 是请一个帮手做一件事。带上 `schema`,答案会变成校验过的 JSON——下一阶段接得住的接口——第一次不对还给一次重试。真正的 Claude Code 还可以选 `model``isolation`worktree / remote`agentType`;本课教学运行时把表面收小一点,好让每一行都读得完。
`pipeline(items, *stages)` 是多阶段工作的默认:每块蛋糕自己走完各阶段,一块在装箱时,另一块可能还在搅拌。阶段之间没有等齐屏障。
@@ -113,9 +115,9 @@ journal: [A 好] [B 好] [C 好] [D 好]
动词是面粉和火候。人们反复发明的,是少数几种*形状*。把它们想成工具箱,不是必点菜单。
![六种 Workflow 模式](images/six-workflow-patterns.svg)
![六种 Workflow 模式](images/six-workflow-patterns.png)
*人们反复发明的六种形状。脚本掌管拓扑;本课用 `agent` / `parallel` / `pipeline` / `phase` / journal 把它们说出来。*
*官方六模式网格——工具箱,不是必点菜单。脚本掌管拓扑;本课用 `agent` / `parallel` / `pipeline` / `phase` / journal 把每种形状说出来。*
**Classify-And-Act分类再行动** 痛点:一个万金油帮手样样稀松。形状:分类器看一眼,再路由到专家 A、B 或 C。本课一次带 `schema``agent` 返回标签,脚本分支到对的后续 `agent`(或嵌一层 `workflow`)。每件东西其实都该同样处理时,就别用。
@@ -140,7 +142,17 @@ journal: [A 好] [B 好] [C 好] [D 好]
| Tournament | 两两裁判 `agent` | 排序/品味却没有锋利刻度 |
| Loop Until Done | `while` + 停止 + `budget` | 埋着不知多少活 |
组合是常态。深度调研常常叠成:分发 → 过滤 → 验证 → 汇总。分流有时会加一层 **quarantine隔离区**:读不可信内容的 agent 只读;只有受信任的 actor 才开 PR。我们的示例,是两个音符的一小段和弦。
组合是常态。深度调研常常叠成:分发 → 过滤 → 验证 → 汇总。我们的示例,是两个音符的一小段和弦。
### 当 workflow 碰上不可信输入
工具箱旁边还值得留一个形状:**quarantine triage隔离分流**。工单、bug 报告、用户反馈都是不可信的。你不会希望*读*它们的 agent同时也握着能开 PR 的钥匙。
![隔离分流](images/quarantine-triage.png)
*读者留在只读的隔离区里,分类、去重,只把结构化摘要递过去。高权限工具住在受信任一侧——它们只根据摘要行动,从不碰原始正文。积压永远睡不着时,可以和 `/loop` 配对。*
落到本课原语,仍是脚本和 agent一串低权限 reader `agent``pipeline``parallel`,摘要进变量,再交给另一个 actor `agent`(或嵌一层 `workflow`)去写。真正值钱的是气闸——谁被允许看见原始文本。
## 跟着 `review-changes` 走一圈——一种组合
@@ -211,4 +223,4 @@ python s16_workflow_runtime/code.py resume # 同一 runId期待缓存命中
s16 讲一批活怎么跑。[s17 Goal Loop](../s17_goal_loop/) 在门口问另一个问题:该停,还是再来一轮?可重复的菜谱若还需要硬性的“做完”,可以和它一起用。
<!-- translation-sync: zh@v15, en@v15, ja@v15 -->
<!-- translation-sync: zh@v16, en@v16, ja@v16 -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

View File

@@ -1,63 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 520" font-family="system-ui, -apple-system, sans-serif" role="img" aria-labelledby="title desc">
<title id="title">Static harness vs dynamic workflow</title>
<desc id="desc">Same question, two harnesses: a generic static pipeline versus a tailor-made dynamic workflow that reads local code and runs an adversarial check.</desc>
<defs>
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0 0 L10 5 L0 10 z" fill="#888"/></marker>
<marker id="ag" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0 0 L10 5 L0 10 z" fill="#22c55e"/></marker>
</defs>
<rect width="960" height="520" rx="8" fill="#fff"/>
<text x="480" y="28" text-anchor="middle" fill="#1a1a1a" font-size="18" font-weight="700">Same question, two harnesses</text>
<rect x="220" y="48" width="520" height="36" rx="6" fill="#fafafa" stroke="#1a1a1a" stroke-width="1.2"/>
<text x="480" y="71" text-anchor="middle" fill="#1a1a1a" font-size="12">Should we migrate our checkout service to a new provider?</text>
<line x1="350" y1="84" x2="200" y2="120" stroke="#888" stroke-width="1.3" marker-end="url(#a)"/>
<line x1="610" y1="84" x2="760" y2="120" stroke="#22c55e" stroke-width="1.5" marker-end="url(#ag)"/>
<!-- Static -->
<rect x="40" y="128" width="420" height="360" rx="8" fill="#fff" stroke="#d0d0d0" stroke-width="1.5"/>
<text x="250" y="154" text-anchor="middle" fill="#1a1a1a" font-size="14" font-weight="700">Static harness</text>
<text x="250" y="172" text-anchor="middle" fill="#888" font-size="11">written ahead - must work for every edge case</text>
<rect x="120" y="190" width="260" height="36" rx="4" fill="#fafafa" stroke="#888"/>
<text x="250" y="212" text-anchor="middle" fill="#1a1a1a" font-size="12">turn into 5 web searches</text>
<line x1="250" y1="226" x2="250" y2="244" stroke="#888" marker-end="url(#a)"/>
<rect x="120" y="246" width="260" height="36" rx="4" fill="#fafafa" stroke="#888"/>
<text x="250" y="268" text-anchor="middle" fill="#1a1a1a" font-size="12">fetch top results</text>
<line x1="250" y1="282" x2="250" y2="300" stroke="#888" marker-end="url(#a)"/>
<rect x="120" y="302" width="260" height="36" rx="4" fill="#fafafa" stroke="#888"/>
<text x="250" y="324" text-anchor="middle" fill="#1a1a1a" font-size="12">verify</text>
<line x1="250" y1="338" x2="250" y2="356" stroke="#888" marker-end="url(#a)"/>
<rect x="120" y="358" width="260" height="36" rx="4" fill="#fafafa" stroke="#888"/>
<text x="250" y="380" text-anchor="middle" fill="#1a1a1a" font-size="12">summarize</text>
<line x1="250" y1="394" x2="250" y2="412" stroke="#888" marker-end="url(#a)"/>
<rect x="120" y="414" width="260" height="40" rx="4" fill="#1a1a1a"/>
<text x="250" y="439" text-anchor="middle" fill="#fff" font-size="12" font-weight="600">a generic research report</text>
<!-- Dynamic -->
<rect x="500" y="128" width="420" height="360" rx="8" fill="#fff" stroke="#22c55e" stroke-width="1.8"/>
<text x="710" y="154" text-anchor="middle" fill="#1a1a1a" font-size="14" font-weight="700">Dynamic workflow</text>
<text x="710" y="172" text-anchor="middle" fill="#888" font-size="11">written for THIS task - then optionally saved</text>
<rect x="560" y="190" width="300" height="36" rx="4" fill="#fafafa" stroke="#1a1a1a"/>
<text x="710" y="212" text-anchor="middle" fill="#1a1a1a" font-size="12">read our billing code</text>
<rect x="560" y="234" width="88" height="24" rx="3" fill="#fff" stroke="#22c55e" stroke-dasharray="3,2"/>
<text x="604" y="250" text-anchor="middle" fill="#1a1a1a" font-size="9">billing/</text>
<rect x="656" y="234" width="88" height="24" rx="3" fill="#fff" stroke="#22c55e" stroke-dasharray="3,2"/>
<text x="700" y="250" text-anchor="middle" fill="#1a1a1a" font-size="9">webhooks/</text>
<rect x="752" y="234" width="88" height="24" rx="3" fill="#fff" stroke="#22c55e" stroke-dasharray="3,2"/>
<text x="796" y="250" text-anchor="middle" fill="#1a1a1a" font-size="9">taxes/</text>
<line x1="640" y1="258" x2="600" y2="286" stroke="#888" marker-end="url(#a)"/>
<line x1="780" y1="258" x2="820" y2="286" stroke="#888" marker-end="url(#a)"/>
<rect x="520" y="288" width="180" height="52" rx="4" fill="#fafafa" stroke="#22c55e"/>
<text x="610" y="310" text-anchor="middle" fill="#1a1a1a" font-size="10">check features vs</text>
<text x="610" y="326" text-anchor="middle" fill="#1a1a1a" font-size="10">new provider docs</text>
<rect x="720" y="288" width="180" height="52" rx="4" fill="#fafafa" stroke="#22c55e"/>
<text x="810" y="310" text-anchor="middle" fill="#1a1a1a" font-size="10">price at our</text>
<text x="810" y="326" text-anchor="middle" fill="#1a1a1a" font-size="10">transaction volume</text>
<line x1="610" y1="340" x2="670" y2="368" stroke="#888" marker-end="url(#a)"/>
<line x1="810" y1="340" x2="750" y2="368" stroke="#888" marker-end="url(#a)"/>
<rect x="560" y="370" width="300" height="40" rx="4" fill="#fff" stroke="#22c55e" stroke-dasharray="4,2"/>
<text x="710" y="395" text-anchor="middle" fill="#1a1a1a" font-size="11">devil's advocate: strongest case against</text>
<line x1="710" y1="410" x2="710" y2="428" stroke="#22c55e" marker-end="url(#ag)"/>
<rect x="560" y="430" width="300" height="40" rx="4" fill="#1a1a1a"/>
<text x="710" y="455" text-anchor="middle" fill="#fff" font-size="12" font-weight="600">a specific recommendation</text>
<text x="480" y="508" text-anchor="middle" fill="#888" font-size="10">Static aims to fit every case. Dynamic cuts cloth for this one - then save if the fit is good.</text>
</svg>

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

View File

@@ -1,108 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 720" font-family="system-ui, -apple-system, sans-serif" role="img" aria-labelledby="title description">
<title id="title">Six Workflow Patterns</title>
<desc id="description">Toolbox of six common dynamic workflow shapes.</desc>
<defs>
<marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0 0 L10 5 L0 10 z" fill="#888"/></marker>
<marker id="arr-g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0 0 L10 5 L0 10 z" fill="#22c55e"/></marker>
</defs>
<rect width="960" height="720" rx="8" fill="#fff"/>
<text x="480" y="28" text-anchor="middle" fill="#1a1a1a" font-size="18" font-weight="700">Six Workflow Patterns</text>
<text x="480" y="48" text-anchor="middle" fill="#888" font-size="11">a toolbox - not a mandatory menu. Compose with agent / parallel / pipeline</text>
<rect x="20" y="64" width="300" height="300" rx="8" fill="#fff" stroke="#d0d0d0"/>
<rect x="330" y="64" width="300" height="300" rx="8" fill="#fff" stroke="#d0d0d0"/>
<rect x="640" y="64" width="300" height="300" rx="8" fill="#fff" stroke="#d0d0d0"/>
<rect x="20" y="380" width="300" height="300" rx="8" fill="#fff" stroke="#d0d0d0"/>
<rect x="330" y="380" width="300" height="300" rx="8" fill="#fff" stroke="#d0d0d0"/>
<rect x="640" y="380" width="300" height="300" rx="8" fill="#fff" stroke="#d0d0d0"/>
<text x="170" y="88" text-anchor="middle" fill="#1a1a1a" font-size="13" font-weight="700">1. Classify-And-Act</text>
<rect x="120" y="110" width="100" height="28" rx="4" fill="#fafafa" stroke="#1a1a1a"/><text x="170" y="128" text-anchor="middle" fill="#1a1a1a" font-size="11">task</text>
<line x1="170" y1="138" x2="170" y2="158" stroke="#888" marker-end="url(#arr)"/>
<path d="M170 162 L192 184 L170 206 L148 184 Z" fill="#fff" stroke="#22c55e"/><text x="170" y="188" text-anchor="middle" fill="#1a1a1a" font-size="9">classifier</text>
<line x1="152" y1="196" x2="90" y2="230" stroke="#888" marker-end="url(#arr)"/>
<line x1="170" y1="206" x2="170" y2="230" stroke="#22c55e" stroke-width="1.8" marker-end="url(#arr-g)"/>
<line x1="188" y1="196" x2="250" y2="230" stroke="#888" marker-end="url(#arr)"/>
<circle cx="90" cy="258" r="22" fill="#fff" stroke="#1a1a1a"/><text x="90" y="262" text-anchor="middle" fill="#1a1a1a" font-size="11">A</text>
<circle cx="170" cy="258" r="22" fill="#fff" stroke="#22c55e" stroke-width="1.8"/><text x="170" y="262" text-anchor="middle" fill="#1a1a1a" font-size="11">B</text>
<circle cx="250" cy="258" r="22" fill="#fff" stroke="#1a1a1a"/><text x="250" y="262" text-anchor="middle" fill="#1a1a1a" font-size="11">C</text>
<text x="170" y="310" text-anchor="middle" fill="#888" font-size="10">route to the right specialist</text>
<text x="170" y="330" text-anchor="middle" fill="#888" font-size="9" font-family="monospace">agent -&gt; branch -&gt; agent</text>
<text x="480" y="88" text-anchor="middle" fill="#1a1a1a" font-size="13" font-weight="700">2. Fanout-And-Synthesize</text>
<rect x="430" y="110" width="100" height="28" rx="4" fill="#fafafa" stroke="#1a1a1a"/><text x="480" y="128" text-anchor="middle" fill="#1a1a1a" font-size="11">task</text>
<line x1="450" y1="138" x2="400" y2="168" stroke="#888" marker-end="url(#arr)"/>
<line x1="470" y1="138" x2="450" y2="168" stroke="#888" marker-end="url(#arr)"/>
<line x1="490" y1="138" x2="510" y2="168" stroke="#888" marker-end="url(#arr)"/>
<line x1="510" y1="138" x2="560" y2="168" stroke="#888" marker-end="url(#arr)"/>
<circle cx="400" cy="190" r="16" fill="#fff" stroke="#1a1a1a"/>
<circle cx="450" cy="190" r="16" fill="#fff" stroke="#1a1a1a"/>
<circle cx="510" cy="190" r="16" fill="#fff" stroke="#1a1a1a"/>
<circle cx="560" cy="190" r="16" fill="#fff" stroke="#1a1a1a"/>
<line x1="400" y1="206" x2="400" y2="232" stroke="#888"/>
<line x1="450" y1="206" x2="450" y2="232" stroke="#888"/>
<line x1="510" y1="206" x2="510" y2="232" stroke="#888"/>
<line x1="560" y1="206" x2="560" y2="232" stroke="#888"/>
<line x1="400" y1="232" x2="560" y2="232" stroke="#22c55e" stroke-width="3"/>
<text x="480" y="252" text-anchor="middle" fill="#22c55e" font-size="10" font-weight="600">barrier</text>
<line x1="480" y1="256" x2="480" y2="274" stroke="#22c55e" marker-end="url(#arr-g)"/>
<circle cx="480" cy="300" r="22" fill="#fff" stroke="#22c55e" stroke-width="1.8"/><text x="480" y="304" text-anchor="middle" fill="#1a1a1a" font-size="9">synthesize</text>
<text x="480" y="340" text-anchor="middle" fill="#888" font-size="9" font-family="monospace">parallel / pipeline -&gt; merge</text>
<text x="790" y="88" text-anchor="middle" fill="#1a1a1a" font-size="13" font-weight="700">3. Adversarial Verification</text>
<circle cx="720" cy="200" r="34" fill="#fff" stroke="#1a1a1a" stroke-width="1.5"/><text x="720" y="204" text-anchor="middle" fill="#1a1a1a" font-size="11">worker</text>
<line x1="754" y1="180" x2="848" y2="140" stroke="#888" marker-end="url(#arr)"/>
<line x1="754" y1="200" x2="848" y2="200" stroke="#22c55e" stroke-width="1.5" marker-end="url(#arr-g)"/>
<line x1="754" y1="220" x2="848" y2="260" stroke="#888" marker-end="url(#arr)"/>
<circle cx="872" cy="140" r="20" fill="#fff" stroke="#1a1a1a"/><text x="872" y="144" text-anchor="middle" fill="#1a1a1a" font-size="9">verify</text>
<circle cx="872" cy="200" r="20" fill="#fff" stroke="#22c55e" stroke-width="1.5"/><text x="872" y="204" text-anchor="middle" fill="#1a1a1a" font-size="9">verify</text>
<circle cx="872" cy="260" r="20" fill="#fff" stroke="#1a1a1a"/><text x="872" y="264" text-anchor="middle" fill="#1a1a1a" font-size="9">verify</text>
<text x="790" y="310" text-anchor="middle" fill="#888" font-size="10">independents stress-test the work</text>
<text x="790" y="330" text-anchor="middle" fill="#888" font-size="9" font-family="monospace">agent -&gt; parallel(verifiers)</text>
<text x="170" y="404" text-anchor="middle" fill="#1a1a1a" font-size="13" font-weight="700">4. Generate-And-Filter</text>
<circle cx="70" cy="460" r="18" fill="#fff" stroke="#1a1a1a"/><text x="70" y="464" text-anchor="middle" fill="#1a1a1a" font-size="8">gen</text>
<circle cx="70" cy="510" r="18" fill="#fff" stroke="#1a1a1a"/><text x="70" y="514" text-anchor="middle" fill="#1a1a1a" font-size="8">gen</text>
<circle cx="70" cy="560" r="18" fill="#fff" stroke="#1a1a1a"/><text x="70" y="564" text-anchor="middle" fill="#1a1a1a" font-size="8">gen</text>
<line x1="90" y1="460" x2="150" y2="508" stroke="#888" marker-end="url(#arr)"/>
<line x1="90" y1="510" x2="150" y2="510" stroke="#888" marker-end="url(#arr)"/>
<line x1="90" y1="560" x2="150" y2="512" stroke="#888" marker-end="url(#arr)"/>
<rect x="155" y="488" width="72" height="44" rx="4" fill="#fff" stroke="#22c55e"/><text x="191" y="506" text-anchor="middle" fill="#1a1a1a" font-size="10" font-weight="600">filter</text><text x="191" y="520" text-anchor="middle" fill="#888" font-size="8">rubric+dedupe</text>
<line x1="227" y1="500" x2="255" y2="470" stroke="#22c55e" marker-end="url(#arr-g)"/>
<line x1="227" y1="520" x2="255" y2="550" stroke="#888" stroke-dasharray="3,2" marker-end="url(#arr)"/>
<rect x="258" y="454" width="42" height="26" rx="3" fill="#fafafa" stroke="#22c55e"/><text x="279" y="471" text-anchor="middle" fill="#1a1a1a" font-size="9">best</text>
<rect x="258" y="538" width="42" height="26" rx="3" fill="#fafafa" stroke="#d0d0d0"/><text x="279" y="555" text-anchor="middle" fill="#888" font-size="8">drop</text>
<text x="170" y="610" text-anchor="middle" fill="#888" font-size="10">keep what survives the test</text>
<text x="170" y="630" text-anchor="middle" fill="#888" font-size="9" font-family="monospace">parallel(gens) -&gt; filter</text>
<text x="480" y="404" text-anchor="middle" fill="#1a1a1a" font-size="13" font-weight="700">5. Tournament</text>
<circle cx="380" cy="450" r="16" fill="#fff" stroke="#1a1a1a"/><text x="380" y="454" text-anchor="middle" fill="#1a1a1a" font-size="9">a</text>
<circle cx="430" cy="450" r="16" fill="#fff" stroke="#1a1a1a"/><text x="430" y="454" text-anchor="middle" fill="#1a1a1a" font-size="9">b</text>
<circle cx="530" cy="450" r="16" fill="#fff" stroke="#1a1a1a"/><text x="530" y="454" text-anchor="middle" fill="#1a1a1a" font-size="9">c</text>
<circle cx="580" cy="450" r="16" fill="#fff" stroke="#1a1a1a"/><text x="580" y="454" text-anchor="middle" fill="#1a1a1a" font-size="9">d</text>
<line x1="380" y1="466" x2="395" y2="494" stroke="#888" marker-end="url(#arr)"/>
<line x1="430" y1="466" x2="415" y2="494" stroke="#888" marker-end="url(#arr)"/>
<line x1="530" y1="466" x2="545" y2="494" stroke="#888" marker-end="url(#arr)"/>
<line x1="580" y1="466" x2="565" y2="494" stroke="#888" marker-end="url(#arr)"/>
<path d="M405 498 L420 514 L405 530 L390 514 Z" fill="#fff" stroke="#22c55e"/><text x="405" y="518" text-anchor="middle" fill="#1a1a1a" font-size="7">judge</text>
<path d="M555 498 L570 514 L555 530 L540 514 Z" fill="#fff" stroke="#22c55e"/><text x="555" y="518" text-anchor="middle" fill="#1a1a1a" font-size="7">judge</text>
<line x1="405" y1="530" x2="460" y2="558" stroke="#888" marker-end="url(#arr)"/>
<line x1="555" y1="530" x2="500" y2="558" stroke="#888" marker-end="url(#arr)"/>
<path d="M480 562 L498 580 L480 598 L462 580 Z" fill="#fff" stroke="#22c55e"/><text x="480" y="584" text-anchor="middle" fill="#1a1a1a" font-size="8">final</text>
<line x1="480" y1="598" x2="480" y2="616" stroke="#22c55e" marker-end="url(#arr-g)"/>
<rect x="452" y="618" width="56" height="20" rx="3" fill="#fafafa" stroke="#22c55e"/><text x="480" y="632" text-anchor="middle" fill="#1a1a1a" font-size="9">winner</text>
<text x="480" y="660" text-anchor="middle" fill="#888" font-size="9" font-family="monospace">pairwise agent judges</text>
<text x="790" y="404" text-anchor="middle" fill="#1a1a1a" font-size="13" font-weight="700">6. Loop Until Done</text>
<circle cx="790" cy="470" r="28" fill="#fff" stroke="#1a1a1a" stroke-width="1.5"/><text x="790" y="474" text-anchor="middle" fill="#1a1a1a" font-size="11">agent</text>
<line x1="790" y1="498" x2="790" y2="524" stroke="#888" marker-end="url(#arr)"/>
<path d="M790 528 L814 552 L790 576 L766 552 Z" fill="#fff" stroke="#22c55e"/><text x="790" y="548" text-anchor="middle" fill="#1a1a1a" font-size="8">new?</text><text x="790" y="562" text-anchor="middle" fill="#1a1a1a" font-size="8">findings</text>
<line x1="814" y1="560" x2="868" y2="560" stroke="#888" marker-end="url(#arr)"/>
<rect x="870" y="548" width="40" height="24" rx="3" fill="#1a1a1a"/><text x="890" y="564" text-anchor="middle" fill="#fff" font-size="9">done</text>
<path d="M766 548 C720 548 720 470 762 470" fill="none" stroke="#22c55e" stroke-width="1.8" marker-end="url(#arr-g)"/>
<text x="728" y="512" text-anchor="middle" fill="#22c55e" font-size="9" font-weight="600">yes -</text>
<text x="728" y="526" text-anchor="middle" fill="#22c55e" font-size="9" font-weight="600">spawn</text>
<text x="790" y="620" text-anchor="middle" fill="#888" font-size="10">stop when dry rounds appear</text>
<text x="790" y="640" text-anchor="middle" fill="#888" font-size="9" font-family="monospace">while + agent + budget</text>
<text x="480" y="702" text-anchor="middle" fill="#888" font-size="10">Script owns the topology; agents judge inside each step.</text>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

View File

@@ -1,68 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 560" font-family="system-ui, -apple-system, sans-serif" role="img" aria-labelledby="title desc">
<title id="title">Workflow primitives: agent, parallel, pipeline</title>
<desc id="desc">Three kitchen verbs of a workflow script: one helper, a barrier of many helpers, and per-item stages without a barrier.</desc>
<defs>
<marker id="p" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0 0 L10 5 L0 10 z" fill="#888"/></marker>
<marker id="pg" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0 0 L10 5 L0 10 z" fill="#22c55e"/></marker>
</defs>
<rect width="960" height="560" rx="8" fill="#fff"/>
<text x="480" y="28" text-anchor="middle" fill="#1a1a1a" font-size="18" font-weight="700">Three verbs the script speaks</text>
<text x="480" y="48" text-anchor="middle" fill="#888" font-size="12">agent asks a helper; parallel waits for every tray; pipeline lets each cake finish its own stages</text>
<!-- agent -->
<rect x="20" y="70" width="920" height="170" rx="8" fill="#fff" stroke="#d0d0d0" stroke-width="1.5"/>
<text x="40" y="98" fill="#1a1a1a" font-size="15" font-weight="700" font-family="monospace">agent(prompt, opts?)</text>
<text x="40" y="120" fill="#888" font-size="12">One helper. One job. Optional schema makes the answer machine-readable.</text>
<rect x="40" y="140" width="520" height="78" rx="4" fill="#111" />
<text x="56" y="164" fill="#86efac" font-size="12" font-family="monospace">const bugs = await agent("audit auth.ts", {</text>
<text x="56" y="184" fill="#e5e5e5" font-size="12" font-family="monospace"> schema: BugList, label: "audit:auth", phase: "Review"</text>
<text x="56" y="204" fill="#86efac" font-size="12" font-family="monospace">})</text>
<rect x="600" y="140" width="310" height="78" rx="4" fill="#fafafa" stroke="#22c55e"/>
<text x="755" y="170" text-anchor="middle" fill="#1a1a1a" font-size="12">returns text, or validated JSON</text>
<text x="755" y="192" text-anchor="middle" fill="#888" font-size="11">journal records each call in order</text>
<text x="755" y="210" text-anchor="middle" fill="#888" font-size="11">resume replays unchanged prefix</text>
<!-- parallel -->
<rect x="20" y="260" width="450" height="260" rx="8" fill="#fff" stroke="#d0d0d0" stroke-width="1.5"/>
<text x="40" y="288" fill="#1a1a1a" font-size="15" font-weight="700" font-family="monospace">parallel(thunks)</text>
<text x="40" y="310" fill="#888" font-size="12">Fan out. Barrier - wait for all.</text>
<circle cx="100" cy="360" r="18" fill="#fff" stroke="#1a1a1a"/>
<circle cx="170" cy="360" r="18" fill="#fff" stroke="#1a1a1a"/>
<circle cx="240" cy="360" r="18" fill="#fff" stroke="#1a1a1a"/>
<circle cx="310" cy="360" r="18" fill="#fff" stroke="#1a1a1a"/>
<line x1="100" y1="378" x2="100" y2="410" stroke="#888"/>
<line x1="170" y1="378" x2="170" y2="410" stroke="#888"/>
<line x1="240" y1="378" x2="240" y2="410" stroke="#888"/>
<line x1="310" y1="378" x2="310" y2="410" stroke="#888"/>
<line x1="100" y1="410" x2="310" y2="410" stroke="#22c55e" stroke-width="3"/>
<text x="205" y="432" text-anchor="middle" fill="#22c55e" font-size="11" font-weight="600">barrier</text>
<text x="245" y="470" text-anchor="middle" fill="#888" font-size="11" font-family="monospace">failing thunk -&gt; null slot</text>
<text x="245" y="492" text-anchor="middle" fill="#888" font-size="11">use when next step needs EVERY result</text>
<!-- pipeline -->
<rect x="490" y="260" width="450" height="260" rx="8" fill="#fff" stroke="#d0d0d0" stroke-width="1.5"/>
<text x="510" y="288" fill="#1a1a1a" font-size="15" font-weight="700" font-family="monospace">pipeline(items, *stages)</text>
<text x="510" y="310" fill="#888" font-size="12">Each item streams its own stages. No barrier.</text>
<!-- item A -->
<text x="530" y="348" fill="#1a1a1a" font-size="11">A</text>
<rect x="550" y="332" width="70" height="28" rx="3" fill="#fafafa" stroke="#1a1a1a"/>
<text x="585" y="350" text-anchor="middle" fill="#1a1a1a" font-size="10">audit</text>
<line x1="620" y1="346" x2="648" y2="346" stroke="#22c55e" marker-end="url(#pg)"/>
<rect x="650" y="332" width="70" height="28" rx="3" fill="#fafafa" stroke="#22c55e"/>
<text x="685" y="350" text-anchor="middle" fill="#1a1a1a" font-size="10">verify</text>
<line x1="720" y1="346" x2="748" y2="346" stroke="#22c55e" marker-end="url(#pg)"/>
<rect x="750" y="332" width="70" height="28" rx="3" fill="#fff" stroke="#22c55e"/>
<text x="785" y="350" text-anchor="middle" fill="#1a1a1a" font-size="10">done</text>
<!-- item B lagging -->
<text x="530" y="400" fill="#1a1a1a" font-size="11">B</text>
<rect x="550" y="384" width="70" height="28" rx="3" fill="#fafafa" stroke="#1a1a1a"/>
<text x="585" y="402" text-anchor="middle" fill="#1a1a1a" font-size="10">audit</text>
<line x1="620" y1="398" x2="648" y2="398" stroke="#888" marker-end="url(#p)"/>
<rect x="650" y="384" width="70" height="28" rx="3" fill="#fafafa" stroke="#d0d0d0" stroke-dasharray="3,2"/>
<text x="685" y="402" text-anchor="middle" fill="#888" font-size="10">verify</text>
<text x="715" y="450" text-anchor="middle" fill="#888" font-size="11" font-family="monospace">failing stage -&gt; null item</text>
<text x="715" y="472" text-anchor="middle" fill="#888" font-size="11">DEFAULT for multi-stage work</text>
<text x="715" y="494" text-anchor="middle" fill="#888" font-size="11">A can finish while B is still mixing</text>
<text x="480" y="545" text-anchor="middle" fill="#888" font-size="10">Script owns topology. Agents judge inside each call. Intermediate bowls stay in variables + journal.</text>
</svg>

Before

Width:  |  Height:  |  Size: 5.7 KiB