117 lines
7.0 KiB
Markdown
117 lines
7.0 KiB
Markdown
# Method::Notify: システム起点のコンテキスト注入と自動ターン開始
|
||
|
||
## 背景
|
||
|
||
現状の Pod の実行サイクルは `Method::Run { input }` が唯一のターン開始手段であり、これは人間(または外部クライアント)が明示的にテキストを送ることを前提としている。
|
||
|
||
Pod オーケストレーション(`tickets/pod-orchestration.md`)では、子 Pod が親 Pod にコールバックで通知を送り、親 Pod が**人間の入力を待たずに**その通知を処理して次のアクションを起こす必要がある。現状のアーキテクチャにはこの経路が無い。
|
||
|
||
また、RUNNING 中の Pod に対しても、リクエストの合間に情報を注入して LLM に認知させたいケースがある(子 Pod からの非同期通知など)。現状は RUNNING 中にコンテキストを追加する手段が無い。
|
||
|
||
## ゴール
|
||
|
||
`Method::Notify` を新設し、Pod の状態(IDLE / RUNNING)に応じて適切にコンテキストへの注入とターン制御を行う。
|
||
|
||
## 仕様
|
||
|
||
### `Method::Notify { source: String, message: String }`
|
||
|
||
protocol に追加する新しい Method。`Run` とは異なり、ユーザーメッセージではなく**システム通知**としてコンテキストに注入される。
|
||
|
||
### Pod が IDLE のとき
|
||
|
||
1. 通知メッセージを system message としてコンテキストに注入
|
||
2. **自動でターンを開始**する(人間の入力を待たない)
|
||
3. LLM は通知を見て次のアクションを判断する
|
||
|
||
### Pod が RUNNING のとき
|
||
|
||
1. 通知メッセージを**次の LLM リクエストの直前**に注入する(tool call の応答を送った後、次のリクエストを組み立てる前)
|
||
2. ターンは中断しない。LLM は現在のタスクを続行しつつ、次のレスポンスで通知を認知する
|
||
3. LLM は今やっていることを優先し、切りの良いタイミングで通知に対処するかを自分で判断する
|
||
|
||
### 注入されるメッセージのフォーマット
|
||
|
||
通知は素のテキストではなく、以下の構造で注入される:
|
||
|
||
```
|
||
[Notification from {source}]
|
||
{message}
|
||
|
||
This is a notification, not a blocking request. If you are in the middle of a task, continue your current work and address this at a natural stopping point.
|
||
```
|
||
|
||
- `[Notification]` prefix で LLM にこれが通知であることを明示
|
||
- 「ブロッカーではないので直ちに対処しなくてよい」という指示を付与
|
||
- LLM が通知を見て即座にタスクを放棄する(指示追従性の暴走)を防ぐ
|
||
|
||
### 複数通知のバッファリング
|
||
|
||
- RUNNING 中に複数の `Notify` が到着した場合、バッファに溜めて次の LLM リクエスト直前にまとめて注入する
|
||
- 個別の `[Notification]` ブロックとして並べる(1つにマージしない)
|
||
- IDLE 中に複数到着した場合、1つの system message にまとめて注入し、ターンを1回だけ開始する
|
||
|
||
## 実装に必要な変更
|
||
|
||
### protocol crate
|
||
|
||
- `Method::Notify { source: String, message: String }` を `Method` enum に追加
|
||
- 対応する `Event` の追加が必要かは設計時に判断
|
||
|
||
### Worker
|
||
|
||
- RUNNING 中に外部からメッセージを注入する仕組みが必要
|
||
- 現状の Worker は turn 実行中にコンテキストの追加手段を持たない
|
||
- tool call → tool result → **notification 注入** → 次の LLM リクエスト、というフローを追加
|
||
- 注入ポイントは `execute_tools` 完了後、次の LLM リクエスト組み立て前
|
||
|
||
### Controller
|
||
|
||
- `Method::Notify` のハンドリングを追加
|
||
- IDLE 時: 通知を注入 → 内部的に `run()` を開始(`Method::Run` と似た経路だがメッセージ種別が異なる)
|
||
- RUNNING 時: Worker の notification buffer に push
|
||
|
||
### Pod
|
||
|
||
- notification buffer を保持するフィールドを追加
|
||
- `ensure_system_prompt_materialized` 的な「ターン開始前に notification を flush する」フックが要るかもしれない
|
||
|
||
## `Method::Run` との対比
|
||
|
||
| | `Method::Run` | `Method::Notify` |
|
||
|---|---|---|
|
||
| 対象状態 | IDLE のみ(RUNNING 中は AlreadyRunning エラー) | IDLE でも RUNNING でも受け付ける |
|
||
| コンテキスト上の見え方 | user message | system message(`[Notification]` prefix 付き) |
|
||
| ターン制御 | 新ターンを開始 | IDLE: 自動でターン開始。RUNNING: 現ターンに注入 |
|
||
| LLM の期待挙動 | 指示に従って即座に行動 | 現タスク優先、切りの良いタイミングで対処を判断 |
|
||
| 送信元 | 人間 / クライアント | システム / 子 Pod のコールバック / Hook |
|
||
|
||
## 設計で決めること
|
||
|
||
- **notification の注入はどの message type で行うか**: 既存の `Role::User` / `Role::Assistant` とは別の `Role::System` (mid-conversation) を追加するか、`Role::User` に `[Notification]` prefix を付けて実質的に区別するか
|
||
- **IDLE 時の自動ターン開始と人間の `Run` の競合**: 通知が到着して自動ターンが始まった直後に人間が `Run` を送った場合の挙動
|
||
- **notification buffer のサイズ上限**: RUNNING が長時間の場合にバッファが無制限に溜まるリスク
|
||
- **通知メッセージの prefix / suffix テンプレートの置き場**: ハードコードか、instruction 側でカスタマイズ可能にするか
|
||
- **Event の対応**: `Event::NotificationInjected` のような確認イベントを返すか
|
||
|
||
## 完了条件
|
||
|
||
- `Method::Notify` が protocol に追加され、Controller が IDLE / RUNNING で適切にハンドリングする
|
||
- IDLE 時: 通知が system message として注入され、自動でターンが開始される
|
||
- RUNNING 時: 通知が次の LLM リクエスト直前に注入され、LLM が認知できる
|
||
- 複数通知のバッファリングが動作する(RUNNING 中に溜まった通知がまとめて注入される)
|
||
- `[Notification]` prefix と non-blocking 指示が付与される
|
||
- 単体テストで IDLE / RUNNING 両パスが検証される
|
||
|
||
## 他チケットとの関係
|
||
|
||
- **tickets/pod-orchestration.md**: 本チケットの主要消費者。子 Pod の `Notify` ツール → 親の callback → 親の `Method::Notify` というフローでオーケストレーションの非同期通知が成立する
|
||
- **tickets/protocol-design.md**: protocol への Method 追加。既存の Method 設計パターン(Run / Resume / Cancel / Shutdown)と整合させる
|
||
- **tickets/compact-improvements.md**: notification がコンテキストに蓄積した場合の compaction 挙動は別途検討
|
||
|
||
## 範囲外
|
||
|
||
- **通知の routing / addressing**: 誰が誰に通知を送るかはオーケストレーション側の責務。本チケットは「Pod が Notify を受けたときの挙動」だけを扱う
|
||
- **通知の優先度 / フィルタリング**: 全通知を等しく注入する。重要度に応じた選別は LLM に任せる
|
||
- **通知の永続化**: 通知は session-store に永続化しない。コンテキスト上の message としてのみ存在する
|