yoi/tickets/tool-output-limit.md

64 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ツール実行結果のサイズ上限
## 背景
Pod のセッションで、Glob が `pattern:"*"` でプロジェクト全体を走査し、
約 125KB / 推定 70k トークン超の tool_result を返した結果、次ターンのリクエストが
組織レートリミット30k input tokens/分)を単発で超過して永久に 429 で詰む事故が発生した。
一度肥大化した履歴は prune/compact が走る前に再送され続け、待っても抜けられない。
根本原因はツールが「呼ばれた通りの結果を素直に全部返す」こと。ツール自身の件数上限
(例: `Glob` の 1000 件)はバイト/トークン単位の上限ではないため機能しない。
ツール実行結果のサイズを LLM に投げる前に強制的にキャップし、LLM に
「検索範囲を絞れ」と促す必要がある。
## 要件
- **単一チョークポイントで全ツールに効く**: 個別ツールの実装を信用しない。
Tool 実行境界llm-worker の Tool runner`ToolOutput.content` をトークン計測し、
上限を超えていたら切り詰めてから履歴に積む。
- **マニフェストで設定可能**: デフォルトは 5000 トークン30k/分レートリミットに
対して余裕を持った値)。プロジェクトごと・ツールごとに上書き可能。
- **切り詰め後は LLM が検知できる**: `summary` 又は `content` 末尾に
`truncated: N tokens dropped, refine your query` 形式の追記を入れ、
LLM が自発的に絞り込みを試みるヒントにする。`ToolError` にはしない
(エラーにすると LLM がリトライループに入りやすい)。
- **計測は既存の `token-counter` クレートを使う**。文字数やバイト数で近似しない。
## マニフェスト
```toml
[worker.tool_output]
# 全ツール共通の既定上限。省略時 5000。
default_max_tokens = 5000
# ツールごとの上書き。ツール名は登録名("Glob", "Read", ...)。
[worker.tool_output.per_tool]
Read = 8000 # Read は大きいファイルを意図的に返すので少し緩める
Grep = 3000
```
- `[worker.tool_output]` セクション自体は省略可能。省略時はデフォルト 5000 が全ツールに適用。
- `per_tool` も省略可能。
- 未知のツール名がマップに含まれていても manifest エラーにはしない(ログ警告のみ)。
## 実装方針(実装順序)
1. `token-counter` を llm-worker の依存に追加まだならし、Tool 実行境界の
`ToolOutput` を計測する薄いラッパーを導入
2. 超過時の切り詰めロジックcontent を二分探索などでトークン数ぎりぎりまで詰め、
末尾に注記を追記)
3. `manifest::WorkerManifest``tool_output: Option<ToolOutputLimits>` を追加、
llm-worker の `Worker` 生成時に渡す
4. 各ツール単体には本チケットでは手を入れない。上限を踏んだツールに対して
後続の改善Glob が `git_ignore` を尊重する等)は別チケットで扱う
## 非ゴール
- **ツール固有の賢い縮退**Glob が件数で、Read が行範囲で、など)は扱わない。
まず一律上限で事故を止め、各ツールの自主制限は必要に応じて別チケットで追加する。
- **prompt caching の導入**や compaction 側の改善は扱わない。
本チケットは「1 回のツール結果が履歴に載る前にキャップする」ことだけに集中する。
- **入力側(ツール引数)のサイズ制限**は扱わない。