ANTIGRAVITY LABEN
記事一覧/Agents & Manager
Agents & Manager/2026-04-29上級

Antigravity エージェントの『失敗から学ばせる』を仕組み化する — 失敗履歴を次のタスクに活かす設計

Antigravity エージェントは同じ失敗を繰り返すことがあります。失敗履歴を構造化して次の実行に渡すことで、個人開発の運用コストを抑えながら賢く育てる方法を、廣川政樹の運用例とともに解説します。

Antigravity338エージェント64信頼性5個人開発90運用設計23

Antigravity エージェントの『失敗から学ばせる』を仕組み化する — 失敗履歴を次のタスクに活かす設計

Antigravity でエージェントを長く運用していると、ある時期から「これ、先週も同じところで詰まったな」という既視感が増えてきます。シェルのパスを間違える、同じ API のレートリミットに引っかかる、同じ依存ライブラリのインストールに失敗します。エージェントは毎回新しいセッションで動くので、前回の失敗を覚えていません。覚えていないということは、何度でも同じ場所で転びます。

私が個人開発のなかで Antigravity を使い始めて感じたのは、「エージェントの能力を上げる」より「同じ失敗を繰り返さない仕組みを外側に作る」ほうが、はるかに費用対効果が高いということでした。これは LLM の進化を待つ話ではなく、運用設計の話です。今日は私が半年運用してたどり着いた「失敗履歴を次のタスクに活かす」設計を共有します。

エージェントが同じ失敗を繰り返す本当の理由

エージェントが同じ失敗を繰り返すのは、賢くないからではありません。新しいセッションには前回の文脈が一切残らないからです。Antigravity のエージェントは強力ですが、セッション間で「自分が過去にどう詰まったか」を引き継ぐ仕組みは標準では用意されていません。これは安全性の観点では正しい設計です。古い失敗の記憶が新しいタスクの判断を歪めることもあります。

しかし個人開発で同じ環境を相手に動かすエージェントの場合、状況は違います。私のローカル環境はずっと同じだし、使う API キーも変わりません。だから「ここで一度詰まった」という情報は次回も有用です。失敗履歴を意識的に残し、次のセッションに渡してあげるだけで、エージェントの実効的な賢さは見違えるほど上がります。

逆に言えば、失敗履歴をうまく残さないと、エージェントの月額費用は上がり続けます。同じ場所で詰まるたびに無駄なトークンを消費し、リトライのたびに API コストが嵩むからです。これは個人開発者にとって無視できない出費になります。

失敗履歴を JSON Lines で残す理由

最初、私は失敗履歴を Markdown のメモにまとめていました。「今日は X で詰まった、原因は Y、対処は Z」と書いていくスタイルです。しかしこの方式は、件数が増えると次のセッションに全文を渡すのが現実的でなくなります。プロンプトの肥大化はコストにも品質にも響きます。

そこで JSON Lines(JSONL)形式に切り替えました。一行に一件の失敗を構造化して書き、関連するタスクのときだけ抜き出して渡す運用です。

{"ts":"2026-04-12T10:34","task":"deploy","tool":"wrangler","error":"Worker exceeded 62 MiB","fix":"split articles.json into per-article HTML","tags":["cloudflare","bundle-size"]}
{"ts":"2026-04-15T22:11","task":"test","tool":"npm","error":"ENOSPC","fix":"do not run npm install in scheduled tasks","tags":["disk","scheduled-task"]}
{"ts":"2026-04-21T09:02","task":"ingest","tool":"openai","error":"rate limit 429","fix":"use exponential backoff with jitter, base 2s","tags":["rate-limit","retry"]}

この形にしておくと、次の三つが一気に解決します。一つ目は機械的な絞り込みが可能になることで、次のタスクに関係ある失敗だけを渡せます。二つ目は失敗の再発を測定できることで、tags でグルーピングすれば「rate-limit 系の失敗が今月 7 件起きている」と数値で見えます。三つ目はあとから人間が読み返せることで、これは私自身の学習にも役立ちます。

私は failures.jsonl という名前のファイルをプロジェクトのルートに置いて、エージェントの実行のたびに追記しています。git にも含めているので、過去の失敗は永久に検索可能です。

失敗を記録する側のエージェントを別建てにする

