はじめに
前回記事、前々回記事からOpenCodeの解説をしております、Uniuniです。
OpenCodeで趣味開発していますが、AIコーディングの常かコンテキスト長に悩まされています。
たとえば、ちょっとしたコマンドを実行したときに、応答が数千行になる。ということもあります。
一瞬でコンテキストが食い尽くされ、AIが作業内容を忘れて迷子になってしまいます。
記憶が消えていく...悲しいことですね。
今回はOpenCodeのエージェント機能を使って対策してみようと思います。
ということで、実質的にエージェント機能の解説記事です。
OpenCodeでのコンテキスト戦略
前提知識として、OpenCodeでのコンテキスト剪定戦略についてまとめます。
コマンド出力に対する保護機能(ファイル書き出し)はありますが、それでも2000行は結構なトークン消費です。
Compaction(LLM による要約)
OpenCode にはモデルのコンテキストウィンドウ上限に近づいたとき会話を自動的に要約する Auto Compact 機能があります。(デフォルト有効)
Compaction では「compaction」という専用エージェントが起動し、要約プロンプトにより、全メッセージ履歴から「これまで何をしたか、今何をしているか、どのファイルを編集中か、次に何をするか」を要約します。
LLMによる要約なので、要約のクオリティはLLMの能力次第です。
Pruning(軽量なトリミング)
Compaction の前段として、古いツールコール出力を削除してコンテキストサイズを縮小します。これは Compaction より軽量手段で、各会話ターン完了後に自動的に実行されます。(デフォルト有効)
コマンド出力のファイル書き出し
2000行を超えるコマンド出力は外部ファイルに書き出され、保存ファイルの言及とともに出力の一部が応答されます。
ただし、保存済みのツール出力を読みに行く代わりにコマンドを再実行しようとするなどの問題も報告されています。
やりたいこと
今回はコマンド実行によるコンテキスト汚染を防止することを目的に、サブエージェントを作成します。
コマンド実行のたびに、サブエージェントを立ち上げ、サブエージェントによりコマンド実行、内容の要約をおこない、コマンドの出力に関わらず、一定の応答となるようにしてみます。
現状の(問題のある)構成
改良後の構成
エージェントについて
OpenCodeのエージェントには2種類あって、Primary AgentとSub Agentです。
Primary Agentは、Plan,Buildなどの直接対話する主要なアシスタントで、Tabキーで切り替えることができます。
Sub Agentは、プライマリエージェントが特定のタスクのために呼び出すことができるアシスタントです。
Primary AgentとSub Agentともに、自作で定義することができます。(今回はSub Agentですね!)
サブエージェント実装
こちらもopencode.jsonと同様にグローバル、プロジェクト、両方に設定することができます。
今回もグローバルに作成しますので、C:\Users\ユーザ名\.config\opencodeにファイルを配置していきます。
エージェントmdの作成
C:\Users\ユーザ名\.config\opencode\agentsフォルダを作成します。
ここに配置されたmdファイルがそのままエージェントになります。
例えばC:\Users\ユーザ名\.config\opencode\agent\debugger.mdを作成すれば、debuggerエージェントが完成します。ファイル名=エージェント名ですね。
今回、サブエージェントのモデルはローカルモデルを割り当てています。
qwen3-4bだと能力不足で、指定下通りのコマンド実行ができなかったり問題があります。
最低でもgpt-oss-20b程度が必要になりそうです。
---
description: debugger command line tool
mode: subagent
model: local-llm/qwen3-4b-thinking-2507
permission:
read: deny
edit: deny
glob: deny
grep: deny
list: deny
task: deny
skill: deny
lsp: deny
todoread: deny
todowrite: deny
webfetch: deny
websearch: deny
codesearch: deny
external_directory: deny
---
あなたはデバッグ専門のsubagentです。
親エージェントからコマンドとデバッグ詳細レベル(Lv1〜Lv5)が渡されます。
## デバッグ詳細レベル定義
### Lv1 — 結果のみ
- 成功なら `✅ PASS` 、失敗なら `❌ FAIL Count:エラー発生数` の1行のみ返す。
- それ以外は一切出力しない。
### Lv2 — 要点
- 成功: `✅ PASS`
- 失敗: エラー発生数、エラー種別、発生ファイル:行番号を返す。最大3行。
- 複数のエラーの場合、最初の1エラーのみ返し、最大3行を厳守する。
### Lv3 — 標準分析
- 成功: `✅ PASS` + 1行程度で結果を添えても良い。
- 失敗: エラー発生数、エラー種別、発生ファイル:行番号を返す。最大3行。
- エラー出力を4行以内に返す。(4行以上で長い場合は一部要約する)
- 複数のエラーの場合、最初の3エラーのみ返す。
### Lv4 — 詳細分析
- 成功: 実行結果をそのまま返す。
- 失敗: エラー発生数、エラー種別、発生ファイル:行番号を返す。最大3行。
- エラーの推定を1段落(最大5行程度)で返す。
- 複数のエラーの場合、最初の3エラーのみ返す。
- コードの引用は最小限(前後3行以内)。
### Lv5 — 完全分析
- 制限なし。以下を全て含める:
- エラーの完全なスタックトレース解析
- 根本原因の詳細な説明
- 関連ファイル全ての調査(Grep/Readを駆使)
- 複数の修正案(トレードオフ付き)
- 再発防止策の提案
- 影響範囲の分析
## 実行ルール
1. 指示されたコマンドをBashツールで実行する。(指定されたコマンドを改変せずに、そのまま実行すること)
2. 出力が長い場合は、保存されたファイルをReadツール(offset/limit付き)で読む。
絶対にコマンドを再実行しない。
3. 指定されたレベルの範囲を厳守する。Lv1なら本当に1行だけ返す。
4. エラーがない場合(成功時)は、どのレベルでも冗長にならない。
6. 最終回答のみを親エージェントに返す。途中経過は返さない。
7. 成功時は原則として、分析・引用・調査は不要である。行数を守ること。
8. レベル指定がない場合はLv3で実行すること。
## 出力例
🔍 テスト対象: 「ファイル名」
「結果」
今回はdebugger.mdとして、debuggerサブエージェントを作成しました。
要約の詳細度をレベルで指定する感じにしました。
改行コードは必ずLF(\n)にしてください。
\rが混じると正常に読み込まれません。
(...これで2時間は格闘しました)
モデル指定に注意してください。
model: qwen3-4b-thinking-2507では呼び出せません。
必ずmodel: プロバイダ名/モデル名としてください。
つまりopencode.jsonで以下のように設定した場合、
"provider": {
"local-llm": {
"npm": "@ai-sdk/openai-compatible",
"name": "Local LLM",
"options": {
"baseURL": "http://127.0.0.1:1234/v1",
"apiKey": "dummy"
},
"models": {
"qwen3-4b-thinking-2507": {}
}
},
model: local-llm/qwen3-4b-thinking-2507となります。
(これで2時間も消費しました...)
システムプロンプト(AGENTS.md)の作成
システムプロンプトで、debuggerエージェントを使うように誘導しましょう。
グローバルの追加システムプロンプトはC:\Users\ユーザ名\.config\opencode\AGENTS.mdに記述できます。(なんか全部Agentでややこしいですね)
## デバッグ委譲ルール
コマンド実行する場合、コンテキスト浪費を抑えるため、自分で直接デバッグ(コマンド実行)を繰り返してはいけない。
以下の手順に従うこと:
1. コマンド実行の際は、原則としてTaskツールで `debugger` subagentに委譲する。
2. Lv4でも原因が不明な場合、debuggerを使わずに直接実行しても良い。
3. 委譲時は以下のフォーマットで指示する:
Lv{レベル} で以下のコマンドを実行・分析してください:{コマンド}
コンテキスト: {何をしようとしていたかの簡潔な説明}
4. レベルの選び方:
- 成功、失敗のみの判断 → Lv1
- 単純なtypoや構文エラーの可能性 → Lv2
- 原因が不明 → Lv3
- 複雑なバグ、複数ファイルにまたがる問題 → Lv4
- 本番障害レベルの調査 → Lv5(Lv5は通常使用しないこと)
5. debuggerからの回答を受け取ったら、それに基づいて分析を行う。
6. 修正後の確認実行もdebuggerに委譲する。
こんな感じにしてみました。
実行
普通に自然言語で依頼します。
npm run test*****(略)を実行してみましょう。ただしdebuggerに委譲してください

※適当に塗りつぶしています。
※Primary AgentはKimi-k2.5です。
それらしく動きました!!
結果
試しに3000行のエラーを吐くコマンド出力を試しました。
改善前:20kトークンの消費 ❌
改善後:0.5kトークンの消費 ✅
大幅に改善できました!!
しかし実際のコーディング内でdebuggerを呼ぶかはAIの気分次第...。プロンプトをもう少し改善したほうが良さそうです。
また、サブエージェントは常に新規セッションで開始しますので、毎回Tool Callなどを含めた全システムプロンプト約10kトークンを送ります。
APIのトークン消費は効率的とは言えないので、subagentのみローカルLLMにするというのも1つの方法かもしれません。
今回の方法はあくまでPrimary agentのトークン汚染を保護するもので、全体のAPIのトークン消費はむしろ上がります。
subagentのときは関係ないTool Callのシステムプロンプトを省略...などできれば良いのですが、いまのところそのような機能はないようです。提案には挙がっているようなので今後のOpenCodeに期待ですね!
おわりに
OpenCode解説記事が少ないですね。
ライセンスの都合でOpenCodeしか選択できない。という方もいるとお思いましたが、おもいのほか少数派でした。
ローカルLLM+OpenCodeというのはかなり有力な選択肢だと思います。
DGX Spark相当(メモリ128GB)があれば、MiniMax M2.5などで、十分に実用的なAIコーディングもできそうです。
気が向いたら比較とかやってみようと思います!
ということでOpenCodeのエージェントについての解説でした!
いかがでしたでしょうか?良い!と思った方はいいねしてフィードバック頂けると励みになります!