この記事は https://danarcheronline.github.io/posts/mind-body-agent で最初に公開されました(originally published at https://danarcheronline.github.io/posts/mind-body-agent)。
エージェントのことを、つい「モデルそのもの」だと考えてしまいがちです。すごいことをすればモデルが賢い。間抜けなことをすればモデルがポンコツ。だから、もっと新しいモデルや、もっといいプロンプトを探しに行くわけです。
たしかにモデルやプロンプトを良くすれば改善することもあります。でも、話はそう単純ではありません。 私がしっくりきたのは、エージェントを一人の人間として考えること(すでに怖いくらいそうしていますが)。そしてLLMモデルとハーネスを、そのデジタルな人間の脳と体として捉えることでした。
モデルは脳
脳にあたるのは、大規模言語モデルそのものです。テキストを受け取り、次に来るべきテキストを予測します。AIが「賢い」と言われるとき、その中身である推論も、提案してくるコードも、すべてここで生まれています。
とはいえ、瓶に入った脳だけではたいしたことはできません。コードベースを見る目もなければ、ファイルを編集したりテストを実行したりする手もない。5分前に何があったかさえ、誰かがもう一度見せてくれなければ覚えていられません。だからこそ AnthropicのMessages API のようなモデルのAPIは、呼び出しのたびに会話履歴を丸ごと受け取る仕組みになっています。モデル単体でできるのは、チャット画面で修正方法を説明するところまで。実際に直すことはできないんです。
ハーネスは体
ハーネスとは、モデルの周りにあるものすべてのことです。この言葉はネット上で一気に広まりましたが、私が最初に目にしたのはBirgitta Böckelerさんの記事 Harness engineering for coding agent users でした。彼女はハーネスという言葉について、「AIエージェントのうち、モデル自体を除くすべてを指す略語として定着してきた」と書いています。
これが体です。脳が何を見て、何に触れられて、脳が生み出したものがどうなるのかを決めています。
厳密に言えば、プロンプトをLLMモデルに直接渡すこともできるので、このたとえはここで破綻します。人間の脳に感覚入力を直接ねじ込むことはできませんからね。今のところは…
それでも普通は、プロンプトを最初に受け取るのはハーネスの目です。 たとえば、エディタのコーディングエージェントに、落ちているテストを直してほしいと頼んだとします。目にあたるのは、リポジトリを検索して、モデルにどのファイルを見せるかを選ぶ部分です。手にあたるのは、ファイルを編集したり npm test を実行したりするツール。モデルにできるのは、それを使いたいと頼むことだけです。そのツールがそもそも存在するかを決め、実際に作業をするのはハーネスのほうです。
それから神経もあります。テストが落ちたら、その出力がモデルに戻され、モデルはもう一度挑戦します。型エラーやlintの失敗は、誰かがフィードバックしない限り脳には届きません。ルールも知っておく必要があり、それはベンダーのシステムプロンプトや、私自身の AGENTS.md から来ています。さらに、何かを壊す前に止めてくれる反射もあります。権限確認のプロンプトや、mainに何かが入る前に私がdiffを読むことなどがそうです。
この体の一部は最初から組み込まれています。Claude CodeやCursorのようなコーディングエージェントを使うとき、モデルの振る舞いを指示する隠れたシステムプロンプトは、ベンダーがすでに書いてくれています。モデルに見せるべきファイルを探すコードや、ツールを実行して結果をフィードバックするループも、ベンダーが作ったものです。私はそこには一切手を出していません。
残りは、その上に自分たちで作っていく部分です。私の AGENTS.md、テストやlintのルール、実行を許可するコマンド、そしてマージ前のレビュー。この外側の層こそ、私たちが実際にコントロールできる部分です。
flowchart LR
subgraph Harness
I["Instructions<br/>system prompt, AGENTS.md"] --> M(("Model"))
C["Context<br/>file search, retrieval"] --> M
M --> T["Tools<br/>read, edit, run"]
T --> K["Checks<br/>tests, types, lint"]
K -->|results| M
K --> G["Gates<br/>permissions, CI, review"]
end
flowchart LR
subgraph Harness
I["Instructions<br/>system prompt, AGENTS.md"] --> M(("Model"))
C["Context<br/>file search, retrieval"] --> M
M --> T["Tools<br/>read, edit, run"]
T --> K["Checks<br/>tests, types, lint"]
K -->|results| M
K --> G["Gates<br/>permissions, CI, review"]
end
エージェントは一人の人間
[!tip] AIの数式 人 = 体 + 頭脳 エージェント = ハーネス + LLMモデル
この2つが合わさって、エージェントになります。脳と体がそろえば、実際に物事をこなせる一人の人間になる。魂のプログラミング方法は、まだ模索中ですが… 🤔
こう考えるようになってから、うまくいかないときに見る場所が変わりました。ある人が何度もドアにぶつかっているなら、まず必要なのはもっと賢い脳ではありません。私なら目を確認します。エージェントも同じです。私のエージェントがある規約を無視したのは、その指示が一度も読み込まれないファイルに書かれていたからでした。テストが赤いまま「完了」と言ったのは、誰もテストを実行していなかったから。触る理由のないファイルを編集したのは、それを止めるものが何もなかったから。どれも脳の問題ではありませんでした。
モデルの有用さは、それが宿る体で決まります。だから今は、エージェントが間抜けなことをしても、脳のせいにするのはやめました。まず体を見ています。