0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIエージェント開発に「インデックス」という考え方を持ち込めないか

0
Posted at

AIエージェントを使った開発では、README、CLAUDE.md、AGENTS.mdなどにプロジェクトのルールや仕様を書き、エージェントに最初に読ませるやり方がよく使われる。

これはかなり強力だ。

AIのメモリ機能や、過去の会話履歴に頼るのではなく、リポジトリ内に置かれたドキュメントを唯一の正として扱える。

仕様が変わったらドキュメントを更新する。
次に起動したエージェントも、その最新の仕様を読む。

いわゆる仕様駆動開発とAIエージェントは、かなり相性がいい。

ただ、実際にやっていると一つ気になることがある。

ドキュメントを読むだけで、かなりのトークンを消費する。

仕様書が育つほど、毎回読むコストが高くなる

最初はCLAUDE.md一枚だけだったものが、プロジェクトが育つにつれて増えていく。

たとえば、

  • 要件定義
  • 技術仕様
  • アーキテクチャ設計
  • API仕様
  • ディレクトリ構成
  • コーディング規約
  • テスト方針
  • ADR
  • 運用手順

などだ。

すると、エージェントはタスクを始めるたびに大量の文書を読むことになる。

もちろん、コンテキストウィンドウが大きくなれば全部入れることはできる。

しかし「入れられる」ことと「毎回入れるべき」ことは違う。

数万トークンある仕様書のうち、今回必要なのは認証仕様の一節だけ、ということは珍しくない。

そこでふと思った。

データベースにはインデックスがある。
同じ発想を、AIエージェントのコンテキスト取得にも使えないだろうか。

データベースは毎回Full Scanしない

データベースで大量のデータを検索するとき、毎回すべての行を先頭から読むわけではない。

インデックスを使って、

「必要なデータがどこにあるか」

を先に特定する。

その後、必要なデータだけを取得する。

AIエージェントも同じ構造にできるのではないか。

現在の仕様駆動開発では、エージェントに仕様書そのものを渡している。

これを、

仕様そのものではなく、まず仕様へ到達するためのインデックスを渡す

形に変える。

たとえば、ユーザーから、

「ログイン処理を変更して」

と言われたとする。

エージェントは最初に巨大な仕様書を読むのではなく、まず小さなインデックスを検索する。

capability: auth.login

docs:
  - docs/product/auth.md#login
  - docs/architecture/session.md#authentication

