Max Nardit
← 記事
11 mindev

Claude Managed Agents の dynamic workflows:ファンアウトはエージェントが書く、だから予算を先に決める

新しい multiagent タイプではスイッチが最初からオンで、ラン開始を承認する仕組みはなく、唯一の金額上限はセッション作成時にしか付けられません。ドキュメントをもとにした設定ガイドです。最初のメッセージを送る前に決めておく 3 つの設定を扱います。

目次

10 月 9 日から、Claude Managed Agents のエージェントはワークフローを書けるようになりました。多数のエージェントをフェーズごとに動かし、返ってきた結果をまとめるプログラムです。サーバーはこれをワークフローランとしてバックグラウンドで実行します。この機能は managed-agents-2026-04-01 ヘッダーのもとでベータ提供されていて、新しい multiagent タイプ multiagent_20261001 と一緒に登場しました。

自分の API キーでは実行していません。以下はすべて 2026 年 10 月 13 日時点のドキュメントに基づく内容で、自分の解釈を書くところではそう明記します。設定そのものは短く済みます。難しいのは、重要な設定を最初のメッセージの前に選んでおく必要があること、金額上限を後から追加できないこと、そしてその後の作業計画はモデルが書き、こちらからは見えないことです。

Claude Managed Agents の dynamic workflow は何をするのか

オーケストレーションを会話の外に出し、モデルが書いたコードに移します。サブエージェントの場合、エージェントはタスクを委任し、報告を読み、次の手を自分で決めます。ワークフローでは、それをプログラムが行います。エージェントを起動し、それぞれの結果を集め、結果を別のエージェントに渡し、ステップを繰り返し、どれかが失敗したときの対応を決めます。結果が届く先はプログラムで、セッションが動かしているエージェントではありません。そのエージェントは手が空いたままなので、ユーザーと話すことも、ターンを終えることもできます。

ラン内の各エージェントは、専用のセッションスレッドで動きます。会話履歴はスレッドごとに別で、サンドボックスはセッションで共有されます。つまり、どのスレッドからも同じファイルが見えます。ドキュメントは、複数のエージェントが必要な作業のほとんどにワークフローを勧めていて、例として監査、マイグレーション、ディープリサーチ、クロスチェックを挙げています。

Claude Managed Agents の dynamic workflows を有効にする方法と、オフのままにする方法

エージェントの multiagent ブロックを新しいタイプに設定します。リリースノートには明示的な形が載っています。

json
{
  "multiagent": {
    "type": "multiagent_20261001",
    "workflows": { "type": "enabled" }
  }
}

ただし、有効にしているのは workflows の行ではありません。このタイプでは workflows と subagents がどちらもデフォルトで有効で、それぞれの inline_agents も有効です。inline_agents があると、エージェントやワークフローがその場でエージェントを定義できます。タイプだけを書いたブロックでも、これが全部付いてきます。

いちばん効いてくるのは移行のときです。エージェントを古い coordinator タイプから移すと multiagent ブロック全体が置き換わり、書かなかった項目はデフォルト値になります。こちらで列挙した 2 つのサブエージェントにしか委任できなかったエージェントが、更新後はワークフローランを開始でき、サブエージェントを自分で定義できるようになります。どちらかをオフのままにするには、同じ更新でその項目に {"type": "disabled"} を送ります。null を送ると、見た目とは逆の結果になります。デフォルトに戻り、そのデフォルトは有効だからです。

同じセクションには、小さな落とし穴がもう 2 つあります。セッションは作成時に設定をコピーするので、エージェントを変更しても既存のセッションは変わりません。また、ツール名の接頭辞 ant__ は予約済みになりました。この接頭辞で始まる名前のカスタムツールを持つエージェントは、ツールの名前を変えるまで更新のたびに 400 で失敗します。

Claude Managed Agents のワークフローランをいつ開始するかは誰が決めるのか

エージェントが決めます。ほかの誰にも確認は求められません。ランを開始する API 呼び出しはありません。user.message で作業を説明すると、ランを開始するかどうか、いつ開始するかはエージェントが判断します。ドキュメントはこれを一文で述べています。

Permission policies apply to the tools that a run's agents call, not to
starting the run.

こちらが使える手段は文章です。ドキュメントの指示例では、契約書レビューのエージェントに対して、契約書が数件を超えるならランを開始し、1 件か 2 件なら自分で処理するように伝えています。作業の分け方、エージェントが失敗したときの対応、制限時間も書けます。

これはこの機能でいちばん弱い制御で、しかもドキュメントが頼っているのはまさにそこだ、というのが自分の見方です。エージェントのシステム指示に書いた指示は考慮されるだけで、強制はされません。プロンプトは不変条件ではない で書いた点です。今回は、あのエッセイがいちばん懸念しているケースに当たります。破られるとお金がかかるルールなのに、API にはゲートを置く場所がありません。ランを開始するツール呼び出しも見えません。最初の兆候はストリームに流れる workflow_run.created イベントです。つまり、ファンアウトを決めるのはモデルで、こちらはそれを後から知ります。歯止めになるのは、最初のメッセージの前に設定しておいたものだけです。

