---
title: ワークフロー実行
url: https://platform.claude.com/docs/ja/managed-agents/workflow-runs
description: エージェントのワークフロー実行を追跡します。実行の状態とイベント、作業が完了するタイミング、実行が開いている間のリクエスト、予算、制限について説明します。
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

「**workflow**」（**ワークフロー**）とは、エージェントが多数のエージェントを実行し、それらが返す結果を組み合わせるために書くプログラムです。「**workflow run**」（**ワークフロー実行**）とは、1つのワークフローの実行です。**[Dynamic workflows](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration#dynamic-workflows)**（動的ワークフロー）は、エージェントがワークフローを書き、実行を開始できるようにする機能です。この機能は、エージェントの `multiagent` (csharp, go: `Multiagent`) ブロックにある `workflows` (csharp, go: `Workflows`) 設定でオンまたはオフにします。

サーバーはワークフローをバックグラウンドで実行します。そのエージェントは、ワークフローが必要とするたびにサーバーが作成する[セッションスレッド](https://platform.claude.com/docs/ja/managed-agents/session-threads)で作業します。実行はセッションの[イベントストリーム](https://platform.claude.com/docs/ja/managed-agents/events-and-streaming)で追跡します。実行を停止するには、エージェントに停止するよう依頼してください（[実行が開いているセッションを中断する](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#interrupt-a-session-with-runs-open)を参照）。

## 動的ワークフローの仕組み

セッションが実行するエージェントは、あなたが説明する作業に合わせて各ワークフローを書きます。ワークフローはプログラムです。他のエージェントを実行し、それぞれが返すものを収集し、結果を組み合わせます。これにより、エージェントは数百件のドキュメントのレビューなど、1つの会話には大きすぎるタスクに取り組むことができます。実行中、エージェントは作業を続けることも、ターンを終了することもでき、実行の状況を確認することもできます。

<Frame>
  ![ワークフロー実行（workflow run）の階層：実行、その2つのフェーズ（phase）、および各フェーズ内のエージェントスレッド（agent thread）。あるフェーズの結果は次のフェーズに渡されます。](https://platform.claude.com/docs/ja/images/workflow-anatomy.svg)
</Frame>

この図は一例を示しています。エージェントが書く各ワークフローには、それぞれ独自のフェーズとエージェントがあります。実行には次の階層があります。

* **ワークフロー実行：** サーバーはワークフローを1つのワークフロー実行としてバックグラウンドで実行します。1つのセッションで複数の実行を同時に開いておくことができます。
* **フェーズ：** ワークフローは作業を「phase」（フェーズ）に分割できます。フェーズとは、「Read the contracts」（契約書を読む）のような、実行の名前付きの段階です。実行の進捗は、そのフェーズイベントで追跡します。
* **エージェントスレッド：** フェーズ内で、プログラムはエージェントを実行します。各エージェントは、プログラムが書いたプロンプトに基づいて、それぞれ独自の[セッションスレッド](https://platform.claude.com/docs/ja/managed-agents/session-threads)で作業します。実行内のエージェントは、プログラム自身が定義するインラインエージェントか、あなたが [`workflows` (csharp, go: `Workflows`) の `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) リスト](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration#predefined-and-inline-agents)に列挙する事前定義エージェントのいずれかです。各スレッドが示す内容については、[実行のスレッド](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#a-runs-threads)を参照してください。

プログラムは次のことができます。

* **エージェントを同時に実行する：** プログラムは多数のエージェントを同時に実行できます。これを「fanning out」（ファンアウト）と呼びます。図では、最初のフェーズで3つのエージェントが契約書を読んでいます。
* **あるエージェントの結果を別のエージェントに渡す：** 各エージェントは結果をプログラムに返します。プログラムはその結果を別のエージェントに渡すことができます。図では、2番目のフェーズのエージェントが、最初の3つが返したものを使って作業します。実行のエージェントは、セッションのサンドボックス内で同じファイルも扱います。
* **次のステップを自ら進める：** エージェントの結果は、セッションが実行するエージェントではなく、プログラムに渡されます。プログラムは次にどのエージェントを実行するかを決定し、そのプロンプトを書きます。
* **繰り返しと選択：** フェーズ内で、プログラムは作業を繰り返し、エージェントが返したものに基づいて次のステップを選択できます。たとえば、レビューに合格するか、設定された回数を使い切るまで、下書きを修正させることができます。図では、プログラムは2番目のフェーズ内でステップを繰り返すことができます。
* **失敗したエージェントを処理する：** エージェントの1つが失敗すると、サーバーは通常、実行の他のエージェントが作業を続けている間に、そのエージェントを新しいスレッドでもう一度実行します。再び失敗した場合、プログラムはその失敗を処理するか、それによって実行を終了させることができます。プログラムが失敗を処理した場合でも、実行は `completed` で終了することがあるため、セッションが実行するエージェントに、何が失敗したかを報告するよう指示してください。

実行が終了すると、セッションが実行するエージェントは、実行が何をしたかを読むためのターンを得ます。その後、あなたに回答するか、別の実行を開始できます。そのターンが後になる場合や来ない場合については、[実行イベント](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#run-events)に記載されています。

実行が作業をどのように行うか、たとえば作業をどのように分割するか、エージェントが失敗したときに何をするかを指示できます。[実行を使用するタイミングをエージェントに伝える](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration#tell-the-agent-when-to-use-a-run)を参照してください。

実行が開始される前に承認ステップはありません。エージェントは、ワークフローを書いたのと同じターンで実行を開始します。先に計画をレビューするには、実行内容を説明してあなたの許可を待つようエージェントに指示してください。実行が開始されると、`workflow_run.created` にその名前、説明、フェーズが表示されます。承認していない実行が開始された場合は、エージェントに停止するよう依頼してください（[実行が開いているセッションを中断する](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#interrupt-a-session-with-runs-open)を参照）。

## 実行の状態遷移

<Frame>
  ![ワークフロー実行（workflow run）の状態：running（実行中）、idle（アイドル）、ended（終了）、および実行をある状態から別の状態に移すもの。](https://platform.claude.com/docs/ja/images/workflow-run-states.svg)
</Frame>

実行は、実行中またはアイドル状態で開始します。たとえば予算に達すると、実行中の実行は一時停止してアイドル状態になります。その後、予算を引き上げるか削除すると、中断によっても一時停止している場合を除き、再び実行されます。実行中の実行は、ワークフローが完了したとき、エージェントが実行を停止したとき、実行が失敗したとき、有効期間が過ぎたとき、またはセッションがアーカイブされたときに終了します。アイドル状態の実行も、たとえばエージェントが実行を停止したときやセッションがアーカイブされたときに終了することがあります。

実行は、実行中かアイドル状態かにかかわらず、`workflow_run.created` イベントから `workflow_run.status_ended` イベントまでの間、**open**（開いている）状態です。実行は、たとえばセッションの予算に達して一時停止している間、アイドル状態になります。実行には[有効期間](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#limits)があり、エージェントは実行を開始するときにそれを設定できます。実行がクライアントを待っている時間も、その有効期間に含まれます。一時停止しても実行の有効期間の経過は止まらないため、一時停止したままの実行は `timeout_error` で終了することがあります。次のイベントは、実行の開始、フェーズ、および終了を報告します。予算での一時停止でもイベントが1つ送信されます。中断後の一時停止では、イベントが送信されない場合があります。すべての `workflow_run.*` イベントには `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) が含まれ、これが `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) になるのは、実行が作成されなかった場合の `workflow_run.error` のみです。

## 実行イベント

実行イベントは、プライマリスレッドのストリームであるセッションのイベントストリームに届き、セッションのイベントを一覧表示した場合にも返されます。実行イベントは[webhook](https://platform.claude.com/docs/ja/managed-agents/webhooks)をトリガーしません。実行のスレッドからのステータスイベントも同じストリームに届きます。各イベントは `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) でそのスレッドを示し、実行のスレッドとは、`session.thread_created` イベントにその実行の `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) が含まれていたスレッドです。

| イベント                                                    | 届くタイミング                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | 対応                                                                                                                                                                                                                                                                                                                                                                     |
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workflow_run.created`                                  | エージェントが実行を開始しました。`workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`)（`wrun_…`）、実行の `name` (csharp, go: `Name`) と `description` (csharp, go: `Description`)、およびワークフローが宣言するフェーズである `phases` (csharp, go: `Phases`) が含まれ、各フェーズには `id` (csharp, go: `ID`)、`name` (csharp, go: `Name`)、`description` (csharp, go: `Description`) があります。ワークフローが何も指定しない場合、`description` (csharp, go: `Description`) は `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) です。`phases` (csharp, go: `Phases`) は常に存在し、空の場合もあります。実行とフェーズの `name` (csharp, go: `Name`) と `description` (csharp, go: `Description`) はモデルが書いたテキストであるため、あなたのリクエストの言葉を繰り返すことがあります。実行の `name` (csharp, go: `Name`) はサーバーが割り当てたものである場合もあります。 | 実行を開いているものとして追跡します。その `name` (csharp, go: `Name`) と、`phases` (csharp, go: `Phases`) に対する進捗を表示します。                                                                                                                                                                                                                                                                      |
| `workflow_run.status_running`                           | 実行の処理が始まったとき（`created` からしばらく後になることがあります）、および予算での一時停止後に再開するたびに届きます。中断後の再開では送信されない場合があります。アイドル状態で開始する実行は、先に `workflow_run.status_idle` を受け取る場合があります。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | 実行を実行中として表示します。                                                                                                                                                                                                                                                                                                                                                        |
| `workflow_run.status_idle`                              | 実行が、たとえばセッションの予算に達して一時停止しました。イベントは理由を示しません。中断後の一時停止では送信されない場合があります。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | 続行するには、[コストと予算](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#cost-and-budgets)または[実行が開いているセッションを中断する](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#interrupt-a-session-with-runs-open)を参照してください。                                                                                                                               |
| `workflow_run.phase_started`、`workflow_run.phase_ended` | ワークフローがフェーズに入ったか出たか、または実行の終了によってまだ開いていたフェーズが閉じられました。終了イベントは、フェーズの作業が完了したかどうかを示しません。どちらにも `workflow_run_phase_id` (java: `workflowRunPhaseId`; php: `workflowRunPhaseID`; csharp, go: `WorkflowRunPhaseID`) が含まれます。終了イベントには、それが閉じる開始イベントの `id` (csharp, go: `ID`) である `phase_started_id` (java: `phaseStartedId`; php: `phaseStartedID`; csharp, go: `PhaseStartedID`) もあります。どちらにもフェーズの名前はありません。`workflow_run.created` の `phases` (csharp, go: `Phases`) で `workflow_run_phase_id` (java: `workflowRunPhaseId`; php: `workflowRunPhaseID`; csharp, go: `WorkflowRunPhaseID`) によって検索してください。                                                                                                                                                                 | 進捗を更新します。フェーズは `phases` (csharp, go: `Phases`) の順序で一度に1つずつ、それぞれ最大1回実行されますが、API はこれを保証しません。フェーズの終了と開始は `phase_started_id` (java: `phaseStartedId`; php: `phaseStartedID`; csharp, go: `PhaseStartedID`) で対応付けます。完了する実行であっても、複数の開いているフェーズ、`phases` (csharp, go: `Phases`) にないフェーズ、および一覧にあるのに開始されないフェーズを処理してください。開始したすべてのフェーズは、実行の `workflow_run.status_ended` の前に終了もします。 |
| `workflow_run.status_ended`                             | 実行が終了しました。常に実行の `workflow_run.*` イベントの最後です。`result` (csharp, go: `Result`) が含まれます。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `result` (csharp, go: `Result`) を読みます（次の表を参照）。その後、エージェントは実行がどのように終了したかを読むためのターンを得ます。予算に達している場合、またはプライマリスレッドがクライアントを待っている間は、そのターンは後になります。中断後は、そのターンが来ない場合があります。その場合は `user.message` を送信するか、`result` (csharp, go: `Result`) を自分で読んでください。アーカイブまたは終了の後は、そのターンは来ません。                                                                                                        |
| `workflow_run.error`                                    | サーバーが実行のエラー、または拒否した開始を報告します。`error` で終了する実行は、`workflow_run.status_ended` の前に、同じエラーを含むこのイベントを受け取ります。`error` (csharp, go: `Error`) が含まれます。これは `type` (csharp, go: `Type`) と、ログに記録しても安全な `message` (csharp, go: `Message`) で構成されます。実行が作成されなかった場合、`workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) は `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) になります。                                                                                                                                                                                                                                                                                                                              | ログに記録し、実行の終了とは見なさないでください。`workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) が `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) の場合、実行は開始されていません。それ以外の場合は、`workflow_run.status_ended` まで実行の追跡を続けてください。                                                                                                |

| `result`                         | 意味                                                                                                                                                                                                                             |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `{"type": "completed"}`          | ワークフローの実行が完了しました。結果は、作業が成功したかどうかを示しません。スレッドでの作業が失敗した場合や、スレッドを作成できなかった場合でも、実行が `completed` で終了することがあります。失敗した作業を見つけるには、各[実行のスレッド](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#a-runs-threads)のイベントを読んでください。 |
| `{"type": "stopped"}`            | エージェントが実行を停止したか、セッションがアーカイブされました。イベントはどちらであるかを示しません。これらが唯一の原因であるとは見なさないでください。                                                                                                                                                  |
| `timeout_error` を伴う `error`      | 実行が[有効期間](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#limits)に達しました。有効期間はエージェントが設定できます。                                                                                                                   |
| `program_error` を伴う `error`      | ワークフローが失敗しました。そのコードが失敗したか、制限以外のワークフローのルールに違反しました。または、実行のスレッドの1つが失敗したか作成できず、ワークフローがそれによって実行を終了させました。                                                                                                                            |
| `thread_limit_error` を伴う `error` | 実行が[ワークフローが開始するエージェントの制限](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#limits)を超えました。                                                                                                                      |
| `unknown_error` を伴う `error`      | サーバーが実行を続行できなかったか、実行がワークフローに関するサーバーの他の制限のいずれかを超えました。                                                                                                                                                                           |

エラー結果は `{"type": "error", "error": {"type": "timeout_error", "message": "..."}}` のようになり、`message` はログに記録しても安全です。認識できない `result.type` は他の方法で終了した実行として、認識できない `error.type` はエラーとして扱ってください。モデル、MCP サーバー、認証情報、課金など、セッションが依存するものが失敗すると、失敗したスレッドのストリームが `session.error` を受け取ります。それだけでは実行は終了しません。しかし、それによって実行のスレッドの1つが失敗し、ワークフローがそれによって実行を終了させた場合、実行は `program_error` で終了します。

たとえば、[契約書レビューエージェント](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration#turn-on-dynamic-workflows)に、300件の契約書のうちどれに支配権変更条項があるかを尋ね、エージェントが実行を開始したとします。

1. `workflow_run.created` が実行に「Find change-of-control clauses」という名前を付け、`phases` (csharp, go: `Phases`) にフェーズ「Read the contracts」と「Reconcile the findings」を列挙します。続いて `workflow_run.status_running` が届きます。
2. フェーズイベントが各フェーズを示し、実行が作成する各スレッドは、実行の `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) を含む `session.thread_created` を送信します。
3. `workflow_run.status_ended` が `result: {"type": "completed"}` とともに届きます。
4. エージェントが「300件の契約書のうち41件にその条項があります」と回答し、`session.status_idle` が `end_turn` とともに届きます。

実行の最初のイベントは、そのフェーズを列挙します。

```json
{
  "type": "workflow_run.created",
  "id": "sevt_01abc...",
  "workflow_run_id": "wrun_01J8XkN5uT3vHpLqRfWdY2",
  "name": "Find change-of-control clauses",
  "description": "Reads each contract and lists those that have the clause.",
  "phases": [
    {
      "id": "wrph_01Kd3a1f3",
      "name": "Read the contracts",
      "description": "Reads each contract for the clause."
    },
    { "id": "wrph_01Kd3b7c9", "name": "Reconcile the findings", "description": null }
  ],
  "processed_at": "2026-10-09T14:01:45Z"
}
```

各フェーズイベントは、`workflow_run_phase_id` でフェーズを示します。これは `phases` 内の `id` ですが、API はこれを保証しません。

```json
{
  "type": "workflow_run.phase_started",
  "id": "sevt_01def...",
  "workflow_run_id": "wrun_01J8XkN5uT3vHpLqRfWdY2",
  "workflow_run_phase_id": "wrph_01Kd3a1f3",
  "processed_at": "2026-10-09T14:01:46Z"
}
```

実行の最後のイベントは、実行がどのように終了したかを報告します。

```json
{
  "type": "workflow_run.status_ended",
  "id": "sevt_01ghi...",
  "workflow_run_id": "wrun_01J8XkN5uT3vHpLqRfWdY2",
  "result": { "type": "completed" },
  "processed_at": "2026-10-09T14:09:12Z"
}
```

## 実行のスレッド

実行内の各エージェントは、ワークフローが必要とするたびにサーバーが作成する、それぞれ独自の[セッションスレッド](https://platform.claude.com/docs/ja/managed-agents/session-threads)で作業します。実行のスレッドは、他の子スレッドと同様に一覧表示、読み取り、ストリーミングでき、そのツール呼び出しにはプライマリストリームから応答できます。スレッドを停止するには、エージェントに実行を停止するよう依頼してください（[実行が開いているセッションを中断する](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#interrupt-a-session-with-runs-open)を参照）。

* **グループ化：** 実行のスレッドには、それを通知する `session.thread_created` イベントと同様に、実行の `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) があります。その他のスレッドと、それらを通知する `session.thread_created` イベントでは、`workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) が `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) に設定されています。
* **エージェント：** `agent` (csharp, go: `Agent`) は、スレッドが実行するエージェントを示します。`multiagent` (csharp, go: `Multiagent`) 内の [`workflows` (csharp, go: `Workflows`) の `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) リスト](https://platform.claude.com/docs/ja/managed-agents/multiagent-orchestration#turn-on-dynamic-workflows)に列挙したエージェントの場合、`agent` (csharp, go: `Agent`) には、列挙したサブエージェントのスレッドと同様に、そのエージェントの `id` (csharp, go: `ID`) と `version` (csharp, go: `Version`) があります。ワークフローが定義するエージェント（インラインエージェント）の場合、`agent` (csharp, go: `Agent`) の `type` は `inline` で、`id` (csharp, go: `ID`) や `version` (csharp, go: `Version`) はありません。セッションエージェントのものではなく、ワークフローが書いたシステムプロンプトを持ちます。また、ワークフローが付けた名前と説明も持ちます。ワークフローが名前を付けなかった場合は、サーバーが名前を割り当てます。セッションが実行するエージェントであるセッションエージェントのモデルを使用します。そのツール、MCP サーバー、スキルは、セッションエージェントのもののサブセットです。すべてを受け取りますが、API はこれを保証しません。そのツールは権限ポリシーを維持します。
* **スレッドが共有するもの：** 実行のスレッドはセッションのサンドボックスで作業するため、すべてのスレッドが同じファイルを扱います。これには、セッションがマウントするメモリストアのファイルも含まれます。ワークフローが定義するエージェントは、セッションが解決する認証情報を使用して MCP サーバーを使用します。各スレッドには独自の会話履歴があります。
* **イベント：** 実行スレッドの `session.thread_created`、`session.thread_status_running`、`session.thread_status_idle`、`session.thread_status_terminated` イベントは、プライマリストリームにも届きます（[実行イベント](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#run-events)を参照）。メッセージイベントは、そのスレッド自身のストリームにとどまります。スレッドの webhook は、他の子スレッドと同様に送信されます。スレッド自身のストリームが記録する内容については、[セッションスレッドのイベント](https://platform.claude.com/docs/ja/managed-agents/session-threads#session-thread-events)を参照してください。
* **フェーズ：** スレッドがどのフェーズで作業しているかを示すイベントやフィールドはなく、1つの実行のスレッドが同じ `agent_name` を持つこともあります。実行の進捗はフェーズイベントで追跡し、スレッドは `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) で区別してください。
* **アーカイブ：** サーバーは、遅くとも実行の終了までに各スレッドをアーカイブします。スレッドが結果を返した時点、または実行がそのスレッドを使い終えた時点で、より早くアーカイブすることもあります。その時点でスレッドがまだ実行中であるか、クライアントを待っている場合、サーバーはまずそれを停止します。アーカイブされたスレッドは、ステータス `terminated` でスレッド一覧に残ります。実行のスレッドを自分でアーカイブする必要はありません。
* **ツール：** 実行は同じ作業に対して複数のスレッドを作成することがあるため、エージェントが呼び出すツールは2回呼び出されても安全なものにしてください。

<Tip>
  エージェントに、あなたのリクエストのために書いたワークフローを出力するよう依頼できます。実行が終了し、セッションが `idle` になるまで待ちます。次に、実行を開始したワークフローを一字一句そのまま出力し、別の実行を開始しないようエージェントに依頼する `user.message` を送信します。

  ```text wrap
  Print the workflow that you started the run with, word for word, in one code block. Do not start another run.
  ```
</Tip>

## 作業が完了したタイミングを知る

実行が実行中の間は、どのスレッドも作業していないときでも、セッションは `running` のままであると想定してください。どのスレッドも作業しておらず、あるスレッドがクライアントを待っている場合、セッションは `requires_action` で `idle` になります。アイドルになっただけでは、作業が完了したことを意味しません。作業は、次の両方が満たされたときに完了します。

1. 作成を確認したすべての実行に `workflow_run.status_ended` がある。
2. その後、`stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) が `end_turn` の `session.status_idle` が届き、それが中断などのあなた自身のリクエストによって引き起こされたものではない。中断した後は、次の `user.message` または `user.define_outcome` の後に届くアイドルイベントのみを数えてください。

* **一時停止した実行：** 一時停止した実行はセッションを `running` に保たないため、実行がまだ開いている間にセッションがアイドルになることがあります。たとえば予算に達すると、セッションは `budget_reached` でアイドルになります。実行が終了するまで、作業は完了していません。
* **別の実行：** エージェントは結果を読んだときに新しい実行を開始できるため、再度確認してください。
* **アウトカム：** [アウトカムを定義した](https://platform.claude.com/docs/ja/managed-agents/define-outcomes)場合、実行が開いている間は、実行中かアイドル状態かにかかわらず、評価は開始されません。エージェントが実行の結果を読むターンで評価が開始されることがあります。
* **`retries_exhausted`：** エージェントのターンがエラーで失敗しました。再試行が尽きたか、課金の失敗など、再試行できないエラーです。このアイドルイベントが届いたときに、実行がまだ実行中である場合があります。実行が終了し、エージェントがまだその結果を読んでいない場合、サーバーはあなたからの入力なしで新しいターンを開始します。セッションは再び `running` になるため、次のアイドルイベントを待ってください。セッションがアイドルのままの場合は、その前に来た `session.error` を読み、原因を修正してください。その後、`user.message` を送信するか、各実行の `result` (csharp, go: `Result`) を自分で読んでください。

## 実行を追跡する

このサンプルは、あなたのメッセージからエージェントの回答までセッションを追跡します。ストリームを開き、メッセージを送信します。その後、次のことを行います。

* `workflow_run.created` から `workflow_run.status_ended` まで**各実行を追跡**し、各フェーズが開始するたびにそれを出力します。
* 各 `agent.custom_tool_use` が届いたときに**カスタムツール呼び出しに応答**します。実行のスレッドは、セッションが `running` のままでもクライアントを待つことがあるためです。エージェントのツールが[確認を求める](https://platform.claude.com/docs/ja/managed-agents/events-and-streaming#tool-confirmation)場合は、`evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`) が `ask` である各 `agent.tool_use` または `agent.mcp_tool_use` に応答する分岐を追加してください。すべての呼び出しを許可する分岐は `always_ask` を常に許可に変えてしまうため、サンプルにはそのような分岐はありません。
* [作業が完了](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#know-when-the-work-is-done)したとき、つまり開いている実行がなく、セッションが `end_turn` でアイドルになったときに**停止**します。セッションが終了した場合も停止します。`requires_action` 以外の停止理由（`budget_reached`、`retries_exhausted`、`refusal` など）を伴うアイドルイベントでは、理由を出力して停止するため、それらは独自のコードで処理してください。サーバーが自ら新しいターンを開始しようとしている場合でも、`retries_exhausted` で停止します。`requires_action` の場合、および実行が開いている間の `end_turn` の場合は、待機を続けます。

<CodeGroup exclude="shell">
  <CodeGroupItem language="cURL">
    このワークフローには、単一のシェルコマンドでは実現できないロジックが必要です。実行するには[Claude SDK](https://platform.claude.com/docs/ja/cli-sdks-libraries/overview)を使用してください。
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    このワークフローには、単一のシェルコマンドでは実現できないロジックが必要です。実行するには[Claude SDK](https://platform.claude.com/docs/ja/cli-sdks-libraries/overview)を使用してください。
  </CodeGroupItem>

  ```python Python
  open_runs: dict[str, str] = {}  # workflow_run_id -> run name
  phase_names: dict[tuple[str, str], str] = {}  # (run ID, phase ID) -> phase name

  # 先にストリームを開き、その後でユーザーメッセージを送信します
  with client.beta.sessions.events.stream(session_id) as stream:
      client.beta.sessions.events.send(
          session_id,
          events=[
              {
                  "type": "user.message",
                  "content": [
                      {
                          "type": "text",
                          "text": "Which contracts in /contracts have a change-of-control clause?",
                      },
                  ],
              },
          ],
      )

      for event in stream:
          match event.type:
              case "workflow_run.created":
                  open_runs[event.workflow_run_id] = event.name
                  for phase in event.phases:
                      phase_names[event.workflow_run_id, phase.id] = phase.name
                  print(f"Run started: {event.name}")
              case "workflow_run.phase_started":
                  phase_id = event.workflow_run_phase_id
                  key = (event.workflow_run_id, phase_id)
                  print(f"  Phase: {phase_names.get(key, phase_id)}")
              case "workflow_run.status_ended":
                  name = open_runs.pop(event.workflow_run_id, event.workflow_run_id)
                  print(f"Run ended: {name} ({event.result.type})")
              case "agent.custom_tool_use":
                  # イベントが届いたら応答します。実行のスレッドは、セッションが
                  # 実行中のまま、クライアントを待機することがあります。
                  result = call_tool(event.name, event.input)
                  try:
                      client.beta.sessions.events.send(
                          session_id,
                          events=[
                              {
                                  "type": "user.custom_tool_result",
                                  "custom_tool_use_id": event.id,
                                  "content": [{"type": "text", "text": result}],
                              },
                          ],
                      )
                  except anthropic.BadRequestError as error:
                      # サーバーは、呼び出しのスレッドをアーカイブした後に届いた
                      # 遅すぎる結果を拒否します。実行の追跡を続けます。
                      print(f"  Answer to {event.name} refused: {error.message}")
              case "session.status_idle":
                  # すべての実行が終了し、エージェントがターンを終えたら完了です
                  if not open_runs and event.stop_reason.type == "end_turn":
                      break
                  # requires_action を伴う idle はクライアントを待機しているため、読み取りを続けます。
                  # その他の停止理由の場合は、それを出力して停止します。
                  if event.stop_reason.type not in ("end_turn", "requires_action"):
                      print(f"Session idle: {event.stop_reason.type}")
                      break
              case "session.status_terminated":
                  break
  ```

  ```typescript TypeScript
  const openRuns = new Map<string, string>(); // workflow_run_id -> run name
  const phaseNames = new Map<string, string>(); // "run ID:phase ID" -> phase name

  // 先にストリームを開き、その後ユーザーメッセージを送信します
  const stream = await client.beta.sessions.events.stream(sessionId);
  await client.beta.sessions.events.send(sessionId, {
    events: [
      {
        type: "user.message",
        content: [
          {
            type: "text",
            text: "Which contracts in /contracts have a change-of-control clause?"
          }
        ]
      }
    ]
  });

  events: for await (const event of stream) {
    switch (event.type) {
      case "workflow_run.created":
        openRuns.set(event.workflow_run_id, event.name);
        for (const phase of event.phases) {
          phaseNames.set(`${event.workflow_run_id}:${phase.id}`, phase.name);
        }
        console.log(`Run started: ${event.name}`);
        break;
      case "workflow_run.phase_started": {
        const phaseId = event.workflow_run_phase_id;
        const phaseName = phaseNames.get(`${event.workflow_run_id}:${phaseId}`);
        console.log(`  Phase: ${phaseName ?? phaseId}`);
        break;
      }
      case "workflow_run.status_ended": {
        const name = openRuns.get(event.workflow_run_id) ?? event.workflow_run_id;
        openRuns.delete(event.workflow_run_id);
        console.log(`Run ended: ${name} (${event.result.type})`);
        break;
      }
      case "agent.custom_tool_use": {
        // イベントが届いたら応答します。実行のスレッドは、セッションが
        // 実行中のまま、クライアントを待機することがあります。
        const result = await callTool(event.name, event.input);
        try {
          await client.beta.sessions.events.send(sessionId, {
            events: [
              {
                type: "user.custom_tool_result",
                custom_tool_use_id: event.id,
                content: [{ type: "text", text: result }]
              }
            ]
          });
        } catch (error) {
          // サーバーは、呼び出しのスレッドをアーカイブした後に届いた遅すぎる結果を拒否します。
          // 実行の追跡を続けます。
          if (!(error instanceof Anthropic.BadRequestError)) {
            throw error;
          }
          console.log(`  Answer to ${event.name} refused: ${error.message}`);
        }
        break;
      }
      case "session.status_idle": {
        // すべての実行が終了し、エージェントがターンを終えたら完了です
        const reason = event.stop_reason.type;
        if (openRuns.size === 0 && reason === "end_turn") {
          break events;
        }
        // requires_action を伴う idle はクライアントを待機しているため、読み取りを続けます。
        // その他の停止理由の場合は、それを出力して停止します。
        if (reason !== "end_turn" && reason !== "requires_action") {
          console.log(`Session idle: ${reason}`);
          break events;
        }
        break;
      }
      case "session.status_terminated":
        break events;
    }
  }
  ```

  ```csharp C#
  var openRuns = new Dictionary<string, string>(); // workflow_run_id -> run name
  var phaseNames = new Dictionary<(string, string), string>(); // (run ID, phase ID) -> phase name

  // 先にストリームを開き、その後ユーザーメッセージを送信します。raw-response 呼び出しは
  // その時点でストリームを開きます。通常の呼び出しは最初の読み取りまで待機します。
  using var stream = await client.Beta.Sessions.Events.WithRawResponse.StreamStreaming(sessionId);
  await client.Beta.Sessions.Events.Send(sessionId, new()
  {
      Events =
      [
          new BetaManagedAgentsUserMessageEventParams
          {
              Type = BetaManagedAgentsUserMessageEventParamsType.UserMessage,
              Content =
              [
                  new BetaManagedAgentsTextBlock
                  {
                      Type = BetaManagedAgentsTextBlockType.Text,
                      Text = "Which contracts in /contracts have a change-of-control clause?",
                  },
              ],
          },
      ],
  });

  await foreach (var streamEvent in stream.Enumerate())
  {
      if (streamEvent.Value is BetaManagedAgentsWorkflowRunCreatedEvent created)
      {
          openRuns[created.WorkflowRunID] = created.Name;
          foreach (var listed in created.Phases)
          {
              phaseNames[(created.WorkflowRunID, listed.ID)] = listed.Name;
          }
          Console.WriteLine($"Run started: {created.Name}");
      }
      else if (streamEvent.Value is BetaManagedAgentsWorkflowRunPhaseStartedEvent phase)
      {
          var phaseId = phase.WorkflowRunPhaseID;
          var key = (phase.WorkflowRunID, phaseId);
          Console.WriteLine($"  Phase: {phaseNames.GetValueOrDefault(key, phaseId)}");
      }
      else if (streamEvent.Value is BetaManagedAgentsWorkflowRunStatusEndedEvent ended)
      {
          var name = openRuns.GetValueOrDefault(ended.WorkflowRunID, ended.WorkflowRunID);
          openRuns.Remove(ended.WorkflowRunID);
          var outcome = ended.Result.Value switch
          {
              BetaManagedAgentsWorkflowRunResultCompleted => "completed",
              BetaManagedAgentsWorkflowRunResultStopped => "stopped",
              BetaManagedAgentsWorkflowRunResultError => "error",
              _ => "ended",
          };
          Console.WriteLine($"Run ended: {name} ({outcome})");
      }
      else if (streamEvent.Value is BetaManagedAgentsAgentCustomToolUseEvent toolUse)
      {
          // イベントが届いたら応答します。実行のスレッドはクライアントを待機することがあり、
          // その間もセッションは実行中のままです。
          var result = await CallTool(toolUse.Name, toolUse.Input);
          try
          {
              await client.Beta.Sessions.Events.Send(sessionId, new()
              {
                  Events =
                  [
                      new BetaManagedAgentsUserCustomToolResultEventParams
                      {
                          Type = BetaManagedAgentsUserCustomToolResultEventParamsType.UserCustomToolResult,
                          CustomToolUseID = toolUse.ID,
                          Content =
                          [
                              new BetaManagedAgentsTextBlock
                              {
                                  Type = BetaManagedAgentsTextBlockType.Text,
                                  Text = result,
                              },
                          ],
                      },
                  ],
              });
          }
          catch (AnthropicBadRequestException error)
          {
              // サーバーは、呼び出しのスレッドをアーカイブした後に届いた
              // 遅すぎる結果を拒否します。実行の追跡を続けてください。
              Console.WriteLine($"  Answer to {toolUse.Name} refused: {error.Message}");
          }
      }
      else if (streamEvent.Value is BetaManagedAgentsSessionStatusIdleEvent idle)
      {
          // すべての実行が終了し、エージェントがターンを終えたら完了です
          var finished = idle.StopReason?.Value is BetaManagedAgentsSessionEndTurn;
          if (openRuns.Count == 0 && finished)
          {
              break;
          }
          // requires_action を伴う idle はクライアントを待機しているため、読み取りを続けます。
          // その他の停止理由の場合は、それを出力して停止します。
          if (!finished && idle.StopReason?.Value is not BetaManagedAgentsSessionRequiresAction)
          {
              var reason = idle.StopReason?.Json.GetProperty("type").GetString();
              Console.WriteLine($"Session idle: {reason}");
              break;
          }
      }
      else if (streamEvent.Value is BetaManagedAgentsSessionStatusTerminatedEvent)
      {
          break;
      }
  }
  ```

  ```go Go
  	openRuns := map[string]string{}      // workflow_run_id -> run name
  	phaseNames := map[[2]string]string{} // {run ID, phase ID} -> phase name

  	// 先にストリームを開き、その後でユーザーメッセージを送信します
  	stream := client.Beta.Sessions.Events.StreamEvents(ctx, sessionID, anthropic.BetaSessionEventStreamParams{})
  	defer stream.Close()

  	if _, err := client.Beta.Sessions.Events.Send(ctx, sessionID, anthropic.BetaSessionEventSendParams{
  		Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
  			OfUserMessage: &anthropic.BetaManagedAgentsUserMessageEventParams{
  				Type: anthropic.BetaManagedAgentsUserMessageEventParamsTypeUserMessage,
  				Content: []anthropic.BetaManagedAgentsUserMessageEventParamsContentUnion{{
  					OfText: &anthropic.BetaManagedAgentsTextBlockParam{
  						Type: anthropic.BetaManagedAgentsTextBlockTypeText,
  						Text: "Which contracts in /contracts have a change-of-control clause?",
  					},
  				}},
  			},
  		}},
  	}); err != nil {
  		panic(err)
  	}

  events:
  	for stream.Next() {
  		switch event := stream.Current().AsAny().(type) {
  		case anthropic.BetaManagedAgentsWorkflowRunCreatedEvent:
  			openRuns[event.WorkflowRunID] = event.Name
  			for _, phase := range event.Phases {
  				phaseNames[[2]string{event.WorkflowRunID, phase.ID}] = phase.Name
  			}
  			fmt.Printf("Run started: %s\n", event.Name)
  		case anthropic.BetaManagedAgentsWorkflowRunPhaseStartedEvent:
  			phaseName, ok := phaseNames[[2]string{event.WorkflowRunID, event.WorkflowRunPhaseID}]
  			if !ok {
  				phaseName = event.WorkflowRunPhaseID
  			}
  			fmt.Printf("  Phase: %s\n", phaseName)
  		case anthropic.BetaManagedAgentsWorkflowRunStatusEndedEvent:
  			name, ok := openRuns[event.WorkflowRunID]
  			if !ok {
  				name = event.WorkflowRunID
  			}
  			delete(openRuns, event.WorkflowRunID)
  			fmt.Printf("Run ended: %s (%s)\n", name, event.Result.Type)
  		case anthropic.BetaManagedAgentsAgentCustomToolUseEvent:
  			// イベントが届いたら応答します。実行のスレッドは、セッションが
  			// 実行中のまま、クライアントを待機することがあります。
  			result := callTool(event.Name, event.Input)
  			if _, err := client.Beta.Sessions.Events.Send(ctx, sessionID, anthropic.BetaSessionEventSendParams{
  				Events: []anthropic.BetaManagedAgentsEventParamsUnion{{
  					OfUserCustomToolResult: &anthropic.BetaManagedAgentsUserCustomToolResultEventParams{
  						Type:            anthropic.BetaManagedAgentsUserCustomToolResultEventParamsTypeUserCustomToolResult,
  						CustomToolUseID: event.ID,
  						Content: []anthropic.BetaManagedAgentsUserCustomToolResultEventParamsContentUnion{{
  							OfText: &anthropic.BetaManagedAgentsTextBlockParam{
  								Type: anthropic.BetaManagedAgentsTextBlockTypeText,
  								Text: result,
  							},
  						}},
  					},
  				}},
  			}); err != nil {
  				// サーバーは、呼び出しのスレッドをアーカイブした後に届いた
  				// 遅すぎる結果を拒否します。実行の追跡を続けます。
  				var apiErr *anthropic.Error
  				if !errors.As(err, &apiErr) || apiErr.StatusCode != http.StatusBadRequest {
  					panic(err)
  				}
  				fmt.Printf("  Answer to %s refused: %v\n", event.Name, err)
  			}
  		case anthropic.BetaManagedAgentsSessionStatusIdleEvent:
  			// すべての実行が終了し、エージェントがターンを終えたら完了です
  			switch event.StopReason.AsAny().(type) {
  			case anthropic.BetaManagedAgentsSessionEndTurn:
  				if len(openRuns) == 0 {
  					break events
  				}
  			// requires_action を伴う idle はクライアントを待機しているため、読み取りを続けます。
  			// その他の停止理由の場合は、それを出力して停止します。
  			case anthropic.BetaManagedAgentsSessionRequiresAction:
  			default:
  				fmt.Printf("Session idle: %s\n", event.StopReason.Type)
  				break events
  			}
  		case anthropic.BetaManagedAgentsSessionStatusTerminatedEvent:
  			break events
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  ```

  ```java Java
  var openRuns = new HashMap<String, String>(); // workflow_run_id -> run name
  var phaseNames = new HashMap<String, String>(); // "run ID:phase ID" -> phase name

  // 先にストリームを開き、その後でユーザーメッセージを送信します
  try (var stream = client.beta().sessions().events().streamStreaming(sessionId)) {
      client.beta().sessions().events().send(
          sessionId,
          EventSendParams.builder()
              .addEvent(BetaManagedAgentsUserMessageEventParams.builder()
                  .type(BetaManagedAgentsUserMessageEventParams.Type.USER_MESSAGE)
                  .addTextContent("Which contracts in /contracts have a change-of-control clause?")
                  .build())
              .build()
      );

      Iterable<BetaManagedAgentsStreamSessionEvents> events = stream.stream()::iterator;
      events:
      for (var event : events) {
          switch (event.type().value()) {
              case WORKFLOW_RUN_CREATED -> {
                  var created = event.asWorkflowRunCreated();
                  openRuns.put(created.workflowRunId(), created.name());
                  created.phases().forEach(phase ->
                      phaseNames.put(created.workflowRunId() + ":" + phase.id(), phase.name()));
                  IO.println("Run started: " + created.name());
              }
              case WORKFLOW_RUN_PHASE_STARTED -> {
                  var started = event.asWorkflowRunPhaseStarted();
                  var phaseId = started.workflowRunPhaseId();
                  var key = started.workflowRunId() + ":" + phaseId;
                  IO.println("  Phase: " + phaseNames.getOrDefault(key, phaseId));
              }
              case WORKFLOW_RUN_STATUS_ENDED -> {
                  var ended = event.asWorkflowRunStatusEnded();
                  var name = openRuns.getOrDefault(ended.workflowRunId(), ended.workflowRunId());
                  openRuns.remove(ended.workflowRunId());
                  var result = ended.result();
                  var outcome = result.isCompleted() ? "completed"
                      : result.isStopped() ? "stopped"
                      : result.isError() ? "error"
                      : "ended";
                  IO.println("Run ended: " + name + " (" + outcome + ")");
              }
              case AGENT_CUSTOM_TOOL_USE -> {
                  // イベントが届いたら応答します。実行のスレッドは、セッションが
                  // 実行中のまま、クライアントを待機することがあります。
                  var toolUse = event.asAgentCustomToolUse();
                  var result = callTool(toolUse.name(), toolUse.input());
                  try {
                      client.beta().sessions().events().send(
                          sessionId,
                          EventSendParams.builder()
                              .addEvent(BetaManagedAgentsUserCustomToolResultEventParams.builder()
                                  .type(BetaManagedAgentsUserCustomToolResultEventParams.Type.USER_CUSTOM_TOOL_RESULT)
                                  .customToolUseId(toolUse.id())
                                  .addTextContent(result)
                                  .build())
                              .build());
                  } catch (BadRequestException e) {
                      // サーバーは、呼び出しのスレッドをアーカイブした後に届いた
                      // 遅すぎる結果を拒否します。実行の追跡を続けます。
                      IO.println("  Answer to " + toolUse.name() + " refused: " + e.getMessage());
                  }
              }
              case SESSION_STATUS_IDLE -> {
                  // すべての実行が終了し、エージェントがターンを終えたら完了です
                  var stopReason = event.asSessionStatusIdle().stopReason();
                  if (openRuns.isEmpty() && stopReason.isEndTurn()) {
                      break events;
                  }
                  // requires_action を伴う idle はクライアントを待機しているため、読み取りを続けます。
                  // その他の停止理由の場合は、それを出力して停止します。
                  if (!stopReason.isEndTurn() && !stopReason.isRequiresAction()) {
                      IO.println("Session idle: " + stopReason.type().asString());
                      break events;
                  }
              }
              case SESSION_STATUS_TERMINATED -> {
                  break events;
              }
              default -> {}
          }
      }
  }
  ```

  ```php PHP
  $openRuns = []; // workflow_run_id => run name
  $phaseNames = []; // run ID => [phase ID => phase name]

  // 先にストリームを開き、その後でユーザーメッセージを送信します
  $stream = $client->beta->sessions->events->streamStream($sessionId);
  $client->beta->sessions->events->send(
      $sessionId,
      events: [
          [
              'type' => 'user.message',
              'content' => [
                  ['type' => 'text', 'text' => 'Which contracts in /contracts have a change-of-control clause?'],
              ],
          ],
      ],
  );

  foreach ($stream as $event) {
      switch (true) {
          case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsWorkflowRunCreatedEvent:
              $openRuns[$event->workflowRunID] = $event->name;
              foreach ($event->phases as $phase) {
                  $phaseNames[$event->workflowRunID][$phase->id] = $phase->name;
              }
              echo "Run started: {$event->name}", PHP_EOL;
              break;
          case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsWorkflowRunPhaseStartedEvent:
              $phaseId = $event->workflowRunPhaseID;
              echo '  Phase: ', $phaseNames[$event->workflowRunID][$phaseId] ?? $phaseId, PHP_EOL;
              break;
          case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsWorkflowRunStatusEndedEvent:
              $name = $openRuns[$event->workflowRunID] ?? $event->workflowRunID;
              unset($openRuns[$event->workflowRunID]);
              echo "Run ended: {$name} ({$event->result->type})", PHP_EOL;
              break;
          case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsAgentCustomToolUseEvent:
              // イベントが届いたら応答します。実行のスレッドは、セッションが
              // 実行中のまま、クライアントを待機することがあります。
              $result = callTool($event->name, $event->input);
              try {
                  $client->beta->sessions->events->send(
                      $sessionId,
                      events: [
                          [
                              'type' => 'user.custom_tool_result',
                              'custom_tool_use_id' => $event->id,
                              'content' => [['type' => 'text', 'text' => $result]],
                          ],
                      ],
                  );
              } catch (\Anthropic\Core\Exceptions\BadRequestException $error) {
                  // サーバーは、呼び出しのスレッドをアーカイブした後に届いた
                  // 遅すぎる結果を拒否します。実行の追跡を続けます。
                  echo "  Answer to {$event->name} refused: {$error->getMessage()}", PHP_EOL;
              }
              break;
          case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsSessionStatusIdleEvent:
              // すべての実行が終了し、エージェントがターンを終えたら完了です
              $finished = $event->stopReason->type === 'end_turn';
              if (!$openRuns && $finished) {
                  break 2;
              }
              // requires_action を伴う idle はクライアントを待機しているため、読み取りを続けます。
              // その他の停止理由の場合は、それを出力して停止します。
              if (!$finished && $event->stopReason->type !== 'requires_action') {
                  echo "Session idle: {$event->stopReason->type}", PHP_EOL;
                  break 2;
              }
              break;
          case $event instanceof \Anthropic\Beta\Sessions\Events\ManagedAgentsSessionStatusTerminatedEvent:
              break 2;
      }
  }
  $stream->close();
  ```

  ```ruby Ruby
  open_runs = {} # workflow_run_id => run name
  phase_names = {} # [run ID, phase ID] => phase name

  # 先にストリームを開き、その後ユーザーメッセージを送信します
  stream = client.beta.sessions.events.stream_events(session_id)

  client.beta.sessions.events.send_(
    session_id,
    events: [{
      type: "user.message",
      content: [{type: "text", text: "Which contracts in /contracts have a change-of-control clause?"}]
    }]
  )

  stream.each do |event|
    case event
    when Anthropic::Beta::Sessions::BetaManagedAgentsWorkflowRunCreatedEvent
      open_runs[event.workflow_run_id] = event.name
      event.phases.each { |phase| phase_names[[event.workflow_run_id, phase.id]] = phase.name }
      puts "Run started: #{event.name}"
    when Anthropic::Beta::Sessions::BetaManagedAgentsWorkflowRunPhaseStartedEvent
      phase_id = event.workflow_run_phase_id
      puts "  Phase: #{phase_names.fetch([event.workflow_run_id, phase_id], phase_id)}"
    when Anthropic::Beta::Sessions::BetaManagedAgentsWorkflowRunStatusEndedEvent
      name = open_runs.delete(event.workflow_run_id) || event.workflow_run_id
      puts "Run ended: #{name} (#{event.result.type})"
    when Anthropic::Beta::Sessions::BetaManagedAgentsAgentCustomToolUseEvent
      # イベントが届いたら応答します。実行のスレッドは、セッションが
      # 実行中のまま、クライアントを待機することがあります。
      result = call_tool.call(event.name, event.input)
      begin
        client.beta.sessions.events.send_(
          session_id,
          events: [{
            type: "user.custom_tool_result",
            custom_tool_use_id: event.id,
            content: [{type: "text", text: result}]
          }]
        )
      rescue Anthropic::Errors::BadRequestError => error
        # サーバーは、呼び出しのスレッドをアーカイブした後に届いた遅すぎる結果を
        # 拒否します。実行の追跡を続けてください。
        puts "  Answer to #{event.name} refused: #{error.message}"
      end
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusIdleEvent
      reason = event.stop_reason.type.to_sym
      # すべての実行が終了し、エージェントがターンを終えたら完了です
      break if open_runs.empty? && reason == :end_turn
      # requires_action を伴う idle はクライアントを待機しているため、読み取りを続けます。
      # その他の停止理由の場合は、それを出力して停止します。
      unless %i[end_turn requires_action].include?(reason)
        puts "Session idle: #{reason}"
        break
      end
    when Anthropic::Beta::Sessions::BetaManagedAgentsSessionStatusTerminatedEvent
      break
    end
  end
  ```
</CodeGroup>

## 実行が開いているセッションを中断する

`session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) なしで、またはプライマリスレッドの ID を指定して、[`user.interrupt`](https://platform.claude.com/docs/ja/managed-agents/events-and-streaming#interrupt-the-agent) を送信します。これはエージェントのターンを停止します。実行は終了しません。セッションの実行は一時停止するか実行を続ける可能性があり、そのイベントはどちらであるかを示さない場合があります。一時停止した実行の有効期間は経過し続けるため、実行が一時停止中に `timeout_error` で終了することがあります。

* **待機中のツール呼び出し：** 中断後も、実行スレッドのツール呼び出しがクライアントを待っている場合があります。それぞれに応答してください。確認を求める呼び出しをキャンセルするには、拒否します。カスタムツール呼び出しをキャンセルするには、`is_error` (java, php: `isError`; csharp, go: `IsError`) を `true` に設定し、`content` (csharp, go: `Content`) に理由を説明するテキストを含めた結果を送信します。セッションが `requires_action` で `idle` の間は、`user.message` は 400 を返すため、先に呼び出しに応答してください。
* **実行を停止するには：** 実行を停止するようエージェントに依頼する `user.message` を送信します。停止した実行は `result` `{"type": "stopped"}` で終了します。セッションが `budget_reached` で `idle` の間は、予算を引き上げるか削除するまで、`user.message` は 400 を返します。予算を引き上げるか削除すると、中断によっても一時停止している場合を除き、予算によって一時停止した実行も再開されます。
* **続行するには：** 実行を続行するようエージェントに依頼する `user.message` を送信します。中断後、実行はこのメッセージを待つ場合があります。セッションが `budget_reached` で `idle` の場合は、先に予算を引き上げるか削除してください。
* **実行結果：** 中断後に終了する実行も、`workflow_run.status_ended` を送信します。

## 実行が開いている間

| リクエスト                                      | 実行が開いている間                                                                                                                                                                                              | 対応                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| セッションをアーカイブまたは削除する                         | セッションのステータスにかかわらず、実行が開いている間は 400 を返す場合があります。エラーの `error.details.error_code` は `"workflow_run_open"` になることがあります。成功する場合もあります。                                                                            | エージェントに実行を停止するよう依頼するか、各実行が終了するまで待ちます。一時停止した実行が自然に終了するのは、有効期間が過ぎたときだけです。その後、セッションが `idle` になったらリクエストを送信します。成功したアーカイブは、開いている各実行を `{"type": "stopped"}` で終了させます。アーカイブ後、実行の `workflow_run.status_ended` と、まだ開いていたフェーズの `workflow_run.phase_ended` はストリームに届きません。それらを読むには、セッションのイベントを一覧表示してください。成功した削除の後は、セッションの実行の終了を報告する `workflow_run` イベントはありません。                                                                                                                                                                                                                                                        |
| 実行のスレッドの1つをアーカイブする                         | サーバーがすでにスレッドをアーカイブしていない限り、実行が開いている間（実行中でもアイドル状態でも）は `error.details.error_code: "workflow_run_open"` とともに 400 を返します。                                                                                    | 何もする必要はありません。サーバーが実行のスレッドをアーカイブします。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| セッションの `agent` (csharp, go: `Agent`) を更新する | 一時停止したものも含め、いずれかの実行が開いている間は `error.details.error_code: "workflow_run_open"` とともに 400 を返します。基になるエージェントの更新は引き続き受け付けられ、セッションは独自のコピーを保持します。`budget` (csharp, go: `Budget`) など他のフィールドも送信するリクエストは、全体が拒否されます。 | すべての実行に `workflow_run.status_ended` が届くまで待つか、エージェントに実行を停止するよう依頼します。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| 実行のスレッドからのツール呼び出しまたはツール確認に応答する             | 許可されます。プライマリストリームに届き、その `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) がスレッドを示します。                                                               | イベントが届いたらすぐに、イベントの `id` (csharp, go: `ID`) を `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`) または `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`) として渡して応答します。`session.status_idle` を待たないでください。実行の他のスレッドが作業している間、セッションは `running` のままになることがあります。サーバーがスレッドをアーカイブした後は、その呼び出しに対するツール結果は効果がなく、400 を返すことがあります。ツール結果が 400 を返した場合は、スレッド一覧で呼び出しのスレッドを探してください。そのステータスが `terminated` であれば、結果が遅すぎたため、破棄してください。サーバーはリクエスト内のイベントの1つを拒否するとリクエスト全体を拒否するため、各ツール結果はそれぞれ個別のリクエストで送信してください。遅すぎたツール確認は 200 を返しますが、これはツールが実行されたことを意味しません。 |

### 再接続後に実行の状態を再構築する

各実行の状態は、セッションのイベントから再構築します。ストリームは見逃したものを再生しません。新しい接続は、接続が開いた後に発行されたイベントのみを配信します。そのため、[過去のイベントを一覧表示する](https://platform.claude.com/docs/ja/managed-agents/events-and-streaming#list-past-events)のように、イベントタイプごとに1つのエントリを指定した `types` (curl: `types[]`; cli: `--type`; csharp, go: `Types`) フィルターでイベントを一覧表示してください。`next_page` (ruby: `next_page_`; java, php: `nextPage`; csharp, go: `NextPage`) が `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) になるか存在しなくなるまで、各レスポンスの `next_page` (ruby: `next_page_`; java, php: `nextPage`; csharp, go: `NextPage`) を `page` (cli: `--page`; csharp, go: `Page`) として渡します。`workflow_run.created`、`workflow_run.status_running`、`workflow_run.status_idle`、`workflow_run.status_ended` は各実行の状態を示しますが、中断後に一時停止した実行は実行中と表示されたままになる場合があります。`workflow_run.phase_started` と `workflow_run.phase_ended` で進捗を再構築します。まだステータスイベントがない実行は、処理を開始していません。実行を一覧表示するエンドポイントはありません。

## コストと予算

実行のモデルリクエストは、[セッションの予算](https://platform.claude.com/docs/ja/managed-agents/budgets)に計上されます。実行自体に価格はありません。そのエージェントが使用するトークンは、セッションの他のトークンと同様に、各モデルの料金で課金されます。セッションのすべての料金については、[Claude Managed Agents の料金](https://platform.claude.com/docs/ja/about-claude/pricing#claude-managed-agents-pricing)を参照してください。

* **1つの実行の使用量：** セッションのスレッドを一覧表示し、実行の `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) を持つスレッドの `usage` (csharp, go: `Usage`) 内のトークン数を合計します。一覧にはステータスが `terminated` のアーカイブ済みスレッドも含まれるため、完了した実行のスレッドも数えられます。`next_page` (ruby: `next_page_`; java, php: `nextPage`; csharp, go: `NextPage`) が `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) になるか存在しなくなるまで、各レスポンスの `next_page` (ruby: `next_page_`; java, php: `nextPage`; csharp, go: `NextPage`) を `page` (cli: `--page`; csharp, go: `Page`) として渡し、`usage` (csharp, go: `Usage`) のないスレッドはスキップしてください。代わりにスレッドの `list_cost` (java, php: `listCost`; csharp, go: `ListCost`) を合計すると、合計にはセッションのランタイムが含まれず、各数値は個別に丸められます。
* **予算に達したとき：** 開いているすべての実行が一時停止し、セッションは `budget_reached` で `idle`、またはツール呼び出しも待機している場合は `requires_action` を報告します。各スレッドはすでに開始したモデルリクエストを完了するため、実行は作業中のスレッドごとに1リクエスト分、予算を超えることがあります。予算を引き上げるか削除すると、中断によっても一時停止している場合を除き、予算によって一時停止した実行が再開されます。セッションの使用量にリスト価格のないモデルが含まれる場合は、予算を削除した場合のみ再開されます。[リスト価格のないモデル](https://platform.claude.com/docs/ja/managed-agents/budgets#models-without-a-list-price)を参照してください。一時停止した実行の有効期間は経過し続けるため、実行が一時停止中に `timeout_error` で終了することがあります。

## 制限

| 制限                          | 値                             | 制限に達したとき                                                                                                                                    |
| --------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| 1つの実行で同時に作業するスレッド           | 64                            | 1つが完了するまで、実行はそれ以上スレッドを作成しません。API はこの数値を保証しません。                                                                                              |
| 実行の全期間を通じてワークフローが開始するエージェント | 1,000                         | ワークフローがそれ以上を要求すると、サーバーは別のエージェントを開始せず、実行は `thread_limit_error` で終了します。サーバーは失敗したエージェントを新しいスレッドで再実行できるため、実行のスレッドが1,000を超える場合があります。             |
| 実行の有効期間                     | デフォルトで24時間、またはエージェントが設定した有効期間 | 実行は `timeout_error` で終了します。エージェントが設定した有効期間を示すイベントはありません。                                                                                    |
| 1つのセッションで同時に開いている実行         | デフォルトで10                      | サーバーは別の実行の開始を拒否します。エージェントのツール呼び出しはエラーを受け取り、あなたは `error.type` が `max_workflow_runs_error` の `workflow_run.error` を受け取ります。アイドル状態の実行も制限に含まれます。 |

サーバーは、実行またはフェーズの `name` (csharp, go: `Name`) を64文字に、`description` (csharp, go: `Description`) を256文字に短縮します。サーバーには、ここに記載されていないワークフローに関する他の制限とルールがあります。表示される内容は、サーバーが問題を検出するタイミングによって異なります。

| 発生すること                                         | 表示される内容                                                          |
| ---------------------------------------------- | ---------------------------------------------------------------- |
| エージェントが実行を開始する時点で、ワークフローが他の制限のいずれかを超えている       | 開始が拒否されます。`workflow_run.error` を受け取り、実行は作成されません。                 |
| 実行が後で他の制限のいずれかを超える                             | `workflow_run.error` を受け取り、その後、実行が `unknown_error` で終了することがあります。 |
| 開始後に、ワークフローが制限以外のワークフローのルールに違反していることをサーバーが検出する | `workflow_run.error` を受け取り、その後、実行が `program_error` で終了することがあります。 |

セッションは、その存続期間中に任意の数の実行を開始できます。

* **実行の開始：** 実行を開始するのは、セッションのプライマリスレッド上のエージェントのみです。実行のスレッドで作業しているエージェントは独自の実行を開始できないため、実行はネストしません。
* **実行の終了：** あなたが送信するイベントで実行が終了することはありませんが、セッションをアーカイブすると終了する場合があります。
* **実行のスレッド：** [ID でスレッドを停止](https://platform.claude.com/docs/ja/managed-agents/session-threads#interrupt-a-session-thread)したり、実行が開いている間にスレッドをアーカイブしたりすることはできません。
* **スレッド制限：** 実行のスレッドは、セッションの[子スレッド制限](https://platform.claude.com/docs/ja/managed-agents/session-threads#primary-thread-and-session-threads)の対象外です。
* **可視性：** ワークフローのコードは表示されませんが、[実行のスレッド](https://platform.claude.com/docs/ja/managed-agents/workflow-runs#a-runs-threads)のヒントで説明するように、エージェントにワークフローを出力するよう依頼できます。また、エージェントが実行を開始および管理するために行うツール呼び出しや、各スレッドがワークフローに返す結果も表示されません。

### レート制限

実行の作業は、組織にすでに設定されている「rate limit」（レート制限）に計上されます。

| 対象                                               | 計上先                                                                                                       | 対応                                                                                                                       |
| ------------------------------------------------ | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| セッション、そのスレッド、およびそれらのイベントを取得または一覧表示するクライアントのリクエスト | [Managed Agents エンドポイント](https://platform.claude.com/docs/ja/managed-agents/reference#rate-limits)の読み取り制限 | ポーリングする代わりに、セッションのイベントストリームで実行を追跡してください。                                                                                 |
| 実行のスレッドからのモデルリクエスト                               | 他のトラフィックとともに、各スレッドが使用するモデルの [Messages API のレート制限](https://platform.claude.com/docs/ja/api/rate-limits)    | それらの制限内に実行のための余裕を残すか、[より高い制限をリクエスト](https://platform.claude.com/docs/ja/api/rate-limits#requesting-higher-limits)してください。 |

実行のスレッドの1つからのモデルリクエストがレート制限を受けた場合、またはモデルが過負荷の場合、スレッド自身のストリームが `model_rate_limited_error` または `model_overloaded_error` タイプの `session.error` を受け取ることがあります。

* その `retry_status.type` が `retrying` の場合、サーバーはリクエストを再試行しており、スレッドはまだ作業中です。
* `exhausted` の場合、スレッドは失敗しています。ワークフローがその失敗によって実行を終了させた場合、実行は `program_error` で終了しますが、これは原因を示しません。原因を見つけるには、失敗したスレッドのイベントを読んでください。

サーバーは、組織のすべてのセッションが1分あたりに行う処理量も制限しています。この制限に達したスレッドは停止し、そのスレッド自身のストリームに、メッセージでレート制限を示す `session.error` が届きます。エージェントに続行を依頼する前に、1分待ってください。
