mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-09-21 21:03:38 +08:00
docs(s16): ideal March-feel chapter + maintainer readability standard (v19)
This commit is contained in:
@@ -1,114 +1,75 @@
|
||||
# s16: Workflow Runtime — レシピをコードに書く
|
||||
# s16: Workflow Runtime — オーケストレーションをコードに書く
|
||||
|
||||
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
|
||||
|
||||
s01 → ... → s14 → [s15](../s15_integrated_harness/) → `s16` → [s17](../s17_goal_loop/)
|
||||
[s15](../s15_integrated_harness/) → `s16` → [s17](../s17_goal_loop/)
|
||||
|
||||
> Workflow = コードに書いたオーケストレーション。トポロジはスクリプト、一歩の判断はモデル。
|
||||
> *計画をチャットの中だけに置かない。* 順番はスクリプトが持ち、一歩ごとの判断はモデルが持つ。
|
||||
>
|
||||
> **Harness 層**: オーケストレーション — 単一 agent ループの上で多 agent スクリプトを回す。
|
||||
>
|
||||
> モデルを信じ、harness を設計する。Workflow はその一言を一段上げる。
|
||||
|
||||
---
|
||||
> **Harness 層**: オーケストレーション — 単一 agent ループの上で、マルチ agent スクリプトを走らせる。
|
||||
|
||||
## 問題
|
||||
|
||||
長い仕事では計画と実行が同じ chat に同居する:途中で完了宣言、自分の宿題を甘く採点、圧縮のあと静かな制約が消える。並列・安定した結果形・再開——柔らかい会話メモリでは支えきれない。
|
||||
あなたはすでに、ひとつのループの中でモデルにファイルを読ませ、コードを直し、エラーを見させることができます。ところが仕事によっては、**順番が最初から分かっている**ものがあります。次元ごとにレビューし、次に意地悪な検証、最後にまとめる——という具合です。その順番をチャットの記憶にだけ預けていると、モデルは途中で「完了」と言い、自分の宿題を甘く採点し、圧縮を何度か経ると「X を触るな」さえ消えます。
|
||||
|
||||
十秒おきにシェフへ SMS を送るような催促。**Workflow** は厨房がそのまま従えるレシピだ。
|
||||
柔らかい会話は、並列も、結果の形の安定も、落ちてからの再開も支えきれません。もっとおしゃべりの上手なモデルが欲しいのではありません。**書き下ろされたオーケストレーション**が欲しいのです。
|
||||
|
||||
## アイデア
|
||||
|
||||
ヘルパー(サブ agent)は考える。**スクリプト**がループ・分散・マージを握る。中間結果は変数と journal に置き、会話には入れない。
|
||||
|
||||
**オーケストレーションを「知性」から「構造」へ移す。**
|
||||
## 解決策
|
||||
|
||||
```text
|
||||
messages[] ──► Workflow(...) ──► tool_result
|
||||
│
|
||||
▼
|
||||
スクリプトが握る: agent / parallel / pipeline
|
||||
│
|
||||
▼
|
||||
変数 + journal
|
||||
あなたの会話 ──► Workflow(...) ──► 結果が一条で戻る
|
||||
│
|
||||
▼
|
||||
スクリプト: agent / pipeline / parallel
|
||||
│
|
||||
▼
|
||||
変数 + journal(半成品はここに。スレに詰め込まない)
|
||||
```
|
||||
|
||||
`Workflow` ツール呼び出しひとつで開始;レシピが終わると結果がひとつ返る。
|
||||
ヘルパー(サブ agent)は相変わらず考えます。**スクリプト**がループ・分配・マージを持ちます。中間結果は変数と journal に置き、親の対話には入れません。
|
||||
|
||||
<details>
|
||||
<summary>Runtime 概要図</summary>
|
||||
一言でいうと:**オーケストレーションを「知性」から「構造」へ移す。**
|
||||
|
||||

|
||||

