Claude Platform Docs
Managed Agentsはじめに

移行

Messages API または Claude Agent SDK で構築した既存のエージェントを Claude Managed Agents に移行します。

Claude Managed Agents は、手書きのエージェントループをマネージドインフラストラクチャに置き換えます。このページでは、Messages API 上に構築したカスタムループ、または Claude Agent SDK から移行する際に何が変わるかを説明します。

Messages API のエージェントループからの移行

while ループ内で messages.create を呼び出し、ツール呼び出しを自分で実行し、結果を会話履歴に追加することでエージェントを構築していた場合、そのコードの大部分は不要になります。

管理しなくてよくなるもの

移行前移行後
会話履歴の配列を保持し、毎ターンそれを渡し直します。セッションが履歴をサーバー側に保存します。イベントを送信し、イベントを受信します。
tool_use コンテンツブロックを反復処理し、各ツールを実行し、tool_result メッセージでループに戻ります。組み込み済みのツールはサンドボックス内で自動的に実行されます。agent.custom_tool_use イベントを通じてカスタムツールのみを処理します。
エージェントが生成したコードを実行するためのサンドボックスを自分で用意します。セッションのサンドボックスがコード実行、ファイル操作、bash を処理します。
ループがいつ完了するかを自分で判断します。エージェントにこれ以上やることがなくなると、セッションが session.status_idle を発行します。

コードの比較

移行前(Messages API ループ、簡略版):

messages = [{"role": "user", "content": task}]
while True:
    response = client.messages.create(
        model="claude-opus-5",
        max_tokens=1024,
        messages=messages,
        tools=tools,
    )
    messages.append({"role": "assistant", "content": response.content})
    if response.stop_reason == "end_turn":
        break
    for block in response.content:
        if block.type == "tool_use":
            result = execute_tool(block.name, block.input)
            messages.append(
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "tool_result",
                            "tool_use_id": block.id,
                            "content": result,
                        }
                    ],
                }
            )

移行後(Claude Managed Agents):

agent = client.beta.agents.create(
    name="Task Runner",
    model="claude-opus-5",
    tools=[{"type": "agent_toolset_20260401"}],
)

session = client.beta.sessions.create(
    agent={"type": "agent", "id": agent.id, "version": agent.version},
    environment_id=environment.id,
)

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": task}]}],
    )
    for event in stream:
        if event.type == "session.status_idle":
            break

引き続き制御できるもの

  • システムプロンプトとモデル: 同じフィールドですが、エージェント定義上に置かれます。
  • カスタムツール: 引き続き JSON Schema で宣言します。実行はインライン処理から agent.custom_tool_use イベントへの応答に移ります。セッションイベントストリームを参照してください。
  • Web 検索と Web フェッチの設定: 同じ allowed_domainsblocked_domainsmax_content_tokensuser_location フィールドですが、リクエストごとではなく、エージェントツールセットの configs 配列内の web_search および web_fetch エントリに一度だけ設定します。max_usescitationscache_control フィールドは利用できません。Web 検索と Web フェッチのドメインを制限するを参照してください。
  • コンテキスト: システムプロンプト、ファイルリソース、またはスキルを通じて、引き続きコンテキストを注入できます。

Claude Agent SDK からの移行

Claude Agent SDK で構築していた場合、すでにエージェント、ツール、セッションという概念を扱っています。違いはそれらがどこで実行されるかです。SDK はあなたが運用するプロセス内で実行されますが、Managed Agents は Anthropic のインフラストラクチャ内で実行されます。移行作業の大部分は、SDK の設定オブジェクトを API 側の同等物にマッピングすることです。

変わるもの

Agent SDKManaged Agents
実行ごとに構築する ClaudeAgentOptions(...)client.beta.agents.create(...) を一度だけ呼び出します。Agent はサーバー側で永続化され、バージョン管理されます。エージェントのセットアップを参照してください。
async with ClaudeSDKClient(...) または query(...)client.beta.sessions.create(...) を呼び出し、その後イベントを送受信します。
SDK によって自動的にディスパッチされる @tool デコレータ付き関数Agent 上で {"type": "custom", ...} として宣言します。クライアントが agent.custom_tool_use イベントを処理し、user.custom_tool_result で応答します。ツールを参照してください。
組み込みツールはあなたのプロセス内で、あなたのファイルシステムに対して実行される{"type": "agent_toolset_20260401"} が同じツールをセッションサンドボックス内で /workspace に対して実行します。
cwdadd_dirs がローカルパスを指すファイルをセッションリソースとしてアップロードまたはマウントします。
system_promptCLAUDE.md の階層Agent 上の単一の system 文字列。エージェントを変更する更新ごとに新しいサーバー側バージョンが生成されます。セッションを特定のバージョンに固定することで、デプロイなしで昇格やロールバックができます。エージェントのセットアップを参照してください。
mcp_servers を一箇所で設定・認証するAgent 上でサーバーを宣言し、Session 上の Vault を通じて認証情報を提供します。
permission_modecan_use_toolツールごとの permission_policyalways_ask ツールには user.tool_confirmation イベントを送信します。

コードの比較

移行前(Agent SDK):

