エージェント設計の基礎 学習ノート — Harness / Eval / Agent Design¶
開始日: 2026-06-10 動機: ai-engineering-digest で
config/harness.yaml(判断基準の外化)を自作したが、「Claude Code の真似」の域を出ていない。harness・eval・エージェント設計を原理から説明でき、自分のプロジェクトに eval を整備できる状態になる 参考:~/ai-engineering-digest/docs/architecture_multi_agent.md、~/nano-code(書籍「作って学ぶAIエージェント」写経)、software-design/11(ReAct)、software-design/23(Supervisor/Swarm)、software-design/28(GEPA + LLM-as-a-Judge) 写経教材:lectures/eval_basics/— STEP 3〜5 に対応する 6 例(決定論チェッカー / golden dataset / LLM-as-a-Judge / judge バイアス実測 / ハイブリッド評価 / 回帰ゲート)
学習ロードマップ¶
- [ ] STEP 0: 概念整理 — Anthropic「Building Effective Agents」を読み、workflow と agent の区別、5つのワークフローパターン(prompt chaining / routing / parallelization / orchestrator-workers / evaluator-optimizer)を自分の言葉で「メモ」節に書く。harness = モデルの外側にあるループ・ツール・基準・権限の総体、という定義を自分の実例(harness.yaml、Claude Code)で説明できるようにする
- [ ] STEP 1: 最小エージェントループを素手で書く(
s01_minimal_agent.py)— フレームワークなし、OpenAI SDK の tool calling だけでwhileループを実装。終了条件(tool 呼び出しが無くなったら終わり)、tool 結果のメッセージ履歴への追記、max_turnsガードの3点を押さえる - [ ] STEP 2: harness の構成要素を既存実装から逆引き —
~/nano-codeのソースを読み、①エージェントループ ②ツール定義 ③コンテキスト管理 ④permission の4要素がどのファイルにあるか対応表を作る。自分のharness.yaml(基準の外化)がどの要素に相当するかも位置づける - [ ] STEP 3: 決定的 eval(
s02_eval_deterministic.py)— 「正しいツールを選んだか」「禁止操作を拒否したか」を assert する最小 eval を書く。テスト(毎回 pass すべき)と eval(pass 率で測る)の違い、温度・非決定性の扱いをメモ化する - [ ] STEP 4: LLM-as-a-Judge(
s03_llm_judge.py)— ルーブリック設計→judge 実装→judge 自体の検証(人手ラベル 20 件と突き合わせて一致率を測る)まで。position bias(順序入替で判定が変わる)対策も試す - [ ] STEP 5: eval を回帰スイートにする — promptfoo または inspect-ai に STEP 3/4 を載せ、「プロンプトや基準を変えたらスコア差分が見える」状態を作る。Langfuse 学習ノートの STEP 5(オンライン評価)とつなぎ、オフライン eval / オンライン評価の役割分担を整理する
- [ ] STEP 6: 自プロジェクト適用 — ai-engineering-digest の Phase 2(分類)に対し、過去 digest から正解 30 件の eval セットを作る。
harness.yamlの基準を変えると precision/recall がどう動くかを測れるようにする(v0.6 の DSPy optimizer 導入の土台になる) - [ ] STEP 7: セキュリティ / ガードレール — 写経教材
lectures/guardrails_basics/(6 例)を一周し、prompt injection(直接/間接)→ 決定論フィルタ → 権限ゲート(allow/ask/deny)→ 出力ガード → LLM ガード → lethal trifecta、の多層防御を素手で組む。「確率の防御(プロンプト)」と「構造の防御(権限・分離)」の違いを自分の言葉で説明し、自分の~/.claudeの permissions・gitleaks hook・secret-handling がこの6層のどこに対応するかを整理する。research-orchestrator(3リポジトリ横断)を lethal trifecta の3辺で点検する - [ ] STEP 8: loop engineering(トリガー設計) — 写経教材
lectures/loop_basics/(6 例)で loop の2要素「トリガー / 検証可能なゴール」を素手で組む。トリガー3類型(人間 / スケジュール / イベント)を区別し、STEP 1 の最小ループに「いつ起動するか」を足す。検証可能なゴール(STEP 3〜5 の eval)と合わせて「prompt を投げる」から「ゴールに達するまでループを回す」への移行を体得する。大規模化は~/temporal-workflows・~/research-orchestratorで既に実践済みなので、その schedules/ や Temporal cron がこの3類型のどれかを整理して接続する
メモ¶
2026-06-26 ハーネス×ループを実プロダクトに適用してみた(STEP 0 / STEP 8 の実例編)¶
学習教材を写経する前に、harness と loop を自分の実プロダクト(個人で作っているブラウザ絵本アプリ。HTML/CSS/JS のみの公開リポジトリ)に当てはめて設計・実装した記録。STEP 0(概念整理)と STEP 8(loop engineering)を「自分の実例で説明できる」状態にするのが狙い。チェックボックスは写経/読書の達成基準を満たしていないので未チェックのまま、ここに応用ログとして残す。
まず一言で¶
ハーネス=AIが転ばず走るための足場。ループ=人の代わりにAIへ自動でプロンプトを出し続ける制御系。 モデルを賢くするより、AIが「やったつもり」で終わらない環境を作るほうが効く、という体験をした。
なぜ足場が要るのか(初学者がつまずく所)¶
AIに「このアプリ作って」とだけ頼むと、だいたい次の3つで失敗する。これは「モデルが馬鹿だから」ではなく足場が無いからで、人間の新入りでもマニュアル・進捗ノート・テストが無ければ同じ失敗をする。
| 失敗 | 中身 | 足場のどの要素で防ぐ |
|---|---|---|
| 記憶喪失 | 会話が切れると何をしたか忘れる | ①指示書 ②状態 |
| やったつもり | 「できました」と言うが動いていない | ③検証 |
| 暴走・破綻 | 1回で全部やろうとして手を広げる | ④範囲 |
足場の5要素(harness の本体)¶
| 要素 | 何のため | 一般的な実体 |
|---|---|---|
| ① Instructions(指示書) | やり方を毎回ファイルから読ませる | AGENTS.md / CLAUDE.md |
| ② State(状態) | 進捗を会話の外(ファイル)に置く | state.json / 進捗ログ |
| ③ Verification(検証) | 「できた」をテストで証明する | テスト・CI(1コマンドで合否) |
| ④ Scope(範囲) | 一度に1機能だけ渡す | 機能リスト(1機能=1単位) |
| ⑤ Lifecycle(始末) | 毎回同じ手順で始め、同じ状態で終える | 初期化スクリプト |
一番大事なのは③検証。完了判定を「エージェントの自己申告」にすると平気で嘘をつく(悪意でなく、そう錯覚する)。だからテストが green になったかで判定し、しかもテストは人間が先に書いた「契約」にして、AIには「テストを通すコードを書く」だけをやらせる。作った本人に採点させない、が肝。
loop engineering の本質(STEP 8)¶
loop は「prompt を投げる」から「ゴールに達するまでループを回す」への移行。2要素は トリガー(いつ起動するか) と 検証可能なゴール(何が green か)。ハーネスが「1回を確実にする足場」なら、ループは「その1回を何度も自動で回す」もの。maker(作る人)と checker(点検する人)を分離するのが核心。
flowchart LR
L["ループ制御<br/>(トリガー + 上限)"] -->|次の機能を1つ渡す| M["maker<br/>(実装する)"]
M -->|コード| C["checker<br/>(テストで検証)"]
C -->|緑| D["done"]
C -->|赤: 失敗を渡して再試行| M
暴走させない安全装置(総回数上限 / 機能ごとリトライ上限 / 予算上限 / 段階レベル L1→L2→L3)を必ず付ける。L1=レポートのみ → L2=実装するが人間がマージ → L3=無人、と信頼を積んでから権限を上げる。
実例: 自分の絵本アプリへの適用¶
このアプリには既に「Issue 起票 → 人間が承認 → AIが実装して Draft PR → 人間がマージ」という自動化があったが、実装が一発勝負だった(初稿を1回出すだけで、赤なら green まで粘るループが無い)。
ここで効いたのが、検証の資産がすでにあったこと。実ブラウザの E2E テスト(本棚に出る / ページ送りが効く / チャイルドロックが効く…)が「正しい絵本」の契約になっている=足場の③検証は手元にある。足りないのは maker→checker のループだけだった。
設計の核を3つに絞った。
- Issue を spec として扱う — 承認された Issue を「人間用の仕様+機械用の機能リスト+受け入れE2E」に変換
- 赤/緑の基準を1コマンドに集約 — ①E2E(シナリオ網羅)②単体テスト(網羅率80%床)③プライバシー(実名0件)④契約の不可侵(テストを書き換えていない)の4ゲート全部緑で「完了」
- maker エンジンを切り替え可能に — 手元は
claude -p(ローカル本命)、無人運用は別エンジン、オフライン検証はモック。起動オプション1つで差し替え(Maker基底+ファクトリ=Strategy パターン)
学び: UIの品質は「カバレッジ%」よりシナリオ網羅で測るほうが直感的。絶対値の%を追うより「本棚に出る・送れる・抜けない」が全部緑か、のほうが意味がある。
設計で止めず、第一歩の実装まで進めた(TDD + セルフレビュー)¶
- テストを先に書いて落とす(TDD)→ 不変な状態機械(
Feature/LoopState)と設定オブジェクトを実装して green - 状態遷移は新しいオブジェクトを返す(元を書き換えない)。バグ混入と追いにくい副作用を防ぐ
- 状態は JSON でファイル保存 → 途中で落ちても再開できる
そして「マージ前に必ずセルフレビュー」を回したら、自分で書いたコードから本物のバグが3つ出た。3つとも回帰テストを先に足してから直した(最終 28 件 green)。
| バグ | なぜ問題か | 直し方 |
|---|---|---|
| 保存が非アトミック | 書込中にプロセスが死ぬと状態ファイルが壊れ再開不能。「再開可能にする」部品が、保存処理自身で契約を破っていた | 一時ファイルに書いてから os.replace(同一FSでアトミック) |
| 不変オブジェクトが内部辞書の参照を漏らす | 返り値をいじると元が無音で汚れる(frozen の意味が無効化) | dataclasses.asdict で再帰コピーを返す |
| 空の仕様で「何もせず全完了」 | 空集合に対する all([]) は True |
入力境界(spec 読込)で空を弾く |
学び: 「セルフレビューを必ず回す」を仕組みにしておくと、自分のコードでもこれだけ拾える。レビューを工程に埋め込む価値の実証。
用語集¶
| 用語 | 一言 | 補足 |
|---|---|---|
| ハーネス(harness) | AIが転ばず走るための足場 | モデルの外側にあるループ・ツール・基準・権限の総体。5要素(指示書/状態/検証/範囲/始末) |
| ループ(loop) | AIへ自動でプロンプトを出し続ける制御系 | トリガー + 検証可能なゴールの2要素 |
| maker / checker 分離 | 作る人と点検する人を分ける | 作った本人に採点させない。checker は決定的テストで判定 |
| テスト=契約 | 正解を先にテストで固定し、AIに通させる | 人間(or 別主体)が契約を握る。AIにテストを書かせない |
| 自動化レベル L1/L2/L3 | 段階的に権限を上げる | L1=報告のみ / L2=実装+人間マージ / L3=無人 |
| シナリオ網羅 | UI品質を「%」でなく必須シナリオの緑/赤で測る | カバレッジ%の代替指標 |
roadmap との接続¶
- STEP 0(概念整理): 本メモで harness/loop を自分の実例(絵本アプリ)で説明できた。残り=「Building Effective Agents」の5ワークフローパターンを自分の言葉で整理する写経
- STEP 1(最小ループを素手で): 今回は
claude -pを maker に使う高レベル適用。素手のwhileループ実装(s01_minimal_agent.py)は別途 - STEP 8(loop engineering): トリガー3類型(人間/スケジュール/イベント)のうち、今回は「人間が approved を付けたら起動」=人間トリガー + 検証可能ゴール(4ゲート)の実例。スケジュール/イベント型は
~/temporal-workflows・~/research-orchestrator(Temporal cron)で実践済みなので、3類型のどれに当たるか整理して接続する
作成: 2026-06-10 / 最終更新: 2026-06-26