ここでハマりがちなのは、「失敗を記録する仕事」を実行中のエージェントに任せてしまうことです。これをやると、エージェントが自分の失敗を都合よく書き換えたり、失敗していないのに失敗と記録したりという、信頼性の低いログが生まれます。

私は「観測係」のエージェントを別に用意しました。実行係のエージェントが終了したあとで、観測係がそのセッションのトレースを読み、失敗を構造化して failures.jsonl に追記する役割です。実行係には書き込み権限を与えず、観測係だけが追記できるようにすると、ログの質が一気に安定します。

観測係に渡すプロンプトの骨子は次のようなものです。

あなたはエージェント実行のレビュアーです。直前のセッションのトレースを読み、
次のいずれかに該当するイベントを JSONL 一行として出力してください。

- ツール呼び出しが失敗してリトライしたケース
- 同じエラーが2回以上発生したケース
- 想定外の入力で停止したケース

出力フィールド: ts, task, tool, error, fix, tags
fix はトレース中で実際に効いた対処を書いてください。推測は書かないでください。
該当しない場合は空行を返してください。

「推測は書かないでください」と明示するのが大事です。観測係はつい「次回はこうすればよさそう」と書きたがりますが、それを許すと未検証の対処が記録されてしまい、次のエージェントを誤った方向に誘導します。観測係はあくまで「実際に効いた対処」だけを記録します。

次のセッションに失敗履歴を渡すパイプライン

失敗履歴を残すだけでは意味がありません。次のセッションに渡してこそ価値が出ます。私が使っている小さな Python スクリプトは、タスクのキーワードを受け取って関連する失敗だけを抜き出します。

# load_failures.py — 関連する失敗履歴だけを抜き出すユーティリティ
import json, sys
from pathlib import Path
 
def relevant(record: dict, keywords: list[str]) -> bool:
    blob = " ".join([
        record.get("task", ""),
        record.get("tool", ""),
        record.get("error", ""),
        " ".join(record.get("tags", [])),
    ]).lower()
    return any(k.lower() in blob for k in keywords)
 
def main(keywords: list[str], limit: int = 8) -> None:
    path = Path(__file__).parent / "failures.jsonl"
    out = []
    for line in path.read_text(encoding="utf-8").splitlines():
        if not line.strip():
            continue
        rec = json.loads(line)
        if relevant(rec, keywords):
            out.append(rec)
    out = sorted(out, key=lambda r: r["ts"], reverse=True)[:limit]
    for r in out:
        print(f"- {r['ts']} [{r['tool']}] {r['error']}{r['fix']}")
 
if __name__ == "__main__":
    main(sys.argv[1:])

エージェントを起動するときは、このスクリプトの出力をプロンプトの先頭に挿入します。たとえばデプロイ系のタスクなら次のように差し込みます。

## 過去の関連する失敗(最大8件)
- 2026-04-12 [wrangler] Worker exceeded 62 MiB → split articles.json into per-article HTML
- 2026-04-15 [npm] ENOSPC → do not run npm install in scheduled tasks
- 2026-04-21 [openai] rate limit 429 → use exponential backoff with jitter, base 2s

## 今日のタスク
(本来のタスク内容)

たったこれだけで、エージェントは前回の地雷を踏まなくなります。私の体感では、デプロイ系タスクの失敗率が以前の三分の一程度に下がりました。

「過学習」という副作用に気づく

この仕組みを半年運用していると、思わぬ副作用が出てきました。失敗履歴が長くなりすぎて、エージェントが「過去の失敗に過剰適応」してしまうのです。

たとえば、ある月の特定の時間帯に偶然レートリミットを連発した記憶が failures.jsonl に厚く残っていると、新しいエージェントは別のプロバイダーの API でも過剰なバックオフを入れるようになります。これは安全側に倒れているので致命的ではありませんが、待ち時間が増えてユーザー体験が落ちます。

私が取った対処は二つです。一つ目は失敗履歴に有効期限を設けることで、90 日を超えた失敗は archived.jsonl に移します。アーカイブされた失敗は通常のロード対象には含みませんが、年単位の振り返りには使います。二つ目は同じタグの失敗が一定数を超えたら集約することで、同じ tag の最新一件だけを代表として残します。