from claude_agent_sdk import (
    ClaudeAgentOptions,
    ClaudeSDKClient,
    create_sdk_mcp_server,
    tool,
)


@tool("get_weather", "Get the current weather for a city.", {"city": str})
async def get_weather(args: dict) -> dict:
    return {"content": [{"type": "text", "text": f"{args['city']}: 18°C, clear"}]}


options = ClaudeAgentOptions(
    model="claude-opus-5",
    system_prompt="You are a concise weather assistant.",
    mcp_servers={
        "weather": create_sdk_mcp_server("weather", "1.0", tools=[get_weather])
    },
)

async with ClaudeSDKClient(options=options) as agent:
    await agent.query("What's the weather in Tokyo?")
    async for msg in agent.receive_response():
        print(msg)

移行後(Managed Agents):

from anthropic import Anthropic

client = Anthropic()

agent = client.beta.agents.create(
    name="weather-agent",
    model="claude-opus-5",
    system="You are a concise weather assistant.",
    tools=[
        {
            "type": "custom",
            "name": "get_weather",
            "description": "Get the current weather for a city.",
            "input_schema": {
                "type": "object",
                "properties": {"city": {"type": "string"}},
                "required": ["city"],
            },
        }
    ],
)
environment = client.beta.environments.create(
    name="weather-env",
    config={"type": "cloud", "networking": {"type": "unrestricted"}},
)

session = client.beta.sessions.create(
    agent={"type": "agent", "id": agent.id, "version": agent.version},
    environment_id=environment.id,
)


def get_weather(city: str) -> str:
    return f"{city}: 18°C, clear"


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": "What's the weather in Tokyo?"}],
            }
        ],
    )
    for event in stream:
        if event.type == "agent.message":
            print(
                "".join(block.text for block in event.content if block.type == "text")
            )
        elif event.type == "agent.custom_tool_use":
            result = get_weather(**event.input)
            client.beta.sessions.events.send(
                session.id,
                events=[
                    {
                        "type": "user.custom_tool_result",
                        "custom_tool_use_id": event.id,
                        "content": [{"type": "text", "text": result}],
                    }
                ],
            )
        elif (
            event.type == "session.status_idle"
            and event.stop_reason
            and event.stop_reason.type == "end_turn"
        ):
            break

Agent と Environment は一度作成され、セッション間で再利用されます。ツール関数は引き続きあなたのプロセス内で実行されます。違いは、SDK が代わりにディスパッチするのではなく、あなたが agent.custom_tool_use イベントを読み取り、結果を明示的に送信する点です。

クライアント側に移る機能

Anthropic がエージェントループを実行することのトレードオフとして、SDK が自動的に処理していたいくつかのことがクライアントの責任になります。

SDK の機能Managed Agents でのアプローチ
プランモードまず計画のみのセッションを実行し、次にその計画を実行する 2 つ目のセッションを実行します。
出力スタイル、スラッシュコマンドuser.message を送信する前、または agent.message を受信した後にクライアント側で適用します。
PreToolUse / PostToolUse フッククライアントは応答する前にすべての agent.custom_tool_use イベントをすでに確認しているので、そこにロジックを置きます。組み込みツールには permission_policy: always_ask を使用します。
max_turnsクライアント側でターン数をカウントします。

移行チェックリスト

  1. エージェントが必要とするネットワークとランタイムを備えた環境を作成します。
  2. システムプロンプトとツールの選択をエージェント定義に移植します。
  3. ループを sessions.createsessions.events.stream に置き換えます。
  4. エージェントが読み取るローカルファイルがあれば、Files API を通じてアップロードし、resources としてマウントします。
  5. カスタムツールハンドラーがあれば、実行を agent.custom_tool_use イベントへの応答としてイベントループ内に移します。
  6. 本番トラフィックを新しいフローに向ける前に、テストセッションで検証します。

モデルバージョン間の移行

新しい Claude モデルがリリースされた場合、Claude Managed Agents の統合の移行は通常 1 フィールドの変更で済みます。エージェント定義model を更新すれば、次に作成するセッションから変更が有効になります。

ant beta:agents update --agent-id "$AGENT_ID" < agent.yaml
agent.yaml
name: Task Runner
model: claude-opus-5
system: You are a task automation agent. Complete the task you are given end to end.
tools:
  - type: agent_toolset_20260401

Messages API 移行ガイドに記載されているモデルレベルの動作変更のほとんどは、あなたの側での対応を必要としません。

  • リクエストパラメータの変更max_tokens のデフォルト値、thinking の設定)は Claude Managed Agents ランタイムによって処理されます。これらのフィールドはエージェント定義には公開されていません。
  • アシスタントメッセージのプリフィルはイベントベースのセッションモデルには存在しないため、新しいモデルでの廃止は影響がありません。
  • ツール引数の JSON エスケープは、agent.custom_tool_use イベントを受信する前にランタイムによって解析されます。生の文字列ではなく、構造化されたデータを受け取ります。

Messages API ガイドの動作の説明(モデルの動作がどう変わるか)は引き続き適用されます。移行手順(リクエストコードをどう変更するか)は適用されません。

Was this page helpful?