Claude Platform Docs
Managed Agents進階編排

多代理協調

在單一工作階段中協調多個代理。

「Multiagent orchestration」(多代理協調)讓一個代理能夠與其他代理協作以完成複雜的工作。各代理可以在各自隔離的上下文中平行運作,這有助於提升輸出品質,也能縮短完成時間。

不確定多代理設定是否適合您的問題?請參閱何時使用多代理系統(以及何時不該使用)

運作方式

所有代理共用相同的沙箱、檔案系統與 vault 憑證,但每個代理都在自己的 session thread(工作階段執行緒)中執行,這是一個上下文隔離的事件串流,擁有自己的對話歷史。協調者會在 primary thread(主執行緒)中回報活動(它與工作階段層級的事件串流相同);當協調者委派工作時,會在執行期間產生額外的執行緒。

執行緒是持久的:協調者可以向先前呼叫過的代理傳送後續訊息,而該代理會保留其先前各輪的所有內容。

每個代理使用自己的設定:模型、系統提示、工具、MCP 伺服器與技能。工作階段層級的代理設定覆寫是例外;它們會套用至協調者及其 self 副本。工具、MCP 伺服器與上下文不會共用。

該委派什麼

多代理協調最適合複雜的任務,這類任務要麼需要跨多種介面進行工作,要麼由多個範圍明確的子任務共同促成整體目標。

效果良好的模式:

  • 平行化(Parallelization): 同時展開彼此獨立的子任務(搜尋多個來源、分析不同檔案),並由協調者彙整結果。
  • 專業化(Specialization): 將工作路由至具有領域專屬系統提示與工具的代理,例如安全代理或文件代理,而不是讓單一代理承載所有能力。
  • 升級(Escalation): 針對部分複雜的子任務,諮詢能力更強的代理或模型。

設定協調者

定義您的代理時,設定 multiagent 以宣告協調者可委派的代理名冊:

ant beta:agents create < coordinator.agent.yaml
coordinator.agent.yaml
name: Engineering Lead
model: claude-opus-5
system: You coordinate engineering work. Delegate code review to the reviewer agent and test writing to the test agent.
tools:
  - type: agent_toolset_20260401
multiagent:
  type: coordinator
  agents:
    - type: agent
      id: $REVIEWER_AGENT_ID # replace before running command
    - type: agent
      id: $TEST_WRITER_AGENT_ID # replace before running command

multiagent.agents 可接受下列任一形式:

  • {"type": "agent", "id": agent.id} 以 ID 參照先前建立的 agent。若未指定 version,該參照會釘選至建立協調者當下該代理的最新版本。
  • {"type": "agent", "id": agent.id, "version": agent.version} 釘選特定的代理版本。
  • {"type": "self"} 允許協調者產生自身的副本。若工作階段是以代理設定覆寫建立的,這些覆寫也會套用至這些副本;以 ID 參照的名冊項目則不受影響。
  • {"type": "advisor", "model": "<model id>"} 為工作階段的主執行緒提供一個可在輪次中途諮詢的顧問。每份名冊最多一個顧問項目。請參閱為工作階段提供顧問

協調者的設定(包括其 multiagent.agents 名冊)會在協調者建立或更新時建立快照。被參照的代理會維持釘選在當時解析出的版本,不會自動套用其定義之後的更新。若要委派給被參照代理的較新版本,請更新協調者,使其名冊參照該版本。

協調者只能委派給一層代理;若參照的代理本身擁有 multiagent.agents 名冊,建立或更新請求會因驗證錯誤而失敗。multiagent.agents 中最多可列出 20 個不重複的代理,但協調者可以呼叫每個代理的多個副本。

當代理釘選了推論地理區域代理定義中的 model.inference_geo)時,協調者的釘選值與每個名冊成員的釘選值必須全部設為相同的值,或全部不設定。不一致的名冊會以 400 驗證錯誤被拒絕,無論是在儲存代理時,或是在建立工作階段時的覆寫變更了任何釘選值時皆然。

為工作階段提供顧問

multiagent.agents 中的顧問項目會為工作階段的主執行緒提供一個 advisor(顧問):一個可在輪次中途諮詢以取得策略性指引的模型,例如規劃做法、擺脫卡關,或在完成前審查工作。該項目恰好有兩個欄位,typemodel

cURL
curl -fsS https://api.anthropic.com/v1/agents \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: managed-agents-2026-04-01" \
  -H "content-type: application/json" \
  -d '{
    "name": "Backend engineer",
    "model": "claude-sonnet-5",
    "system": "You implement backend features end to end. Consult the advisor before major backend design decisions.",
    "multiagent": {
      "type": "coordinator",
      "agents": [
        {"type": "advisor", "model": "claude-opus-5"}
      ]
    }
  }'

