「AIに任せておけばなんとかしてくれる」— そう思いがちですが、実際にエージェントをプロダクションで動かそうとすると、壁が次々と現れます。
コードがエラーを吐いて止まる。コンテナが突然死ぬ。セキュリティトークンが漏れる。コンテキストが溢れてAIが混乱する。そして何より、失敗したときにどう復旧するのかが設計されていないと、エージェントは本番環境では使い物になりません。
Anthropicのエンジニアリングチームが公開した記事「Scaling Managed Agents」は、この問題に対する彼らの解決策を詳しく解説しています。そのエッセンスを、開発者向けにかみ砕いて紹介します。
多くのエージェント実装は、ひとつのコンテナ(あるいはひとつのプロセス)に全部詰め込む設計になっています。AIモデルの呼び出し、コード実行、ファイル管理、認証…全部ひとまとめ。
インフラ界隈で有名な「Pets vs Cattle」のたとえです。
全部入りコンテナはPetです。状態が全部その中にあるから、壊れたら最初からやり直し。
Anthropicが直面したのも同じ問題でした。コンテナがクラッシュした瞬間、AIの「記憶」も「進捗」も「認証情報」も全部失われる。これはプロダクションでは許容できません。
解決策はシンプルかつ強力です。「考える部分」と「作業する部分」を切り離す。具体的には、3つの抽象レイヤーに分割します。
┌─────────────────────────────────────────────┐
│ Session(セッション) │
│ → 追記のみのイベントログ。完全な履歴。 │
│ → 破棄しない。セッション=真実の源泉。 │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Harness(ハーネス) │
│ → Claudeを呼び出すループ。 │
│ → セッションからコンテキストを取り出して渡す。 │
│ → ステートレス。いつでも再起動OK。 │
└──────────────────┬──────────────────────────┘
│ execute(name, input) → string
┌──────────────────▼──────────────────────────┐
│ Sandbox(サンドボックス) │
│ → コード実行環境(コンテナ等)。 │
│ → 使い捨て。壊れてもharnessが新しいのを作る。 │
└─────────────────────────────────────────────┘
harnessはコンテナを直接管理しません。コンテナは単なるexecute(name, input) → stringという関数として扱います。
コンテナが死んだら? harnessがエラーをキャッチ → Claudeに「失敗したよ」と伝える → Claudeが再試行を決める → 新しいコンテナをプロビジョニング。全部自動。
この設計の美しさは、「どこが壊れても復旧できる」こと。サンドボックスは使い捨てだし、harnessはステートレスだからいつでも作り直せる。セッションは追記-onlyだから壊れない。各レイヤーが独立しているから、どこかが落ちても全体は回復できるのです。
AIエージェントのセキュリティで一番怖いのは、AIが認証情報にアクセスできてしまうこと。サンドボックス内でコードを実行するということは、理論上そのコードは何でもできるということ。そこにAPIキーやOAuthトークンが置いてあったら…
git clone)にだけ使う。サンドボックス内からは見えない。初期化が終わったらトークンは消える。認証情報はサンドボックスに置かない。これは譲れないライン。
ここ、意外と誤解されがちですが超重要です。
セッションとコンテキストウィンドウは別物です。
つまり、harnessの仕事は「セッション(巨大なログ)から、今のClaudeのコンテキストに収まる分だけをうまく切り出して渡す」こと。これをgetEvents()で位置ベースのスライス取得で実現しています。
// セッションは追記型の完全ログ
session.append(event) // 追記だけ。編集・削除はしない
// harnessがセッションから必要な分だけ取り出す
const context = session.getEvents({ after: cursor })
// Claudeのコンテキストに収まるように調整して渡す
harness.callClaude(context)
この設計のおかげで、長時間動くエージェントでも「途中で記憶を失う」ことがありません。セッションは全部残っているので、いつでも必要な部分を再構成できるのです。
脳と手を分離すると、スケーリングも自然に解決します。
なぜこれだけ速くなるのか。harnessはステートレスなので、複数のharnessを同時に起動できます。しかもコンテナは必要な時だけプロビジョニングするから、リソースの無駄もありません。
このアーキテクチャを「多脳・多手」と表現しています:
execute(name, input) → stringというインターフェースさえ満たせば、何でも「手」として扱える。// 手は何でもいい。インターフェースさえ合えば。
execute("docker-container", code)
execute("android-emulator", tapCommand)
execute("browser", navigateAction)
execute("smartphone", swipeGesture)
// 全部 string → string だから統一的に扱える
Anthropicの設計思想の根底にあるのは、OSがハードウェアを抽象化して半世紀以上生き残ったのと同じ発想です。
execute(name, input) → stringという契約は明確。これに従えば何でも「手」になれる。「まだ思いついていないプログラム」のためにシステムを設計する。これが、拡張性の真の意味です。
このアーキテクチャの先には、harness自体もツールとして扱う「メタハーネス」の世界が見えてきます。harnessを管理するharness。脳を束ねる脳。そうなると、エージェントの能力は組み合わせで無限に広がっていくことになります。
AIエージェントを本気でプロダクションに届けたいなら、「全部入り」から脱却して、脳と手を分ける設計を検討してみてはいかがでしょうか。