code:
  - src/auth/**
  - src/api/login.ts

tests:
  - tests/auth/login.test.ts

tools:
  - test.auth
  - db.schema.users

related:
  - auth.session
  - security.rate-limit

これを見るだけで、

  • どの仕様を読むべきか
  • どのコードを見るべきか
  • どのテストを実行すべきか
  • 必要ならどのツールを使うべきか

が分かる。

そして必要になった箇所だけを読む。

不足していれば、relatedにある次の候補を読む。

それでも足りなければ、通常のgrepや検索にフォールバックする。

つまり、

Index Scan → 必要箇所の取得 → 不足時のみ追加探索

という流れだ。

「仕様書のインデックス」だけではなく「ツールのインデックス」にする

この発想で特に面白いと思っているのが、ドキュメントだけを対象にしないことだ。

LLMは基本的には、テキストを受け取り、テキストを返す。

そこにAPI、MCP、シェル、ブラウザ操作などのツールを組み込むことで、エージェントとして汎用的になる。

であれば、

ドキュメントとツールに共通のインデックスを貼ればいい。

たとえば、

auth.login

という共通IDに、

  • 要件
  • 設計
  • 実装
  • テスト
  • DBスキーマ
  • ブラウザ操作
  • 検証コマンド

を紐づける。

イメージとしてはこうだ。

                    requirement
                         |
                    architecture
                         |
docs ----------- auth.login ----------- code
                         |
                       tests
                         |
                       tools

エージェントにとって重要なのは、

「何を知っているか」

だけではない。

「その領域について何ができるか」

も同時に知る必要がある。

ならば、知識とアクションを別々の探索空間にする必要はない。

Capability = Knowledge + Action + Validation

という単位でまとめてもいい。

インデックスは真実を持ってはいけない

ただし、この仕組みには重要な原則がある。

インデックス自体を仕様書にしてはいけない。

たとえばインデックスに、

auth.login = JWT認証

と書いてしまう。

その後、本当の仕様書ではCookie Sessionに変更したのに、インデックスの更新を忘れたとする。

すると真実が二つできてしまう。

これは危険だ。

データベースのインデックスも、本体データとは別物だ。

インデックスの役割は、

「データがどこにあるかを示すこと」

であって、

「データそのものになること」

ではない。

同じように、

仕様書はSource of Truth。
インデックスはSource of Location。

と分離するのが重要だと思う。

インデックスには、

id: auth.login
source: docs/product/auth.md
anchor: "#login"

までを書く。

実際の仕様は必ず参照先に置く。

ファイル単位ではなく、セクション単位で参照したい

さらに、インデックスが、

auth.login → docs/auth.md

だけでは不十分だ。

結局auth.md全体を読むことになる。

なので、

auth.login → docs/auth.md#login

のように、できるだけ細かい単位で参照する。

大きなドキュメントなら、

AUTH-LOGIN-BEGIN
...
AUTH-LOGIN-END

のような安定した境界を持たせてもいい。

するとエージェントは、その区間だけを取得できる。

これはトークン削減だけでなく、不要な情報による判断ノイズも減らせる。

AGENTS.mdは「百科事典」ではなく「ブートローダー」にする

この考え方を突き詰めると、AGENTS.mdやCLAUDE.mdの役割も変わる。

大量の仕様を書く場所ではなくなる。

代わりに、

「このリポジトリでどう情報を探すか」

だけを書く。

たとえば、

1. タスクを受け取ったら最初に.agent/indexを検索する
2. capabilityを特定する
3. normativeな仕様だけを読む
4. 不足時のみrelatedを辿る
5. 最後に指定されたvalidationを実行する
6. indexと仕様が矛盾した場合、仕様を優先する

程度でいい。

つまり、

AGENTS.md = ブートローダー
Index = クエリプランナ用メタデータ
docs = Source of Truth

という三層構造になる。

一番難しいのはインデックスの陳腐化

もちろん問題もある。

一番怖いのは、

仕様書は更新されたのに、インデックスだけ古い

状態だ。

通常の全文探索なら遅くても仕様を見つけられる。

インデックス方式は高速だが、インデックスから漏れた情報は見つからない可能性がある。

データベースでインデックスが成立するのは、データ更新とインデックス更新が一体になっているからだ。

AIエージェント用のインデックスも同じで、

document update
↓
index regenerate
↓
validation
↓
commit

という流れにすべきだと思う。

手作業でindex.yamlを更新する方式は、おそらく長期運用では壊れる。

なので各ドキュメントにメタデータを持たせ、

---
id: auth.login
type: product-spec
related:
  - auth.session
tests:
  - test.auth.login
---

そこからインデックスを自動生成する方がよさそうだ。

つまり、インデックスは手書きの仕様ではなく、生成物にする。

インデックスが外れたらFull Scanに戻ればいい

そして、インデックスは絶対的なものにしない。

検索の最初に使うだけだ。

理想的には、

Task
↓
Index Lookup
↓
候補の仕様を読む
↓
十分?
 ├─ Yes → 実装
 └─ No
     ↓
 relatedを辿る
     ↓
 grep / semantic search
     ↓
 必要ならFull Scan

とする。

データベースのクエリプランナと同じで、

Index Scanが効くなら使う。

効かなければ別の探索手段を使う。

重要なのは、

インデックスによって探索を禁止するのではなく、探索順序を最適化すること

だ。

LLMにプロジェクト全体を覚えさせるのではなく、探索方法を覚えさせる

この発想の本質は、トークン削減だけではないと思っている。

現在のAIエージェント開発では、

「必要な知識を全部コンテキストに入れる」

方向に寄りやすい。

しかし別の考え方もある。

プロジェクト全体をコンテキストとして持たせるのではなく、
プロジェクトを探索する能力をコンテキストとして持たせる。

つまり、

巨大なKnowledge Context

ではなく、

小さなIndex
+
必要な情報を取得するTool

を持たせる。

必要な情報は、その都度取得する。

これは、AIエージェントが巨大なコードベースを扱うようになるほど重要になってくる気がする。

今の多くのエージェント開発は、まだかなり「Full Table Scan」に近い。

その次に来るのは、

semantic key → index scan → pointer chase → 必要なら追加scan

という仕組みなのかもしれない。

仕様駆動開発の次のテーマは、

「何を仕様書に書くか」

だけではなく、

「AIがその仕様へどう到達するか」

になるのではないかと思っている。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?