一份名冊最多可包含一個顧問項目,並可與其他任何名冊形式並存。該項目佔用保留的名冊名稱 anthropic.advisor:若名冊同時列出顧問項目以及一個字面上名為 anthropic.advisor 的成員,會以 400 驗證錯誤被拒絕。在回應中,無論顧問項目提交時位於何處,它都會在名冊中最後回傳。

顧問模型必須達到最低能力門檻,且代理本身的模型不得比其顧問更強;能力相同的模型可以配對。無效的配對會在儲存代理時以 400 驗證錯誤被拒絕。有效的配對遵循顧問工具的模型相容性表格。

顧問也以 Messages API 上的伺服器工具形式提供。Managed Agents 介面在設定與傳遞方式上有所不同:名冊項目沒有 max_usesmax_tokenscaching 欄位,且建議是透過執行緒事件送達,而非 advisor_tool_result 區塊。

諮詢的運作方式

每次諮詢都以平台產生、名為 anthropic.advisor 的執行緒執行,該執行緒會在諮詢完成時自行終止,而建議會以 agent.thread_message_received 事件傳遞至主執行緒。一次諮詢會發出標準的執行緒事件,並以保留名稱 anthropic.advisor 識別(執行緒生命週期事件以 agent_name 攜帶它,建議傳遞事件則以 from_agent_name 攜帶它),通常依下列順序:

  1. session.thread_created
  2. session.thread_status_running
  3. agent.thread_message_received(建議內容)
  4. session.thread_status_idlestop_reason: end_turn
  5. session.thread_status_terminated

諮詢不會發出 agent.tool_use 事件,工作階段的事件串流上也不會出現 agent.thread_message_sent 事件,因為諮詢的輸入是由平台組成,而非由代理傳送。若您列出顧問執行緒本身的事件,建議也會以 agent.thread_message_sent 事件出現在那裡。建議傳遞(事件 3)不保證會在顧問執行緒的 idle 與 terminated 事件之前送達,因此請勿將這些事件視為建議已送達的訊號。

您的用戶端能否讀取建議取決於顧問模型的政策,這與 Messages API 顧問工具上的結果變體區分方式一致。在那裡回傳純文字結果的顧問模型,在這裡會以可讀的文字內容傳遞建議;在那裡回傳已遮蔽結果的顧問模型,在這裡會於每個用戶端介面上以 [{"type": "redacted"}] 佔位符作為訊息內容傳遞,而代理本身仍會在伺服器端讀取完整建議。在前述範例中,Claude Opus 5 是遮蔽結果型顧問,因此您的用戶端會看到佔位符,而代理會讀取完整建議;若您希望建議在事件串流上可讀,請改選 Claude Opus 4.8 作為顧問。顧問的思考內容永遠不會顯示。用戶端無法自行傳送 redacted 區塊;包含此類區塊的事件會以 400 驗證錯誤被拒絕。

失敗或被中斷的諮詢絕不會使代理的輪次失敗:代理會在收到一則諮詢失敗的通用通知後繼續執行。諮詢期間的工作階段層級 user.interrupt 會終止顧問執行緒且不傳遞任何建議;帶有顧問執行緒 session_thread_iduser.interrupt 則只會放棄該次諮詢。

顧問執行緒

顧問不是名冊代理:協調者的 list_agents 工具看不到它,無法以 send_to_agent 向它傳送訊息,且只有工作階段的主執行緒可以諮詢它。名冊代理則不行。

顧問執行緒不受並行執行緒上限的限制。它們會出現在工作階段的執行緒清單中,其 agent 設為與設定完全相同的顧問形式({"type": "advisor", "model": ...}),且 parent_thread_id 設為主執行緒。

顧問端的提示快取是自動的;無需任何設定。諮詢依顧問模型的費率計費,其 token 會出現在顧問執行緒的用量以及工作階段的用量總計中。

移除顧問

若要移除顧問,請以不再包含顧問項目的名冊更新代理。若顧問是名冊中唯一的項目,請設定 "multiagent": null 以完全清除名冊。

建立工作階段

建立一個參照協調者的工作階段。協調者會視需要委派給其名冊中的代理。

session = client.beta.sessions.create(
    agent=coordinator.id,
    environment_id=environment.id,
)

將代理連接至 MCP 伺服器

MCP 伺服器是代理範圍的(每個代理定義宣告自己的伺服器與工具),而 vault 憑證是工作階段範圍的(建立工作階段時傳入的 vault_ids 會套用至每個執行緒)。這對您的整合有兩項影響:

  • 若要驗證 MCP 伺服器,請為所有代理所使用的每個 MCP 伺服器納入一個 vault 憑證。
  • 若要限制代理的存取權,請在其代理定義中只宣告它需要的伺服器。

建立工作階段時的代理設定覆寫可以取代協調者及其 self 副本的 MCP 伺服器。