|
||||
|
||||
</details>
|
||||
*左:汎用の固定パイプライン。右:このタスク向けに裁断したオーケストレーション。*
|
||||
|
||||
## ふたつの入口
|
||||
Claude Code には二つの扉があります。**動的**——モデルがこのタスク用に JS を書く(`script` / `scriptPath`)。**保存済み**——良いスクリプトを `name` + `args` で再実行。外側には SDK で先に書き切る静的オーケストレーションもあります。本章は **Python の教材用 runtime**(JS VM なし)です。考えは揃え、デモは「保存済み」の扉を使います。製品ではモデルはスクリプトを出せます——ここでは JS を走らせないだけです。
|
||||
|
||||
- **Dynamic**: モデルが*この*タスク向けに JS オーケストレーションを書く(`script` / `scriptPath`)。
|
||||
- **Saved**: 良いスクリプトを `.claude/workflows/` に置き、`name` + `args` で再呼び出し。
|
||||
- **Static**(外のいとこ): SDK / `claude -p` で事前に書く——だいたい汎用寄り。
|
||||
## 仕組み
|
||||
|
||||

|
||||
|
||||
*左: 固定パイプライン → 汎用レポート。右: あなたのコード向けに裁断 → 具体的な提案。*
|
||||
|
||||
本章は **Python のティーチング runtime**(JS VM なし)。概念は Claude Code に揃え、デモは Saved 入口。製品ではモデルが実行可能スクリプトを出せる——ここでは JS インタプリタを埋め込まないだけ。
|
||||
|
||||
```python
|
||||
# teaching sketch — 完全な schema ではない
|
||||
Workflow({ "name": "review-changes", "args": { "changes": "..." } })
|
||||
# Claude Code はさらに: script | scriptPath | resumeFromRunId
|
||||
```
|
||||
|
||||
## 三つの動詞
|
||||
**1. 三つの動詞**
|
||||
|
||||
```text
|
||||
agent ヘルパー一人、仕事ひとつ(schema で JSON 検証可)
|
||||
pipeline item ごとに段階を進む(既定 — 障壁なし)
|
||||
parallel 全部揃ってから次へ(障壁 — 控えめに)
|
||||
agent 一人のヘルパー、一件の仕事(schema で次に渡せる JSON も可)
|
||||
pipeline 各 item が自分の段階を進む(既定。同期しない)
|
||||
parallel 全部揃ってから先へ(バリア。多用しない)
|
||||
```
|
||||
|
||||
失敗しても艦隊は続く: `parallel` はそのスロットが `null`;`pipeline` は**その item** と後段を落とす。マージ前にフィルタ。
|
||||
失敗時:`parallel` のその枠は `null`。`pipeline` はその item を捨てます。艦隊は丸ごと沈みません。マージ前にフィルタしてください。
|
||||
|
||||
再開: journal は呼び出し順に記録;**最長の未変更プレフィックス**を再生し、最初の変更以降は実走。本物の JS runtime は `Date.now()` / `Math.random()` を禁じる。このデモは完全サンドボックスしない——それでも決定的に書く。
|
||||
**2. 再開はノートで。チャット記憶ではない**
|
||||
|
||||
journal は `agent()` の**呼び出し順**で記帳します。再開は最長の未変更プレフィックスを再生し、最初の変更から先は全部ライブです。本番の JS runtime は `Date.now()` / `Math.random()` を禁じます——ノートがずれないように。教材スクリプトも決定的に書いてください。
|
||||
|
||||
```text
|
||||
journal [A] [B] [C] [D]
|
||||
resume hit hit ✂ live
|
||||
再開 命中 命中 ✂ ライブ
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>公式プリミティブ・カード + 静かな動詞</summary>
|
||||
**3. サンプル一つ:Fanout + Adversarial**
|
||||
|
||||

|
||||
|
||||
*`agent`;`parallel`(障壁)vs `pipeline`(ストリーミング段階)。Claude Code には `model` / `isolation` / `agentType` もある;ティーチング面は小さめ。*
|
||||
|
||||
静かな動詞: `phase`、`log`、ネスト一段 `workflow`、`args`、`budget`。
|
||||
|
||||
</details>
|
||||
|
||||
## ふたつの形 + ひとつの sample
|
||||
|
||||
まずふたつ(六パターン全体は下の折りたたみ):
|
||||
`review-changes` は「一つのパターン」ではありません。**Fanout** の中に **Adversarial** が入ります。次元ごとに `pipeline(audit, verify)`、検証で `parallel` に意地悪させ、残った finding だけ残します。
|
||||
|
||||
```text
|
||||
Fanout task ──► ● ● ● ● ══barrier══► synthesize
|
||||
Adversarial worker ──► verifier×N → 残るものだけ残す
|
||||
```
|
||||
|
||||
sample `review-changes` = **Fanout** の中に **Adversarial**: 次元ごとに `pipeline(audit, verify)`、`verify` 内で `parallel` 検証、`isReal` だけ残す。
|
||||
|
||||
```text
|
||||
correctness ── audit ── verify ──┐
|
||||
security ── audit ── verify ──┤── confirmed
|
||||
performance ── audit ── verify ──┤
|
||||
style ── audit ── verify ──┘
|
||||
correctness ── 監査 ── 検証 ──┐
|
||||
security ── 監査 ── 検証 ──┤── confirmed
|
||||
performance ── 監査 ── 検証 ──┤
|
||||
style ── 監査 ── 検証 ──┘
|
||||
```
|
||||
|
||||
```python
|
||||
# code.py から(抜粋)
|
||||
# code.py 抜粋 — 形だけ見ればよい
|
||||
async def sample_workflow(ctx, args):
|
||||
ctx.phase("Review")
|
||||
results = await ctx.pipeline(DIMENSIONS, audit, verify)
|
||||
@@ -116,71 +77,63 @@ async def sample_workflow(ctx, args):
|
||||
return {"confirmed": confirmed}
|
||||
```
|
||||
|
||||
艦隊は早止めできず、作者は審判にならず、トポロジは chat の毎ターンで書き換わらない。
|
||||
艦隊は早逃げできず、著者は自分の審判にならず、トポロジも疲れたチャットのたびに書き換わりません。
|
||||
|
||||
<details>
|
||||
<summary>六パターン格子 + プリミティブ対応</summary>
|
||||
<summary>よくある六つの形(パターン庫)</summary>
|
||||
|
||||

|
||||

|
||||
|
||||
| パターン | プリミティブ速写 | 使わないとき |
|
||||
|----------|------------------|--------------|
|
||||
| Classify-And-Act | `agent` → 分岐 → `agent` | 全部同じ扱いでよい |
|
||||
| Fanout-And-Synthesize | `pipeline` / `parallel` → マージ | 一回で収まる |
|
||||
| Adversarial Verification | 生成 → `parallel(verify)` → フィルタ | 間違っても安い |
|
||||
| Generate-And-Filter | `parallel(gens)` → フィルタ | 答え空間がもともと狭い |
|
||||
| Tournament | 一対一の審判 `agent` | 明確な尺度で一発選定可 |
|
||||
| Loop Until Done | `while` + 停止 + `budget` | 仕事量が既知 |
|
||||
| パターン | 人の言葉 | 原語のスケッチ |
|
||||
|------|------|----------|
|
||||
| Classify-And-Act | 仕分けしてから適任へ | `agent` → 分岐 → `agent` |
|
||||
| Fanout-And-Synthesize | 分けてやり、またまとめる | `pipeline` / `parallel` → 統合 |
|
||||
| Adversarial Verification | 狐に鶏小屋を採点させない | 産出 → `parallel(verify)` → フィルタ |
|
||||
| Generate-And-Filter | まず多く作り、それから篩 | `parallel(gens)` → フィルタ |
|
||||
| Tournament | 一対一で優勝を決める | 審判 `agent` |
|
||||
| Loop Until Done | 「まだ新しい?」なら続ける | `while` + 停止 + `budget` |
|
||||
|
||||
`review-changes` ≈ Fanout + Adversarial。調査系はよく 分配 → フィルタ → 検証 → 統合 と積みます。
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>動的 / 保存済み / 静的と公式原語図</summary>
|
||||
|
||||
```python
|
||||
# teaching sketch
|
||||
kind = await ctx.agent("このチケットを分類", schema=KIND)
|
||||
if kind["type"] == "billing":
|
||||
return await ctx.agent("請求を処理…")
|
||||
# 教材スケッチ
|
||||
Workflow({ "name": "review-changes", "args": { "changes": "..." } })
|
||||
# Claude Code はさらに: script | scriptPath | resumeFromRunId
|
||||
```
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>信頼できない入力: quarantine</summary>
|
||||
<summary>信頼できない入力:読み書きを隔離</summary>
|
||||
|
||||
チケットを*読む* agent が PR を開く鍵まで持つべきではない。reader は読み取りのみ → 構造化サマリ;trusted actor はサマリだけ見て動く。
|
||||
チケットを読む agent が、同時に PR を開ける鍵を持ってはいけません。読み手は読むだけ → 要約。信頼側は要約だけ見て動きます。
|
||||
|
||||
```text
|
||||
backlog(非信頼)→ [quarantine: readers → 重複除去 → summary] → [trusted: actor]
|
||||
バックログ → [隔離: 読 / 重複除去 / 要約] → [信頼: 実行]
|
||||
```
|
||||
|
||||

|
||||
|
||||
*高権限ツールは trusted 側。バックログが眠らないなら `/loop` と組む。*
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>s15 への掛け方</summary>
|
||||
|
||||
s15 がホストループのまま;s16 は `Workflow` ツールを足すだけ。製品ではバックグラウンド可;ティーチング CLI は前景の `demo` / `resume` で段階とキャッシュを見せる。
|
||||
|
||||
</details>
|
||||
|
||||
## 隣人と、使わないとき
|
||||
|
||||
計画を握るのは誰か。s06 一回委譲、s13 メール箱の仲間、s15 単一ループ、**s16 スクリプト + journal**、s17 は「全体ゴールは終わったか」。
|
||||
|
||||
普通のコーディングなら s15 一回、または正直な s06 で十分なことが多い。Workflow は token と調整コスト——構造が単一コンテキストより長生きすべきときだけ。
|
||||
計画を握るのは誰か。s06 は一回きりの委譲、s13 はメール箱つきの仲間、s15 は単一ループのチャット、**s16 はスクリプト + journal**、s17 は入り口で「全体は終わったか」と聞きます。普通の数ファイルの修正なら s15 か一つの s06 で足りることが多い。Workflow は token と調整のコストが要ります——**構造が一度の会話より長生きしなければならない**ときだけ手を伸ばしてください。
|
||||
|
||||
## 試してみる
|
||||
|
||||
```bash
|
||||
python s16_workflow_runtime/code.py # s15 ホスト + Workflow(本番 API)
|
||||
python s16_workflow_runtime/code.py demo # 固定データ;段階を見る
|
||||
python s16_workflow_runtime/code.py resume # 同じ runId;キャッシュ命中を期待
|
||||
python s16_workflow_runtime/code.py demo
|
||||
python s16_workflow_runtime/code.py resume
|
||||
```
|
||||
|
||||
完全再開では `agents=0 tokens=0` になるはず。
|
||||
一回目は Review → Verify を見てください。同じ run の二回目は `cached` がほとんど(理想は `agents=0 tokens=0`)。完全なホストに載せるなら引数なしで `code.py` を。
|
||||
|
||||
## 次へ
|
||||
s15 はあいかわらずそのループです。ここに増えるのは `Workflow` ツールだけ。[s17](../s17_goal_loop/) は別の問いをします。もう止まっていい?
|
||||
|
||||
s16 はバッチの回し方。[s17 Goal Loop](../s17_goal_loop/) は聞く:止めるか、もう一周か。
|
||||
|
||||
<!-- translation-sync: zh@v18, en@v18, ja@v18 -->
|
||||
<!-- translation-sync: zh@v19, en@v19, ja@v19 -->
|
||||
|
||||
Reference in New Issue
Block a user