藤岡 達也
LLMエージェント基盤 / 協働インターフェース設計

人を、
どこに残すか。

LLMエージェントと協働インターフェースを、動くデモではなく、 壊れ方を制御できるシステムとして設計しています。 残しすぎれば自動化の意味が消え、削りすぎれば取り返しのつかない破壊を許す。 4つの個人開発を通じて、介入点・権限・記録を一体として設計してきました。

取り組める課題

主要プロジェクト

すべて個人開発・現在も運用中

ordinaryMemory 会話から wiki を蒸留し続ける、マルチエージェント知識システム

会話・メモ・文書・ToDoを、27種のエージェントが構造化 wiki へ 蒸留し続ける知識システムです。ただし、エージェントは wiki を直接変更できません。 人はすべての処理を監視するのではなく、質問への回答と変更の受理・却下という、 結果を左右する地点にだけ残ります。

図 01 — ordinaryMemory / 原料と成果物が同じ環を回る

人が関与する点 原料 蒸留 提案 受理 反映 wiki ツリー 文脈に読み込む チャット やり取りが次の原料になる 質問に答える 受理/却下 使う・問いを投げる
原料は会話だけではありません。メモ・取り込んだ文書・ToDo も同じ堆積に入り、 区別なく蒸留の対象になります。要点は成果物が次の周回の入力になることで、 wiki はチャットの文脈として読み込まれ、そこで出たやり取りが再び原料へ戻る。 一周ごとに wiki が濃くなり、濃くなった wiki が次の会話の質を上げます。 人はこの環の上ではなく中にいます。流れ作業の一工程として全件を捌くのではなく、 受理するか却下するか、エージェントが判断できない問いに答えるか、 チャットで実際に使うか——判断が要る三点にだけ関与する
Hono (Node/TS) ── 単一プロセスで JSON API と SPA を配信 ├ エージェント基盤 タスクキュー方式(投入 → 取得 → 一覧) │ 実行ステップを全て永続化し、後から再構成可能 │ サブエージェント委譲・用途別モデル割り当て │ ├ ツール群 12種 wiki / 記憶 / 会話 / 文書 / ToDo / システムページ … │ エージェント27種が同一のツール集合を共有 │ ├ 書き込み経路 propose_wiki_edit → 提案テーブル → 受理 → 反映 │ エージェントは wiki を直接書き換えられない │ ├ LLM 抽象化 9社のLLMプロバイダを共通インターフェース背後に配置 │ プロバイダ固有の破綻はアダプタ層で吸収 │ リクエスト単位で利用量とコストを記録 │ └ Postgres 型接頭辞つきID・冪等マイグレーション テストは使い捨てPostgresを都度起動

27種のエージェントが同一のツール集合を共有する構成にしたことで、 新しい用途を足すコストが「プロンプトと担当範囲を書く」だけになりました。 エージェントごとに専用の道具を作らない、という判断です。 実行はタスクキュー方式にしてあり、長い処理でリクエストを占有しません。 書き込み権限をどう絞ったかは規律02に、 障害をどう追跡しているかは規律01に記載しています。

swiper スワイプ評価で育つ画像生成プロンプトスタジオ

LLMが提案し、ComfyUIが生成した画像を、人がスワイプと任意のコメントで評価する協働ループです。 画像の良し悪しは言語化しづらい一方、見れば即断できる。だから判断は人に残し、 基本の入力を軽くしました。

図 02 — swiper / 人に何を要求しないかで、集まる標本が決まる

人が関与する点 提案 プロンプト 生成 画像 スワイプ 評価 追記ストア 蓄積された評価が、次の提案の文脈になる 入力方法と、フィードバックの続けやすさ 毎回コメントを必須にする 入力負荷が高い スワイプ + 任意コメント 継続しやすい
環の形は他のシステムと変わりません。効いたのは人の位置に何を置いたかです。 画像の良し悪しは言語化しづらい一方、見れば即断できる。だから判断は人に残す。 基本の評価はスワイプで完了し、言葉にできるときはコメントを添えられます。 軽い入力と情報量の多い入力を排他的にせず、必要に応じて使い分けられる設計です。
提案 LLM がプロンプト候補を生成 生成 ComfyUI API へ投入 → 画像を GCS へアップロード フロントは image_id の変化だけを見て再読み込み (latest.png のポーリングをやめ、無駄な取得を排除) 評価 人がスワイプ → 追記専用ストアへ 反映 蓄積された評価を次の提案文脈に注入 運用 Docker Compose + systemd で常駐、手動生成と全自動を切替

