Claude Platform Docs
Managed Agents自行託管沙箱

自行託管沙箱中的自訂工具

從自行託管的沙箱 worker 提供自訂工具,並將您網路內的 MCP 伺服器包裝為自訂工具,而無需執行通道。

自訂工具是由您自己的程式碼執行的工具:代理會發出 agent.custom_tool_use 事件,並等待相符的 user.custom_tool_result。這段程式碼可以是您的 worker。由於它在您的沙箱內執行,該工具可以存取您為沙箱設定的內部服務、憑證和網路出口(network egress),除此之外別無其他。

環境金鑰授權發布自訂工具結果,因此您的 Claude API 金鑰不會出現在 worker 主機上。

提供自訂工具

  1. 在代理上宣告工具

    在代理的 tools 中新增一個 custom 項目,其 name 須與您的 worker 所註冊的工具相符。完整的宣告結構請參閱自訂工具。

    {
      "type": "custom",
      "name": "get_order_status",
      "description": "Look up an order in the internal fulfillment system by order ID.",
      "input_schema": {
        "type": "object",
        "properties": {
          "order_id": { "type": "string", "description": "The order ID" }
        },
        "required": ["order_id"]
      }
    }
  2. 向 worker 註冊實作

    透過 worker 的 tools 工廠(請參閱 EnvironmentWorker)傳入工具,並與內建工具集一起使用:

    import asyncio
    import os
    from anthropic import AsyncAnthropic, beta_async_tool
    from anthropic.lib.environments import EnvironmentWorker
    from anthropic.lib.tools.agent_toolset import beta_agent_toolset_20260401
    
    
    @beta_async_tool
    async def get_order_status(order_id: str) -> str:
        """Look up an order in the internal fulfillment system by order ID."""
        # 在 worker 主機上執行:可呼叫沙箱能存取的任何資源。
        return f"Order {order_id}: shipped"
    
    
    async def main() -> None:
        environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
        environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
        async with AsyncAnthropic(auth_token=environment_key) as client:
            await EnvironmentWorker(
                client,
                environment_id=environment_id,
                environment_key=environment_key,
                workdir="/workspace",
                tools=lambda env: [*beta_agent_toolset_20260401(env), get_order_status],
            ).run()
    
    
    asyncio.run(main())

worker 只會回應向其註冊的工具。如果某個工具已在代理上宣告,但沒有任何 worker 或用戶端提供該工具,工作階段會以 requires_action 停止原因暫停,並持續暫停,直到有程式發布結果為止。事件流程請參閱處理自訂工具呼叫。

將 MCP 伺服器包裝為自訂工具

MCP 連接器從 Anthropic 端連線至 MCP 伺服器。因此,伺服器必須公開一個 Anthropic 可以直接或透過 MCP 通道存取的 HTTP 端點。

若要使用只有您的網路才能存取的伺服器,請改為讓 worker 擔任 MCP 用戶端,並將伺服器的工具宣告為自訂工具。MCP 伺服器不需要來自您網路外部的傳入連線。Anthropic 會收到您在代理上宣告的工具定義、每次呼叫的輸入,以及您的 worker 回傳的結果。

在執行階段,模型會像呼叫其他自訂工具一樣呼叫包裝後的工具:

  1. 代理發出 agent.custom_tool_use 事件。
  2. 位於您沙箱內的 worker 透過其開啟的 MCP 工作階段,將呼叫轉送至您網路上的伺服器。
  3. worker 將伺服器的回應作為 user.custom_tool_result 發布。

安裝 MCP SDK

SDK 的用戶端 MCP 輔助函式會將伺服器的工具轉換為 worker 可接受的可執行工具。請在 Anthropic SDK 之外另行安裝 MCP SDK:pip install "anthropic[mcp]" "mcp>=1.24"。

這些範例在未經驗證的情況下連線。若要傳送憑證,請設定您交給 MCP 傳輸層的 http_client。