Claude Managed Agents のワークフローランが使える金額に上限をかける方法

セッション予算でかけます。設定できるのはセッション作成時だけです。ラン自体に料金はありません。ラン内のエージェントが使うトークンは、セッションのほかの部分と同じく、各モデルの料金で課金されます。金額の上限は予算ひとつだけで、その下にスレッド単位の上限はありません。

json
{
  "agent": "$AGENT_ID",
  "environment_id": "$ENVIRONMENT_ID",
  "budget": {
    "type": "limit",
    "max_list_cost": { "amount": "2000", "currency": "USD" }
  }
}

金額は US セント単位の整数を文字列で書くので、"2000" は 20 ドルです。上限が期待どおりに働くかどうかは、4 つの細部で決まります。まず、後から追加できません。予算なしで作成したセッションに予算を追加しようとすると 400 が返り、予算の削除も一方通行です。次に、計算は契約価格ではなく定価で行われ、セッションの稼働時間と Web 検索も含まれます。3 つ目に、厳密な停止ではありません。各スレッドはすでに始めたモデルリクエストを最後まで実行し、1 つのランでは 64 スレッドが同時に動くことがあります(API が保証している数字ではありません)。そのため超過分は、動作中のスレッド 1 本につき最大 1 リクエストです。最後に、上限に達するとセッションは budget_reached でアイドルになり(ツール呼び出しがクライアントの応答をまだ待っている場合は requires_action)、予算を引き上げるか削除するまで user.message を拒否します。その間も一時停止したランの存続時間は進むので、ランが待っているうちに timeout_error で終わることがあります。

そのほかの上限は、どれも数の上限です。1 つのランの存続期間中に起動できるエージェントは 1,000、存続時間はエージェントが短く設定しないかぎり 24 時間、1 セッションで同時に開けるランはデフォルトで 10 件です。このうち金額で決まるものはひとつもありません。

コストに関わるもうひとつの設定はモデルです。インラインエージェントは、セッションが動かしているエージェントのモデルを使います。最大のモデルで動くエージェントは、最大のモデルでファンアウトします。ランの一部に安いモデルを使う方法としてドキュメントにあるのは、そのエージェントを自分で作成し、workflows.predefined_agents に列挙することです。Claude Code 自身の Workflow ツールには、同じ日にそのための環境変数が追加されました。v2.1.296 の CLAUDE_CODE_WORKFLOW_SUBAGENT_MODEL です。Managed Agents では、エージェントのリストを使います。

Claude Managed Agents のワークフローランを追い、完了を知る方法

セッションのイベントストリームで workflow_run.* イベントを読みます。created(ランの名前と宣言されたフェーズ付き)、status_running、status_idle、phase_started、phase_ended、status_ended、error です。作業が終わったと言えるのは、2 つの条件がそろったときです。作成を確認したすべてのランに workflow_run.status_ended が届いていること。そしてその後に、自分のリクエストが原因ではない end_turn 付きの session.status_idle が届くこと。インタラプトの後は、次の user.message に続くアイドルだけが数に入ります。アイドル単独では何の証明にもなりません。ランが一時停止すると、ランが開いたままでもセッションはアイドルになります。さらに、エージェントは結果を読んだ時点で別のランを開始できます。

ランのイベントは webhook を発火しません。新しい接続では見逃した分が再送されず、ランを一覧するエンドポイントもありません。再接続後は、セッションのイベントを一覧して状態を組み立て直します。また、セッションが running のまま、ランのスレッドがクライアントからのツール確認を待つことがあります。イベントが届いたらその場で応答してください。確認が遅すぎた場合も 200 が返りますが、ドキュメントの言葉では、それはツールが実行されたという意味ではありません("doesn't mean that the tool ran")。

ランを止めるには、エージェントに頼みます。こちらから送るイベントでランを終了させるものはありません。user.interrupt はエージェントのターンを止めるだけで、ランは終了しません。エージェントにランの停止を頼む user.message を送ります。セッションをアーカイブしてもランは終了しますが、ランが開いている間はアーカイブが 400 を返すことがあります。ドキュメントにあるのは、停止を頼み、各ランの status_ended を待ち、それからアーカイブする、という順序です。

"completed" は Claude Managed Agents のワークフローランの成功を意味するのか

意味しません。ドキュメントがはっきりそう書いています。

The workflow finished running. The result doesn't say whether the work
passed. A run can end completed even though work on its threads failed, or a
thread couldn't be created.

失敗した作業を見つけるには、ランの各スレッドのイベントを読みます。失敗時の結果も具体的ではありません。program_error は原因を示しません。ワークフローのコードも、ランを管理するツール呼び出しも、各スレッドがプログラムに返した結果も見えません。ドキュメントは、ランの後でエージェントにワークフローを一字一句そのまま出力させることを勧めています。それは、何を実行したかについてのモデル自身の説明です。読む価値はありますが、ログではありません。

