Coding Agentを作るだけなら、それほど難しくありません。
Taskを渡して、Modelにコードを書かせ、Testを実行し、失敗したらもう一度修正させる。
しかし実際に自動化し始めると、問題はCode Generationそのものより、その周辺に集まってきます。
- Processが途中で落ちたらどうするのか
- 同じModel Callを二重実行しないためにはどうするのか
- AgentがCanonical Repositoryを壊さないようにするにはどうするのか
- Reviewerを減らしてもQualityが落ちていないことを、どう証明するのか
- ContextやCacheが古くなったとき、どうFail Closedにするのか
そこで作ったのが、AIVP v2というLocal-firstのCoding-Agent Harnessです。
AIVP v2はProduction-readyなMulti-tenant Platformではありません。位置付けとしては、production-minded prototypeです。
今回の記事では、Modelそのものではなく、その外側に作ったHarnessについて説明します。
公開Repository:
1. 全体像
AIVP v2では、Coding Agentを単純なLLM Loopではなく、複数のBoundaryを持つExecution Systemとして扱っています。
概念的にはこうです。
┌──────────────────────┐
│ Task │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Harness Panel │
│ │
│ State / Policy │
│ Context / Routing │
│ Telemetry / Evidence │
└──────┬─────────┬─────┘
│ │
generation │ │ verification
▼ ▼
┌──────────┐ ┌───────────────┐
│ Codex │ │ Test / Review │
└────┬─────┘ └───────┬───────┘
│ │
▼ ▼
┌────────────────────────────┐
│ Per-run Git Worktree │
│ + Controlled Verification │
└─────────────┬──────────────┘
│
▼
AUTO_FINISHED
or
HUMAN_REQUIRED
重要なのは、Modelを中心に置いていないことです。
中心にあるのはHarnessです。
ModelはHarnessから見れば、失敗する可能性のあるWorkerの一つとして扱います。
2. Process MemoryではなくSQLiteにRun Stateを持たせる
最初の問題はDurabilityでした。
例えば、GeneratorがChangeを作り終えた直後にProcessが落ちたとします。
単純なScriptなら、もう一度最初から実行するしかありません。
しかしModel CallにはCostがありますし、再実行すると同じ結果になる保証もありません。
そこでAIVP v2では、Run StateをSQLiteへ永続化しました。
概念的には、
run
├── current state
├── completed steps
├── pending steps
├── artifact references
├── verification result
├── review result
├── risk decision
└── terminal state
のような情報をProcess Memoryの外に持たせています。
これにより、
NEW
↓
GENERATING
↓
VERIFYING
↓
REVIEWING
↓
AUTO_FINISHED
の途中でProcessが死んでも、
「どこまで完了していたか」
を復元できます。
Resume時には既に完了済みのStepを再実行せず、必要な地点から再開します。
ここでSQLiteを選んだ理由は単純で、このPrototypeではDistributed Databaseが必要なかったからです。
Local-first / Single-userというBoundaryの中では、Operational Complexityを増やさずにDurabilityを得られるSQLiteの方が合っていました。
将来Multi-user化するならPostgreSQL等を検討できますが、現段階では不要と判断しています。
3. Canonical Repositoryを直接編集させない
次はIsolationです。
Coding AgentにCanonical Repositoryを直接編集させると、失敗したRunの影響範囲が大きくなります。
そこでRun単位でGit Worktreeを作ります。
canonical repo
│
├── run-A worktree
├── run-B worktree
└── run-C worktree
これによって、それぞれのRunが別のFilesystem Boundaryを持ちます。
AIVPが失敗してもCanonical Repositoryそのものを直接壊しにくくなります。
また、Runが終われば、
worktree
artifact
cache reference
run state
をOwnership単位で追跡できます。
このOwnership情報は、後述するGarbage Collectionにも使っています。
4. 「Promptで禁止」ではなくCapabilityを制限する
Coding Agentでは、
Productionへ接続しないでください
とSystem Promptに書くだけではBoundaryとして弱いと考えています。
そのためAIVP v2では、Capability Policyを別Layerに置いています。
例えば概念的には、
LOCAL_MUTATE
EXTERNAL_READ
EXTERNAL_WRITE
SENSITIVE
PRODUCTION
のようなCapabilityを分類し、Harness側で許可・拒否します。
特にProduction CapabilityはDefault Denyです。
つまり、
Model:
「これを実行したい」
Harness:
「Policy上許可されているか?」
を分離します。
LLMのReasoningとAuthorizationを同じ場所に置かない、という設計です。
5. Verificationは可能な限りDeterministicにする
Modelが生成したChangeを別のModelだけで評価すると、
probabilistic generator
↓
probabilistic reviewer
になってしまいます。
Independent Review自体には意味があります。
ただし、その前に可能な部分をDeterministicに判定します。
AIVP v2では、
syntax
tests
path constraints
diff constraints
policy
artifact integrity
など、機械的に判定できるものを先に処理します。
Verification SandboxについてはDockerをBoundaryとして採用しています。
目的は、
「ModelをDockerに入れる」
ことそのものではなく、
Verification Environmentを
Host Environmentから分離する
ことです。
NetworkやFilesystem、Environment VariableなどのBoundaryも、できるだけHarness側で狭くします。
6. Context Compilerを作った
Coding AgentにRepository全体を毎回渡すのは高コストです。
そこでTaskに関連するContextだけを組み立てるContext Compilerを作りました。
例えば、
task
↓
repository map
↓
candidate files
↓
relevant symbols
↓
policy / architectural context
↓
compiled context
という流れです。
Controlled BenchmarkではProvider Inputが、
413,779
↓
110,790
まで減りました。
削減率は**約73.22%**です。
ただし、ここには重要な失敗があります。
最初はさらにAggressiveなCompressionを試しました。
Token数だけを見ると良い結果でした。
しかしRetrieval Qualityが十分ではなかったため、採用しませんでした。
また、最終的に採用したCompiled Contextも、そのControlled RunではBaselineより約3.35秒遅くなりました。
したがって、
Context CompressionによってLatencyも改善した
とは主張していません。
改善が確認できたのは、主にProvider Input量です。
このあたりは、数字を一つだけ見てOptimization成功としないために意識した部分です。
7. Deterministic Cache
Context Preparationを毎回ゼロから行うのも無駄なので、Deterministic Cacheを追加しました。
Local Controlled Benchmarkでは、
cache miss median
133.203 ms
cache hit median
8.242 ms
でした。
約16.162倍で、Context Preparation Latencyとしては約93.813%減です。
Provider Prompt CacheについてもControlled Callで、
input tokens: 22,052
cached tokens: 11,008
となり、**49.918%**がCachedとして観測されました。
一方でSemantic CacheはDeferredにしました。
「意味的に似ているTask」だけを根拠に過去結果を再利用すると、
Repository SHA
Policy
Business Invariant
Dependency State
などの違いを見落とす可能性があります。
そのため現時点では、
Similarityが高いからReuseする
というCacheは採用していません。
8. Optimizationより先にEval Harnessを作る
AIVP v2で最も重要だった順番の一つが、
Eval
↓
Routing Optimization
です。
逆ではありません。
Reviewer Callは高コストです。
なので当然、
Low RiskならClaude ReviewをSkipできないか?
という案が出ました。
最初に試したBroad LOW/LOW Routingでは、Reviewer Callをかなり削減できる可能性がありました。
しかしSafety Boundaryとして広すぎると判断してRejectしました。
もしFixed Evalがなければ、
Callが減った
↓
Optimization成功
と判断していた可能性があります。
そこでM7で先に固定Evaluation Suiteを作りました。
最終的なM7 baselineは、
15 cases
27 trials / regrades
15 / 15 PASS
です。
ここを固定してからRoutingを変更しました。
9. Risk-aware Routing
M8では、Eval結果を壊さない範囲でReviewer Callを減らしました。
結果はこうなりました。
| Metric | M7 | M8 | Difference |
|---|---|---|---|
| Fixed Eval | 15/15 | 15/15 | unchanged |
| Codex Calls | 47 | 47 | 0 |
| Claude Calls | 31 | 25 | -6 |
| Total Model Calls | 78 | 72 | -6 |
| Total Calls Reduction | - | - | -7.69% |
| Claude Calls Reduction | - | - | -19.35% |
| Wall Time | 1122.694s | 1036.739s | -7.66% |
ここで注意しているのは、Wall Timeの改善をRoutingだけの因果として主張していないことです。
同時に変動する要素があるため、
85.955秒短くなった
というObservationまでは言えても、
Routingによって85.955秒改善した
とは言っていません。
また、M8では6件のNo-op Review Routing Artifactと、Claude Callが6件減ったことが一致しています。
これはMechanismを支持するEvidenceですが、これも完全な因果証明とは扱っていません。
10. Cost per Accepted Change
AIVPでNorth Starとして置いた指標が、
Cost per Accepted Change
です。
単純なCost per Runではありません。
Agentが安くても、間違ったChangeを大量に生成したら意味がないからです。
本来は、
provider cost
──────────────
accepted change
として見たい。
ただし今回、USD Provider Billing Evidenceは十分に取れませんでした。
そのため、
USD Cost per Accepted Change = UNAVAILABLE
としています。
推定値で埋めてはいません。
今回公開しているのは、
model calls
token observations
latency
quality outcome
など、実際に取得できたEvidenceです。
11. Garbage CollectionもHarnessの一部
Agent Systemを長く回すと、WorktreeやCache、Artifact、Run Directoryが残ります。
単純に、
docker system prune -a
rm -rf ...
のように消すのは危険です。
そこでM9では、
Delete less, identify ownership first
という原則でGarbage Collectionを作りました。
CLIとしては、
aivp gc --older-than 7d
のように扱います。
DefaultはDry Runです。
実際に削除する場合だけ、
--yes
を要求します。
さらに、
AIVP-owned
terminal
resumable
unknown ownership
evidence retention
を区別します。
Ownershipが不明なものは削除しません。
Host全体に対するGlobal Docker Pruneも行いません。
12. 最後にPublic Reproducibilityを作った
実装が動くだけでは、第三者には分かりません。
そこで最後のM10では、
README
Architecture
Technical Report
Benchmark Report
Security
Evals
ADRs
Publication Evidence
を揃えました。
さらにMakefileを追加し、最低限の入口を、
make doctor
make demo
make benchmark
make test
にまとめました。
make demoはLive Codex / Claude Providerを使いません。
Scripted Providerを使い、
controlled verification failure
↓
bounded repair
↓
re-verification
↓
terminal state
までを再現します。
そのためAPI QuotaなしでHarnessのControl Flowを確認できます。
現在のRegression Suiteは、
415 tests
がPASSしています。
Publication前にはClean Cloneから、
make doctor
make demo
make benchmark
make test
を再実行しました。
さらにGit HistoryについてもCurrent Treeだけではなく、Reachable Blobを全走査しました。
Historical .env、Private Path、Credential-like String、Runtime Artifactなどが過去Commitに残っていないことを確認してからPublic化しています。
13. AIVP v2で意識したこと
AIVP v2を作っていて、Coding Agentの品質はModel性能だけでは決まらないと感じました。
Modelの外側に、
State
Context
Policy
Isolation
Verification
Evaluation
Observability
Economics
Lifecycle
が必要です。
LLMを「賢い関数」として呼ぶだけではなく、
失敗する可能性のあるProbabilistic Workerとして扱う
というのが、今回の設計の中心です。
Harnessの役割は、
失敗をなくすこと
ではなく、
失敗しても復旧できる
影響範囲を制限できる
Evidenceを残せる
不確実なら人間へ返せる
状態を作ることだと考えています。
14. Limitations
最後に、できていないことも明確にしておきます。
AIVP v2はLocal-first / Single-userです。
Production-readyなMulti-tenant Platformではありません。
Zero Trust Systemでもありません。
Semantic CacheはDeferredです。
Production CapabilityはDefault Denyです。
USD Cost per Accepted Changeは、Provider Billing Evidence不足のためUNAVAILABLEです。
また、M7/M8のEvaluationはFixed Suite上での結果であり、すべてのRepositoryやTaskへ一般化できる数字ではありません。
そのBoundaryを含めて公開しています。
まとめ
AIVP v2で作ったものを一言で表すなら、
Coding Agentそのものではなく、Coding AgentをEngineering Systemとして扱うためのHarness
です。
Code Generationは、その中の一Componentにすぎません。
Generate
↓
Isolate
↓
Verify
↓
Review
↓
Measure
↓
Route
↓
Recover
というLoop全体を制御する方が、実際にはずっと面白い問題でした。
これからCoding Agentがさらに強くなればなるほど、
「何ができるか」より「どこまで任せるか」
を設計する重要性は、さらに上がると思っています。
Repositoryは公開しています。
まずControl Flowだけ確認したい場合は、
make doctor
make demo
から試せます。