◉CLAUDE LABEN
●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/API & SDK
⬡ API & SDK/2026-05-31上級

再現できないエージェント障害をなくす設計 — 決定論的リプレイとイベントソーシング

深夜に一度だけ失敗した自律エージェントの障害は、そのまま再実行しても再現できません。モデル出力やツール入出力といった非決定の境界をイベントログに記録し、決定論的にリプレイして原因を特定する設計を、スキーマ定義から録音再生ラッパー、実行単位のコスト配賦まで実装コードとともに解説します。

Claude Agent SDK13イベントソーシングオブザーバビリティ本番運用36リプレイ

✦ プレミアム記事

2014年から個人でアプリを開発してきて、累計5,000万ダウンロードを超えるまでに一番こたえたのは、派手なクラッシュではありませんでした。誰も見ていない深夜に、バックエンドの自律処理が一度だけ静かに失敗し、朝になってログを開いても「なぜそうなったのか」がもう分からない、という種類の障害です。

Claude Agent SDK で自律エージェントを本番に置くと、この問題がはっきり形を変えて現れます。エージェントは外部の状態に深く依存して動きます。モデルの出力は毎回わずかに違い、ツールが叩く API のレスポンスは時間とともに変わり、Date.now() は当然進み、リトライの分岐は乱数やレイテンシで変わります。つまり、失敗した実行をそのまま「もう一度走らせる」だけでは、二度と同じ失敗にたどり着けません。

両家の祖父がともに宮大工で、組み上げたものが何十年も保つのを近くで見て育ちました。長く保つものには必ず「後から検証できる」という性質が備わっています。エージェントの設計でも私が一番大事にしているのはここで、これからお伝えするのは、失敗を後から正確に再現するための設計、すなわち決定論的リプレイ(deterministic replay)とイベントソーシングを、実装と運用の両面から具体に落とした手順です。

なぜ「もう一度走らせる」では再現できないのか

再現を妨げる原因は、エージェント実行のなかに散らばった「非決定の境界(nondeterminism boundary)」です。コードのロジック自体は決定論的でも、外界に触れる瞬間だけは毎回違う値が入ってきます。本番で観察してきた限り、境界は次の4種類に集約できます。

第一にモデル出力です。temperature: 0 でも完全な再現は保証されず、ツール呼び出しの引数が1文字違うだけで分岐が変わります。第二にツールの入出力で、外部 API・データベース・ファイルの状態は時間とともに変化します。第三に時刻で、Date.now() や日付に基づく分岐は実行のたびに別の枝へ進みます。第四に乱数とリトライで、ジッター付きバックオフやサンプリングは実行ごとに揺れます。

ここで多くの人がオブザーバビリティ基盤(メトリクス・トレース・ダッシュボード)を入れて満足してしまいますが、それは「何が起きたかの統計」を見るものであって、「特定の1回をもう一度動かす」ものではありません。事後分析に本当に必要なのは後者です。発想を変えて、これら4つの境界を通過する値をすべて追記専用ログに記録し、再実行時にはログから読み戻すようにすれば、実行は決定論的に再現できます。これがイベントソーシングをエージェントに適用するという考え方です。

イベントログのスキーマを決める

まず、1回の実行を一意に識別する runId を発番し、その実行が境界を通過するたびに連番 seq 付きのイベントを追記します。イベントは「録る(record)」モードでは実値を書き込み、「再生(replay)」モードでは読み戻すという、対称な構造にしておくのが要点です。

// events.ts — 追記専用イベントの型と最小ストア
export type BoundaryKind = "model" | "tool" | "clock" | "random";
 
export interface AgentEvent {
  runId: string;
  seq: number;            // 実行内で単調増加
  kind: BoundaryKind;
  key: string;            // 呼び出しの論理キー(例: "tool:fetch_orders")
  input: unknown;         // 録音時の入力(照合に使う)
  output: unknown;        // 境界が返した実値
  tokensIn?: number;      // model イベントのみ
  tokensOut?: number;
  costUsd?: number;
  ts: string;             // ISO8601。clock の真値ではなく記録時刻
}
 
export interface EventStore {
  append(e: AgentEvent): Promise<void>;
  load(runId: string): Promise<AgentEvent[]>;
}

実運用では EventStore を追記専用に保つことが命綱です。途中で書き換えると再現性が壊れます。私は本番では1行1イベントの JSON Lines をオブジェクトストレージに置き、開発では単純な配列で持つ、という二実装で運用しています。スキーマには必ず kind と key を持たせてください。後述するリプレイで「同じ順序・同じ呼び出し」であることを照合する鍵になります。

✦

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

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦非決定の境界(モデル出力・ツールI/O・時刻・乱数)を特定し、追記専用イベントログとして記録する具体実装
✦失敗した1回の実行だけをオフラインで決定論的に再現するリプレイハーネスのコード
✦同じログからコストとトークンを実行単位で配賦し、事後分析を定量化する運用手順
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

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

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

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

関連記事

⬡ API & SDK2026-05-20
Claude Agent SDK で複数 MCP サーバを束ねるときのツール名衝突 — 名前空間と動的調停の設計
GitHub MCP と Linear MCP の create_issue が同居したとき、Sonnet 4.6 はどちらを呼ぶか分かりません。複数 MCP を束ねる Claude Agent SDK アプリで踏むツール名衝突の構造、TypeScript で書ける Reconciler の実装、そして本記事に最初に載せた schemaHash が5種類のスキーマ変更を全て見逃していた実測と訂正までをまとめます。
⬡ API & SDK2026-05-24
Claude API のレスポンスを Cloudflare R2 にアーカイブする実装メモ — 監査・再現性・障害分析の3軸設計
Claude API のリクエストとレスポンスを Cloudflare R2 に保存して、監査・障害分析・本番リプレイの3つに使う設計を、Workers の waitUntil パターンと D1 メタデータインデックス込みで実装メモにまとめました。
⬡ API & SDK2026-05-05
Claude API 拡張思考を本番導入して見えたコストの現実 — タスク別の費用対効果と使い分け判断基準
拡張思考(Extended Thinking)を本番環境で3ヶ月運用し、タスク別のコスト・精度・速度を計測した実データを公開します。費用対効果マトリクスによる使い分け判断フロー、モデル選択との組み合わせ、思考トークンが効く場面と不要な場面の見極めまで、実測値に基づいて解説します。