対象読者と前提
- Claude Code のようなエージェント型ツールを使っていて、内部でエージェント・スキル・フックがどう連携しているのか気になる方
- ローカル LLM(Ollama)でマルチエージェントを試してみたい方
- 動作確認環境: macOS / Node.js v24.14.0 / Ollama / TypeScript 5.8
なぜ作ったか
普段 Claude Code を使っていて、サブエージェントやスキル、フックがどういう順序で呼ばれ、どこで判断が分岐しているのかが気になりました。公式ドキュメントを読めば概念は把握できますが、実装の詳細までは分かりません。一番早く理解する方法は、同じような仕組みを自分で組んでみることだと考え、将棋の駒をモチーフにしたローカル LLM 専用のマルチエージェント CLI 「Jin」を作りました。
Jin は Claude Code の互換実装でも公式プロジェクトでもありません。2026年7月時点の公開ドキュメントを比較対象に、エージェント・スキル・フック・プロジェクトコンテキストといった概念を参考にして、将棋盤のメタファーで独自に再構成したものです。MCP 連携や Web 検索、Git 操作、詳細な権限制御などは実装していません。
npm で公開しています。
npm install -g @tanishi-z/jin
- パッケージ:
@tanishi-z/jin(npm view @tanishi-z/jin versionで0.1.0を確認済み、2026-07-12 公開) - リポジトリ: github.com/Tanishi-z/Jin
- 紹介サイト: tanishi-z.github.io/Jin
- 動作要件: Node.js 24.0.0 以上、Ollama がインストール済みであること
- ソース規模: TypeScript 約 10,600 行、依存パッケージは
@clack/promptsとchalkのみ
Jin とは
自然言語の雑な要求を受け取り、将棋の駒になぞらえた複数の専門エージェントが協調して「仕様・体験・実装計画」に変換する対話型 CLI です。API キーは不要で、Ollama 上のオープンソースモデルだけで完結します。
駒(エージェント)は 7 種類。分析フェーズを終えた駒は「成り」、実装フェーズに入ります。
| 駒 | 分析フェーズの役割 | 成り駒(実装フェーズ) |
|---|---|---|
| 金(Kin) | 要求整理・布陣決定・全体統合 | — |
| 銀(Gin) | UI/UX・体験設計 | 成銀:フロントエンド実装 |
| 飛車(Hisha) | 技術実装・アーキテクチャ計画 | 龍王:バックエンド実装 |
| 角(Kaku) | 品質・リスク・テスト設計 | 龍馬:テストコード実装 |
| 桂馬(Keima) | データモデル・API設計・計測 | 成桂:スキーマ・マイグレーション実装 |
| 香車(Kyosha) | セキュリティ・認可設計 | 成香:認証ミドルウェア実装 |
| 歩(Fu) | ドキュメント・タスク整理 | と金:ドキュメント生成 |
金だけは唯一「成らない」駒で、常にオーケストレーター役です。
使ってみる
Ollama を入れてから起動するだけです。
brew install ollama # macOS の場合
jin
初回起動時は言語モード選択のあと、ローカルモデルのセットアップ画面に進みます。Ollama を未設定でも UI だけを試せる --demo モードもあります。
jin --demo
デモモードでは Ollama を一切呼び出さず、あらかじめ用意された固定のサンプル出力を各駒が返します。今回この記事のスクリーンショットも jin --demo を実際に実行して取得しました。「新しい機能を追加する」を選び、要求として「既存のToDoアプリにタグ機能を追加したい。タグの作成・付与・タグでの絞り込みができるようにしたい。」と入力すると、次のように進みます。
◆ やりたいことを選んでください
│ ● 新しい機能を追加する
└
◇ やりたいことを選んでください
│ 新しい機能を追加する
│
◇ 金が目的と制約を整理しています ✓
┌─ 金(Kin) ─ 分析 ──────────────────────────
│ 「構想を受け取った。目的・制約・布陣を整理する。」
│
├─ 受信 ────────────────────────────────────
│ 要求: 既存のToDoアプリにタグ機能を追加したい。タグの作成・付与・タグでの絞り込みができるようにしたい。
│
├─ 返却 ────────────────────────────────────
│ [目的] ...
└────────────────────────────────────────────
デモモードは要求文をそのまま各駒に渡しますが、返す内容は駒ごとに固定されたモック(src/roles/*.ts)です。実際に Ollama を叩く実行では、この「返却」の中身が要求に応じて変わります。全 6 駒の分析が終わると、銀は成銀に、飛車は龍王に……と成って実装フェーズに入り、最後に金が全体を統合して提案としてまとめます。
布陣が決まるまで
肝心なのは、どの駒を呼ぶかを固定リストではなく 金が動的に決める ことです。実装は src/screens/inReview.ts にあります。
金の出力に含まれる「布陣」セクションを extractFormation がパースし、そこに書かれた駒名から関与する駒の ID リストを組み立てます(src/screens/inReview.ts:301)。LLM 呼び出しに失敗したりパースできなかった場合は、要求の種類ごとに定義した静的ルーティング(src/routing/roleRouter.ts)にフォールバックします。
各駒の分析結果は金がレビューし、approve / retry / add のいずれかを返します(runKinReview、src/agents/runner.ts:187)。差し戻しは駒ごとに最大 2 回まで(MAX_RETRIES_PER_ROLE)、布陣全体としても最大 12 反復まで(MAX_TOTAL_ITERATIONS)という上限を設けていて、LLM が意見をこじらせて無限ループに入るのを防いでいます。上限に達した場合は強制承認して次に進みます。
小さいモデルほど指示を守らずフォーマットを崩しやすいので、プロンプト側にも工夫を入れました(src/agents/techniques.ts)。
- 全モデル共通で Chain-of-Thought の前置きを付与する
- 30B 未満のモデルには Few-Shot の出力例を追加する
- 30B・32B・35B・70B・72B を含むモデル名には ReAct 形式の推論指示を追加する
- 角(品質・リスク担当)だけは 3 つの視点で並行生成してマージする自己一貫性を適用する
閾値はモデル名に含まれるパラメータサイズの文字列(35b 30b 32b 70b 72b)で判定しており、同じプロンプトでもモデルサイズによって効き方が変わることを前提にした実装です。
ダッシュボードで可視化する
jin を起動すると http://localhost:3050 にダッシュボードが自動で立ち上がります。各駒が何を受け取り、何を返したかをリアルタイムに見られます。
過去のセッションを選ぶと、この布陣盤の上でやりとりがリプレイされます。上の画像は実際に jin --demo を動かした直後のダッシュボードで、成銀・龍王・龍馬・成桂・と金が金色の枠で表示され、金(Kin)を中心にデータの流れが破線で描かれています。右側のパネルには「殿 → 金 ― 分析完了」というように、金と各駒のやりとりが会話形式で流れます。
ポートが衝突する場合は環境変数で変更できます。
JIN_DASHBOARD_PORT=3199 jin
作って分かったこと
役割ごとに生成戦略を変えられるのは、単一プロンプトにはない利点です。 角(品質・リスク担当)だけ自己一貫性で3視点をマージしているように、駒ごとに異なる生成戦略を割り当てられるのはマルチエージェント構成ならではだと感じました。
ローカル LLM 特有の作業は「型を守らせる」チューニングでした。 CoT・Few-Shot・ReAct の使い分けは、結局のところ出力フォーマットを崩させないための工夫です。クラウドの大型モデルであれば意識しなくて済む部分に、実装の比重が寄りました。
Claude Code との一番の違いは、権限やツール呼び出しの層がないことです。 Jin はテキストのやり取りとファイル書き出しだけで完結していて、MCP や Git 操作、詳細な権限確認のような周辺機構は持っていません。エージェント同士の「差し戻しループ」や「動的な役割決定」は再現できましたが、実行環境を安全に触らせる部分の設計はまったく別の難しさがあると感じています。次に踏み込むならそこです。
ソースは全て公開しています。気になった方は覗いてみてください。