research_agent = client.beta.agents.create(
    name="researcher",
    model="claude-haiku-4-5",
    mcp_servers=[
        {"type": "url", "name": "github", "url": "https://api.githubcopilot.com/mcp/"},
    ],
    tools=[{"type": "mcp_toolset", "mcp_server_name": "github"}],
)

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

session = client.beta.sessions.create(
    agent=coordinator.id,
    environment_id=environment.id,
    vault_ids=[vault.id],
)
print(session.id)

在此範例中,只有 researcher 宣告了 GitHub MCP 伺服器,因此協調者沒有存取權。工作階段的 vault_ids 會將 GitHub 憑證提供給 researcher 的執行緒。

執行緒

工作階段層級的事件串流/v1/sessions/{session_id}/events/stream)被視為主執行緒,包含所有執行緒活動的精簡檢視。您看不到子代理的完整活動,但可以看到其工作的開始與結束,以及工具權限請求等阻塞事件。

工作階段執行緒是您深入檢視特定代理活動的地方。

工作階段的 status 是所有代理活動的彙總;只要至少有一個執行緒為 running,整體工作階段狀態也會是 running

工作階段預算是工作階段所有執行緒共用的單一上限。達到上限時,各執行緒會獨立暫停,且每個執行緒的成本依該執行緒本身所使用的模型計價。

依下列方式列出與工作階段關聯的所有執行緒:

for thread in client.beta.sessions.threads.list(session.id):
    print(f"[{thread.agent.name}] {thread.status}")

完整清單包含主執行緒。主執行緒的 parent_thread_id 為 null。

主執行緒事件

這些事件會在位於 /v1/sessions/{session_id}/events/stream 的主執行緒上呈現多代理活動。訊息方向事件的命名是相對於其所出現之串流的執行緒而言:agent.thread_message_received 表示有訊息從另一個執行緒送達此執行緒,而 agent.thread_message_sent 表示此執行緒送出了一則訊息。例如,協調者委派的任務會以 agent.thread_message_received 事件送達子執行緒自己的串流。

類型說明
session.thread_created已建立一個執行緒。包含 session_thread_idagent_name
session.thread_status_running執行緒已開始活動。
session.thread_status_idle與該執行緒關聯的代理正在等待輸入。包含指出代理停止原因的 stop_reason
session.thread_status_terminated執行緒已封存或遇到終止性錯誤。
agent.thread_message_received在主執行緒上,某個代理向協調者傳送了報告或問題。包含 from_session_thread_idfrom_agent_namecontent
agent.thread_message_sent在主執行緒上,協調者向另一個代理傳送了任務或後續訊息。包含 to_session_thread_idto_agent_namecontent

顧問諮詢會以保留名稱 anthropic.advisor 發出相同的這些執行緒事件(在執行緒生命週期事件上為 agent_name,在建議傳遞事件上為 from_agent_name);事件順序請參閱為工作階段提供顧問

工作階段執行緒事件

關鍵事件會被代理轉送至主執行緒。不過,您可能仍想調查特定代理的推理與工具呼叫。若要這麼做,請串流或列出相關工作階段執行緒的事件。

每個工作階段執行緒在 /v1/sessions/{session_id}/threads/{thread_id}/stream 都有自己的事件串流,且它接受與工作階段層級串流相同的 event_deltas[] 參數,因此您可以在模型生成時預覽子代理的文字。一個連線只會預覽它正在讀取的執行緒:子執行緒的預覽永遠不會出現在工作階段層級的串流上,因此若要即時觀看子代理,請開啟它自己的執行緒串流。關於如何選擇加入、累積與核對預覽,請參閱預覽工作階段執行緒事件

with client.beta.sessions.threads.events.stream(
    thread.id,
    session_id=session.id,
) as stream:
    for event in stream:
        match event.type:
            case "agent.message":
                for block in event.content:
                    if block.type == "text":
                        print(block.text, end="")
            case "session.thread_status_idle":
                break

工具權限與自訂工具

若子代理需要您的用戶端提供某些東西,例如執行 always_ask 工具的權限,或自訂工具的結果,該事件會交叉發布至主執行緒,並以 session_thread_id 標示來源的工作階段執行緒。

{
  "type": "session.thread_status_idle",
  "id": "sevt_01ABC...",
  "session_thread_id": "sth_01DEF...",
  "agent_name": "code-reviewer",
  "stop_reason": {
    "type": "requires_action",
    "event_ids": ["sevt_01XYZ..."]
  }
}

發布 user.tool_confirmation(帶有 tool_use_id)或 user.custom_tool_result(帶有 custom_tool_use_id);伺服器會自動將回應路由至正確的執行緒。

下列範例擴充了工具確認處理程式以路由回覆。相同的模式也適用於 user.custom_tool_result

for event_id in stop.event_ids:
    client.beta.sessions.events.send(
        session.id,
        events=[
            {
                "type": "user.tool_confirmation",
                "tool_use_id": event_id,
                "result": "allow",
            }
        ],
    )

Was this page helpful?