提案と評価は追記専用ストアに蓄積し、次の提案の文脈として再投入します。 スワイプを基本操作にしつつ、理由や方向性を伝えたい場合はコメントも保存できます。

Tray キーボード操作前提のツリー型アウトライナー

タスク管理・日誌・思考の整理に日常的に使うツリー型アウトライナーです。 ここでは人の判断をエージェントへ渡しません。思考そのものは人に残し、 深い階層を読む負荷と操作の摩擦だけを削っています。

図 03 — Tray / 深さを字下げではなく色で符号化する

プレーンテキスト 深さは字下げの量だけ 第何階層かは数えるしかない 深くなるほど現在地を落とす Tray 同じ木を、深さで色分けする 深さも系統も色で読める 深さ 1 → 5
同じ木を二通りに描いています。左では全ての行が同じ色で、深さは字下げの量からしか読めません。 浅いうちは問題になりませんが、深い位置に入った瞬間、自分が何の下にいるかを 上まで遡って数える作業が発生します。右はインデントガイドを階層ごとの色に置き換えたもので、 深さと親の系統が、その行を見るだけで分かる。 情報を足したのではなく、すでに画面にあった字下げという情報を、 数えなくても読める形に符号化し直しただけです。 日常的に自分で使う中で最も効いた変更がこれでした。

子要素の生成・編集への遷移・フォーカス移動・要素の移動・折り畳みは、 すべてキーボードショートカットへ割り当てました。 作った本人が毎日使い、見つけた摩擦を継続的に削っています。

astraloop LLMエージェントによる機械学習実験の自動探索

LLMが改善案を提案し、MCTSが限られた試行予算を配分する自動探索システムです。 人が評価基準や探索条件を与え、 その基準の中で、試行ごとの提案と探索順序をエージェントへ委ねます。

図 04 — astraloop / 人が評価と制約を与え、その中を探索する

人が与える評価基準と探索条件 評価関数・採否条件 固定条件・探索制約 試行予算・配分規則 提案 設定差分 選別 残った案 配分 予算を割る枝 試行・スコア スコアを木へ逆伝播し、反証された案は次の提案文脈へ 与えられた基準と制約の中で探索する
人が目的と制約を与え、エージェントはその中で候補を提案し、MCTSが試行予算を配分します。 つまり人の判断を無くすのではなく、各試行への逐次介入から、探索空間と評価基準の設定へ 役割を移しています。重複検知や実効変化判定は、限られた予算を有効な試行へ使うための仕組みです。

重複検知・多様性ポリシー・実効変化判定を挟み、似た案の反復や 「変更したつもりで何も変わっていない」試行への予算消費を防いでいます。 統計的な側面と実験設計の詳細は Page 01 — 統計的推論・実験設計 に記載しています。

人が介入する地点の設計

上記のプロジェクト運用から導いたもの

4つの実例で異なっていた人の位置は、次の三問で決まります。 その判断を実運用で成立させる土台が、後に続く分離記録です。

規律 01 — 判断

人の判断を、どこに残すか

残しすぎれば自動化の意味が消え、削りすぎれば取り返しのつかない破壊を許す。 地点を決めるとき、私は次の三つをこの順に問います。 先に来るものほど強く、上で決まれば下は見ません。

  1. 取り返しがつくか。 不可逆な操作の手前には、必ず人を置きます。やり直せる操作なら任せてよい。 この一問で決まる場面が最も多く、判断の質を議論する前に片が付きます。
  2. 人にしか分からないことがあるか。 言語化しづらいが見れば即断できる、という種類の判断は人に残します。 ただし要求する労力は最小まで削る。労力が重いと標本が集まらず、 残した意味がなくなります。
  3. 評価基準と制約を形式化できるか。 評価関数や固定条件として与えられるなら、人が枠組みを決め、 その中の反復をエージェントに委ねます。 形式化できない判断まで無理に外すことはしません。

図 05 — 三問のカスケードと、4システムが出てくる位置