ワークフローランのページにあるもう一文は、設計に入れておく価値があります。"A run can create more than one thread for the same piece of work, so make the tools your agents call safe to call twice." ランは同じ作業に対して複数のスレッドを作ることがあるので、エージェントが呼ぶツールは 2 回呼ばれても安全にしておくように、という内容です。どのくらいの頻度で起きるかについて、ドキュメントは何も約束していません。自分はこれを、あなたのマルチエージェントシステムは分散システムです で書いた at-least-once の問題として読んでいます。再発行されうる作業は、2 回実行しても安全でなければなりません。この呼び名を付けたのは自分です。ツールを 2 回目の呼び出しに耐えるようにせよという指示は、ベンダーのものです。

あの記事での自分のルールは、成功のシグナルは成果物から取り、作業したエージェントの手が届かないもので確認する、というものでした。これは今回も有効で、適用する場所は共有サンドボックスです。これは自分の提案で、未検証ですが、システム指示でワークフローに作業単位ごとに結果ファイルを 1 つ書かせ、そのファイルをランの外から自分で数えて中身を確認します。ドキュメントの例にあるような締めの要約 "41 of the 300 contracts have one," は、こちらが読んでいないスレッドについての主張です。

無人作業で Claude Managed Agents のワークフローを有効にする前に設定しておくこと

設定が 3 つ、習慣が 3 つです。予算はセッション作成時に設定し、スレッドごとの超過を見込んだ額にします。後から追加できないからです。workflows の下の inline_agents を無効にし、ランが使ってよいエージェントを列挙します。インラインエージェントは現在、セッションのエージェントのツール、MCP サーバー、スキルをすべて受け取ります(API が保証しているのはその一部だけです)。ドキュメントによると、自分で定義したエージェントのようには制限できません。ワークフローだけを使いたいなら、subagents を明示的に無効にします。書かずにおくと有効になるからです。セッションは作成時にエージェントの multiagent 設定をコピーします。

習慣のほうはフィールドではありません。ランのエージェントが呼べるツールは、すべて 2 回呼ばれても安全にしておきます。ランを開始する場合としない場合をシステム指示に書き、それはあくまで目安として扱います。まとめられた結果は、信用する前にランの外から確認します。

2 つ目と 3 つ目の設定を行うブロックを、ドキュメントにあるフィールドから組み立てるとこうなります。

json
{
  "multiagent": {
    "type": "multiagent_20261001",
    "subagents": { "type": "disabled" },
    "workflows": {
      "type": "enabled",
      "inline_agents": { "type": "disabled" },
      "predefined_agents": [
        { "type": "agent", "id": "agent_01Lm4cV8yQ2tNs7XbKdR5h", "version": 2 }
      ]
    }
  }
}

これらのエージェントが呼ぶツールには、ランの中でも権限ポリシーがそのまま適用されます。そのため、web_fetch の変更 で取り上げたデフォルトは、ワークフローが作るすべてのスレッドに当てはまります。同時に最大 64 本です。

ドキュメントと意見が分かれるのは「ほとんど」という言葉です。ワークフローが合うのは、分け方が事前にわからず、各部分が独立している場合です。分け方がすでにわかっているなら、自分で書いたスクリプトのほうが、実行前に読める場所に計画を置いておけます。サブエージェントのリストなら、各ステップを決めるのはやはりエージェントですが、少なくとも誰を呼べるかは固定できます。ワークフローでは、計画は実行時にモデルが書き、後から頼んだときにだけ見せてもらえます。

01 / ディスカッション

コメント欄はありません。議論は X で行っています。

Max Nardit@mnardit

02 / ほかの記事

  1. Codex CLI のマネージド Git worktree: 始め方は 3 通り、モデルが呼ぶツールだけはリモートのデフォルトブランチから始まります

    Codex CLI 0.162.1 を使い捨てのリポジトリで実際に動かした記録です。チェックアウトがどこに作られるか、入口ごとにどのコミットから始まるか、.env と未コミットの編集がなぜ元の場所に残るか、作業をどうマージして戻すか、後片付けでディスクに何が残るかを確かめました。

  2. サプライチェーンとしての Claude Code スキル: 220 万件の採用、レジストリなし、スキャナーがソースを読む一方で Python はキャッシュを実行する

    スキルは実行する前に読む、というのが定番の助言ですが、この助言には穴が 2 つあります。コピーしたスキルには更新の経路がないため、読んだコピーは知らないうちに元のスキルとずれていくことがあります。そして Python を同梱するスキルでは、読んだファイルとインタープリターが読み込むファイルが同じとは限りません。

  3. Claude Code vs Codex: どちらかを選ばず、開発者が 2 つに仕事を振り分ける 7 つの方法

    受け渡しの手段は、いまではベンダー自身が文書化しています。レビューコマンド、セッションの転送、双方向のインポーターです。一方、どの仕事をどちらに任せるべきかは、どこにも書かれていません。7 つの分担を出どころまでたどり、「文書化済み」か「報告」かを付けて紹介します。あわせて、既定値が異なるサンドボックスと、今年削除された連携も取り上げます。