# collapse_failures.py — 古いログの圧縮
from collections import defaultdict
from datetime import datetime, timezone, timedelta
import json
from pathlib import Path
 
CUTOFF = datetime.now(timezone.utc) - timedelta(days=90)
 
active = []
archive = []
for line in Path("failures.jsonl").read_text().splitlines():
    if not line.strip():
        continue
    rec = json.loads(line)
    ts = datetime.fromisoformat(rec["ts"]).replace(tzinfo=timezone.utc)
    (active if ts >= CUTOFF else archive).append(rec)
 
# 同じタグセットの重複を最新一件に圧縮
seen = {}
collapsed = []
for rec in sorted(active, key=lambda r: r["ts"], reverse=True):
    key = ",".join(sorted(rec.get("tags", [])))
    if key in seen:
        continue
    seen[key] = True
    collapsed.append(rec)
 
Path("failures.jsonl").write_text(
    "\n".join(json.dumps(r, ensure_ascii=False) for r in collapsed) + "\n"
)
Path("archived.jsonl").write_text(
    "\n".join(json.dumps(r, ensure_ascii=False) for r in archive) + "\n"
)

このスクリプトを月に一度回すだけで、エージェントが渡される失敗履歴のノイズが大幅に減りました。

失敗を「再発したかどうか」で評価する

失敗履歴を使うようになると、評価指標が一段抽象化されます。これまでは「エージェントの成功率」を見ていましたが、失敗履歴を導入したあとは「同じ失敗の再発率」を見るようになりました。

具体的には、tags が同じ失敗が同月内に再発したケースの割合です。最初の月は再発率が約 38% でしたが、半年運用したあとには 9% まで下がりました。同じ転び方を繰り返さないことが、トータルのコストを最も大きく押し下げます。

逆に「初めて見る失敗」は依然として一定数発生します。これは仕方ないと割り切って、観測係がきちんと記録してくれることに信頼を置いています。新しい失敗を学習する伸びしろがある以上、エージェントの運用は終わりません。

個人開発で「失敗の共有資産化」を急がない

最後に、私の意見を一つ書きます。失敗履歴の仕組みを作るとき、つい「会社全体・チーム全体の共有資産にしたい」と考えがちですが、個人開発では急ぐ必要はありません。

理由は二つあります。第一に、個人の failures.jsonl は自分の環境・自分の癖に強く依存しているため、他人にとってノイズになる確率が高いです。第二に、共有資産化のメンテナンスコストは思ったより重く、個人開発者の時間を奪います。

まずは自分のためだけの failures.jsonl を作って三ヶ月運用してみてください。半年後に、この中の一部だけを「他人にも有用そう」と判断して切り出せばいいです。順序を逆にすると、共有のための仕組み作りに時間を取られて、肝心の自分のエージェントが賢くならないままになります。

次の最小の一歩

明日、Antigravity でエージェントを動かす前に、プロジェクトのルートに空の failures.jsonl を作ってみてください。そして、その日に発生した失敗を一件だけ手動で書き加えてみます。書式はこの記事のままで構いません。一週間続けてみると、自分のエージェントがどこで詰まる癖があるかが見えてきます。観測係や圧縮スクリプトはそのあとで作っても遅くありません。

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Agents & Manager2026-04-27
Antigravity を個人開発の「夜のもう1人」として迎え入れる運用モデル
Antigravity のエージェントを、個人開発者にとっての「夜のもう1人」として運用するための設計指針。タスクの渡し方・境界線の引き方・朝に何をレビューするかまで、実際に運用して整えてきた手順を共有します。
Agents & Manager2026-07-16
作業中のエージェントに、次の指示をいつ渡すか — 待つ・割り込む・積むを実運用で測りました
Antigravity v2.3.0 で入ったメッセージのキューイングと Send Now。待つ・割り込む・積むの三択を同じ物差しで測り、積んだ指示が古くなる問題と、前提スタンプで手戻りを22%から9%へ下げた記録をまとめました。
Agents & Manager2026-07-12
Antigravity のエージェントに任せる作業と任せない作業を2週間の運用で見直す
個人開発の日々のタスクを2週間ほど Antigravity のエージェントに任せてみて、任せて正解だったものと手元に残すべきだったものの線引きを、運用ログを添えて振り返ります。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →