72 lines
5.9 KiB
Markdown
72 lines
5.9 KiB
Markdown
# Movement 制御フローツールと park シグナル
|
||
|
||
エンジン内部リファレンス。「ツールを呼ぶと movement が**待機/終了状態に遷移**するが、その遷移先は**ピース毎の `rules` に書かなくてよい**」という仕組みのまとめ。BrowseWeb のログイン待ち・RequestTool の承認待ち・(提案中の)WaitSubTask が同じ骨格を共有する。今後この型を流用する時の下敷き。
|
||
|
||
## 要点
|
||
|
||
movement の遷移には **2 系統**ある。
|
||
|
||
| 系統 | 遷移先の決まり方 | LLM への提示 | 例 |
|
||
|------|------------------|--------------|-----|
|
||
| **rules ベース** | ピースの `rules[].next` を `buildTransitionTool` が enum 化 | `transition` ツールの選択肢として提示 | 別 movement への中間遷移 |
|
||
| **sentinel `next`(park/terminal)** | ツールまたは engine が `MovementResult.next` に**特別な値**を直接セット | 専用ツール(`complete` 等)として提示。`rules` 不要 | 終了・各種待機 |
|
||
|
||
後者が今回の主題。**ツールが「作業をする」のではなく「movement を畳む制御シグナルを出す」**。`complete` がまさにこれで、`BrowseWeb`(ログイン待ち)・`RequestTool`(承認待ち)も同じ。`rules` に依存しないので、`rules: []` の単一 movement ピース(`chat` 等)でも一律に効く。
|
||
|
||
## 仕組みの流れ
|
||
|
||
```
|
||
agent-loop.ts
|
||
LLM が制御フローツールを呼ぶ
|
||
└─ finishMovement({ next: '<SENTINEL>', resumeMovement?, waitReason? }) を返す
|
||
│ MovementResult.next に sentinel を載せる
|
||
▼
|
||
piece-runner.ts mapMovementResult(result, ...)
|
||
└─ next の値で分岐し PieceRunResult を返す
|
||
├─ 終了系 → kind:'done' / status: completed|aborted|cancelled
|
||
└─ 待機系 → kind:'done' / status: waiting_* + resumeMovement(+waitReason)
|
||
▼
|
||
worker.ts
|
||
└─ waiting_* のジョブを停車。条件成立で resumeMovement から再開
|
||
(waiting_subtasks=子全完了 / waiting_human=ユーザー回答・ログイン・承認)
|
||
```
|
||
|
||
ポイントは、**待機系も「ジョブを停車してワーカーを解放」する**こと。ツール内で同期ブロックして待つのではない(後述の鉄則)。
|
||
|
||
## sentinel カタログ(`mapMovementResult` の分岐・origin/main 時点)
|
||
|
||
| `next` | 生成元 | 結果 status | resumeMovement | waitReason | 種別 |
|
||
|--------|--------|-------------|----------------|-----------|------|
|
||
| `COMPLETE` | `complete` ツール | `completed` | — | — | 終了 |
|
||
| `ABORT`(`cancelled` 含む) | キャンセル経路 | `cancelled` | — | — | 終了 |
|
||
| `ABORT` | `complete`/各種ガード(`text_only_limit`・`max_iterations` 等) | `aborted` | — | — | 終了 |
|
||
| `ASK` | `complete({status:'needs_user_input'})` | `waiting_human`(上限超で `aborted`) | 現在の movement | — | 待機 |
|
||
| `WAIT_SUBTASKS` | `transition`(rules 経由)/**WaitSubTask ツール(提案)** | `waiting_subtasks` | `default_next`(ツール版は現在の movement に変更予定) | — | 待機 |
|
||
| `WAITING_HUMAN_BROWSER` | `BrowseWeb`(ログイン要求時) | `waiting_human` | 現在の movement | `browser_login` | 待機 |
|
||
| `WAITING_HUMAN_TOOL_REQUEST` | `RequestTool` | `waiting_human` | 現在の movement | `tool_request` | 待機 |
|
||
| `null` | 異常(ツール未決着) | `error` | — | — | 異常 |
|
||
|
||
> `WAIT_SUBTASKS` だけは現状 `rules[].next` にも書ける(rules ベース経由)。ツール版(WaitSubTask)を足すと、**同じ sentinel に「ルール不要の入口」**が増える。下流の `mapMovementResult` 分岐は共有。
|
||
|
||
## 新しい park ツールを足すレシピ
|
||
|
||
1. **ツール定義**を該当モジュール(例 `orchestration.ts`)の `TOOL_DEFS` に追加。
|
||
2. **agent-loop で制御フローツールとして識別**し、`finishMovement({ next: '<新SENTINEL>', resumeMovement, waitReason })` を返す(`WAITING_HUMAN_BROWSER` の実装が雛形)。
|
||
3. **`mapMovementResult` に分岐を追加**(piece-runner.ts)。終了なら `status: 'aborted'|'completed'`、待機なら `status: 'waiting_*'` + `resumeMovement`(+`waitReason`)。
|
||
4. **worker の再開条件**を実装/再利用。既存の `waiting_human` / `waiting_subtasks` のどちらかに寄せられるなら新 status は不要。
|
||
5. **型**(`MovementResult.next` のユニオン、`waitReason`)を更新。
|
||
|
||
既存の待機 status(`waiting_human` / `waiting_subtasks`)に相乗りできるなら、3〜4 は分岐追加だけで済むことが多い。
|
||
|
||
## 鉄則・gotcha
|
||
|
||
- **ツール内で同期ブロックして待たない。** 待機は必ず「停車=ワーカー解放」で表現する。in-tool で `await` し続けると親ワーカーを占有し、最悪ワーカー枯渇でデッドロックする(`WAIT_SUBTASKS` が遷移=停車である理由)。
|
||
- **resume 先を意識する。** `default_next` が `COMPLETE` のピース(単一 movement)で再開させると終了に飛ぶ。多くの待機ツールは**現在の movement に再入**させて、再開後に結果を読んで `complete` させる。
|
||
- **terminal と park を混同しない。** `COMPLETE`/`ABORT` はジョブを終わらせる(再開なし)。`WAITING_*`/`WAIT_SUBTASKS` は停車→再開。`resumeMovement` の有無が分かれ目。
|
||
- **sentinel は `rules` の enum に出さない。** これらは engine-internal。`rules[].next` に書けるのは別 movement 名と `WAIT_SUBTASKS` のみ(`loadPiece`/lint が `COMPLETE`/`ABORT`/`ASK` を reject する)。
|
||
|
||
## 関連
|
||
|
||
- 設計: `docs/design/2026-06-26-subtask-wait-and-safety.html`(WaitSubTask ツール=この型の新規適用例)
|
||
- 実装: `src/engine/agent-loop.ts`(`finishMovement` / 制御フローツール識別)、`src/engine/piece-runner.ts`(`mapMovementResult`)、`src/worker.ts`(待機ジョブの停車・再開)
|