宣告並提供工具

  1. 在代理上宣告伺服器的工具

    列出 MCP 伺服器的工具,並將每個工具宣告為 custom 工具。MCP 的 name、description 和 inputSchema 會一對一對應到自訂工具的欄位。如果伺服器對其工具清單進行分頁,請宣告每一頁;worker 也必須列出相同的頁面。

    import asyncio
    from typing import Any, cast
    from anthropic import AsyncAnthropic
    from anthropic.types.beta import BetaManagedAgentsCustomToolParams
    from mcp import ClientSession, types
    # 需要 mcp >= 1.24,該版本將 streamablehttp_client 更名為 streamable_http_client。
    from mcp.client.streamable_http import streamable_http_client
    
    MCP_SERVER_URL = "http://mcp.internal.example.com:8000/mcp"
    
    
    def to_custom_tool(tool: types.Tool) -> BetaManagedAgentsCustomToolParams:
        # MCP 欄位與自訂工具宣告一一對應。cast
        # 會將 schema 字典原封不動地傳給 SDK 的型別化參數。
        return {
            "type": "custom",
            "name": tool.name,
            "description": tool.description or tool.name,
            "input_schema": cast(Any, tool.inputSchema),
        }
    
    
    async def main() -> None:
        # 請在您建立代理程式的地方執行,而非在 worker 主機上:
        # 它會使用您的 Claude API 金鑰(ANTHROPIC_API_KEY)進行驗證。
        async with (
            streamable_http_client(MCP_SERVER_URL) as (read, write, _),
            ClientSession(read, write) as mcp_session,
            AsyncAnthropic() as client,
        ):
            await mcp_session.initialize()
            listed = await mcp_session.list_tools()
            agent = await client.beta.agents.create(
                name="Internal tools agent",
                model="claude-opus-5-5",
                tools=[
                    {"type": "agent_toolset_20260401"},
                    *[to_custom_tool(tool) for tool in listed.tools],
                ],
            )
            print(agent.id)
    
    
    asyncio.run(main())
  2. 從 worker 提供工具

    在啟動時連線至同一個 MCP 伺服器,使用 async_mcp_tool 轉換其工具,並將它們與 beta_agent_toolset_20260401 一起註冊。在 worker 的整個生命週期中保持一個 MCP 工作階段開啟。

    import asyncio
    import os
    from datetime import timedelta
    from anthropic import AsyncAnthropic
    from anthropic.lib.environments import EnvironmentWorker
    from anthropic.lib.tools.agent_toolset import beta_agent_toolset_20260401
    from anthropic.lib.tools.mcp import async_mcp_tool
    from mcp import ClientSession
    # 需要 mcp >= 1.24,該版本將 streamablehttp_client 更名為 streamable_http_client。
    from mcp.client.streamable_http import streamable_http_client
    
    MCP_SERVER_URL = "http://mcp.internal.example.com:8000/mcp"
    
    
    async def main() -> None:
        environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
        environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
        # 啟動時連線 MCP 伺服器一次,並在 worker 的整個生命週期中
        # 保持工作階段開啟。逾時設定會將卡住的工具呼叫轉為錯誤
        # 結果,而非停滯的呼叫。
        async with (
            streamable_http_client(MCP_SERVER_URL) as (read, write, _),
            ClientSession(read, write, read_timeout_seconds=timedelta(seconds=60)) as mcp_session,
            AsyncAnthropic(auth_token=environment_key) as client,
        ):
            await mcp_session.initialize()
            listed = await mcp_session.list_tools()
            mcp_tools = [async_mcp_tool(tool, mcp_session) for tool in listed.tools]
            await EnvironmentWorker(
                client,
                environment_id=environment_id,
                environment_key=environment_key,
                workdir="/workspace",
                tools=lambda env: [*beta_agent_toolset_20260401(env), *mcp_tools],
            ).run()
    
    
    asyncio.run(main())

限制與行為

工具是宣告的,而非在執行階段探索

worker 在啟動時只會列出一次 MCP 伺服器的工具,且無法將工具新增至執行中的工作階段。當伺服器的工具變更時:

  1. 重新宣告它們,可在代理上宣告,或透過更新代理設定在閒置的工作階段上宣告。
  2. 重新啟動 worker。

宣告必須符合 Managed Agents API

MCP 輔助工具會保留伺服器的名稱和描述,且大多數結構描述會原封不動地傳遞。當宣告違反下列任一規則時,請重新命名、精簡或內嵌:

欄位規則
name每個代理中必須唯一。由字母、數字、底線和連字號組成,長度 1–128 個字元。不可與內建代理工具(例如 bash 或 read)相同,也不可使用保留的 mcp__ 前綴。
description必填且不可為空。
input_schema接受 MCP 伺服器常見輸出的 JSON Schema 關鍵字,例如 additionalProperties 和 title。拒絕任何位置的參照關鍵字(例如 $ref),以及頂層的 oneOf、anyOf 和 allOf。屬性名稱使用字母、數字、底線、點和連字號,長度 1–64 個字元。
代理的 tools 陣列最多 128 個項目。每個包裝後的工具佔一個項目,內建工具集另佔一個。

有兩種情況需要額外處理:

  • 兩個伺服器公開相同的工具名稱: 請自行以加上前綴的名稱定義包裝器,並讓它呼叫伺服器的原始工具名稱。
  • 像 pydantic 這類產生器將結構描述拆分至 $defs: 請在宣告工具之前將這些結構描述內嵌。

工具失敗會以錯誤工具結果呈現

當 MCP 伺服器回報工具錯誤時,worker 會發布一個模型可以回應的錯誤工具結果。沒有對應工具結果形式的 MCP 內容(例如音訊區塊和資源連結)也會以錯誤呈現。

請在 MCP 用戶端上設定逾時,以獲得更快速且更明確的失敗,如同 Python worker 範例使用 read_timeout_seconds 的做法。若未設定逾時會發生什麼情況,請參閱包裝的 MCP 工具呼叫停滯。

只包裝您營運或信任的伺服器

包裝後工具的名稱、描述和結果會像其他工具一樣進入模型的上下文。它們是不受信任的輸入,可能影響代理如何使用其他工具,包括 worker 主機上的 bash。請只宣告您打算讓代理使用的工具。

權限政策不適用

權限政策管理內建工具集和 MCP 工具集。worker 會執行模型發出的每一個包裝工具呼叫,因此請將任何核准步驟放在您自己的工具程式碼中。

Was this page helpful?