人の関与 設計対象 自動化する対象が無い 問 1 取り返しがつくか つかない つく 問 2 人にしか分からないことがあるか ある ない 問 3 評価基準と制約を形式化できるか できる できない 既定 — 人が判断する Tray すべての操作が人 全面 ordinaryMemory 提案の受理 要所 swiper スワイプ + 任意コメント 要所 astraloop 評価・制約を設定し、反復を委ねる 設計時
出口の高さは自動化の到達度ではなく、問いが片付いた深さです。 ordinaryMemory は不可逆性の一問で決まり、astraloop は人が評価と制約を形式化した上で、反復を委ねています。 Tray は自動化する判断がないため、このカスケード自体が起動しません。
規律 02 — 分離

エージェントに、直接の権限を渡さない

エージェントの出力品質は確率的です。どれだけプロンプトを詰めても外れは出ます。 だから外れたときに何がどこまで壊れるかを、権限の設計で先に決めておきます。 プロンプトで賢くすることと、壊れる範囲を限ることは別の仕事で、後者は構造でしか解けません。

図 06 — 権限の分離 / 出力が外れたとき、壊れる範囲はどこまでか

直接書き込みの経路は存在しない エージェント 出力は確率的 呼ぶ 書く 外れたときに壊れる範囲 登録済みツール 12種 未登録の操作へは手が届かない 提案テーブル propose_wiki_edit の書き先 ペルソナ名前空間 / 使い捨てDB 試行が本番の蓄積に触れない 受理 人 / 規則 反映 本番の蓄積 wiki ツリー 記憶 / 会話 / 文書 一度の破壊が 過去の蓄積を巻き込む
エージェントが外しても、届くのは登録済みツール・提案テーブル・分離環境までです。 本番へ進む経路は受理の一本に絞り、直接書き込みは禁則ではなく、配線そのものを持ちません。 出力品質の改善とは独立に壊れる範囲を固定することで、安心して試行できます。
規律 03 — 記録

障害の記録を、修正の入力にする

エージェントの不具合は再現が困難です。出力は確率的で、ツール実行列は長く、 挙動はプロバイダに依存する。記録が薄いと調査は「なんとなく失敗した」で止まり、 対策が推測に変わります。そこで実行を全ステップ永続化し、 タスクID ひとつで全体像を復元できる状態を先に整えました。

make agent-debug TASK=task_xxxxxxxx ── 単一コマンドで全復元 ヘッダ 状態 / 所要時間 / 使用プロバイダ / エラー ステップ表 seq・反復回数・ツール名・引数・結果/エラー LLM 呼び出し 入出力トークン・実コスト(USD)・レイテンシ コンテキスト増加を棒グラフで可視化 開始→終了のトークン数、1コールあたり平均増加量 ツール頻度 どのツールを何回叩いたか エラー一覧 失敗したステップのみ抽出

必要な情報を単一コマンドへ集めたことで、一次調査が機械的に片付き、 タスクIDから原因特定と修正へ進めるようになりました。 防御ロジックには観測元のタスクIDを残し、障害と修正を結びつけています。

この経路で、同一ツール呼び出しの反復、壊れたJSON、トークン上限による出力欠損、 プロバイダ固有形式などを特定し、吸収層へ対策を追加してきました。 個々の対処より重要なのは、まだ見ぬ破綻も同じ経路で潰せることです。

技術スタック

実運用しているものに限定

LLM / エージェント DeepSeek・OpenAI・Gemini・xAI・Cerebras・OpenRouter・Alibaba・Z.AI・Ollama を共通抽象の背後に実装/ツール実行ループ、マルチエージェント委譲、タスクキュー方式の非同期実行、サブエージェント、用途別モデル割り当て
信頼性設計 構造化出力(zod → JSON Schema)、引数の正規化と型強制、破綻したツール呼び出しの寛容パース、無限リトライ検知、プロバイダ固有プロトコルのアダプタ吸収、実行ステップの全永続化、利用量とコストの計測、提案と反映の分離、ツールの登録制、名前空間とテスト環境の隔離
画像生成 ComfyUI API 連携、ワークフロー制御、生成物の GCS 配信と署名URL、フィードバック蓄積ループ
フロントエンド Preact、Vite、TypeScript/キーボード駆動UI、ツリー型UI、SPA配信、状態管理とフックの自作構成
バックエンド TypeScript(Hono / Node)、PostgreSQL、MongoDB、SQLite、スキーマ駆動のリクエスト検証
基盤・運用 Docker Compose、systemd(service / timer)、GCS、セルフホスト運用全般
テスト Vitest(testcontainers で使い捨てPostgres)、Playwright による E2E