本教程演示如何使用方舟 Managed Agents 的多智能体协作能力,编排一个协调器 Agent 与三个专家 Agent,端到端完成一份定制销售提案:调研目标客户所在行业的优先事项、挑选最相关的案例、依据内部规则生成定价方案,最终由协调器整合为可交付的 Markdown 提案。
销售员工每接触一个新客户,都需要手动调研行业痛点、从案例库挑选相关成功案例、依据内部规则制定价格,再整合为一份定制提案。这些步骤各自需要不同的信息源和工具集,也存在依赖关系。
本教程用一个协调器 Agent 编排三个专家 Agent 完成这一流程:
- 行业调研员(prospect_researcher):联网调研客户行业的优先事项与动态。
- 资料管理员(case_study_picker):从案例库中挑选 2 个最相关的成功案例。
- 方案定价员(pricing_modeler):基于内部规则表生成 2 至 3 个定价方案。
三个专家各自拥有按角色划定的工具作用域——研究员只能联网、资料管理员和定价员只能读本地文件。协调器读取产品说明后,把它们的产出组装成 proposal.md。
- 已开通方舟 Managed Agents 和目标模型服务。
- 本地已安装 curl 或任意 HTTP 客户端。
- 准备好资源文件:产品一页说明、定价规则、5 至 10 个成功案例(Markdown 格式)。
将 API Key 与 Base URL 配置为环境变量:
export ARK_API_KEY="你的 API Key"
export ARK_BASE_URL="https://ark.cn-beijing.volces.com/api/v3"
第 1 步:设计 Sub-agent 的工具作用域
多智能体拆分的核心价值之一是权限隔离:每个 sub-agent 只保留完成其任务必需的工具。使用 agent_toolset_20260701 时,可以在 configs 数组里对单个工具设 enabled: false 关闭。
curl -X POST "$ARK_BASE_URL/agents" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
"name": "prospect_researcher",
"model": {"id": "doubao-seed-2-1-pro-260628"},
"system": "你是一位企业调研分析师。给定行业细分和企业规模,用 web_search / web_fetch 调研该细分市场的近期优先事项、痛点和动态。完成后通过 send_to_parent 返回结构化结果:{priorities, recent_moves, pain_points, sources}。",
"type": "agent_toolset_20260701",
{"name": "bash", "enabled": false},
{"name": "read", "enabled": false},
{"name": "write", "enabled": false},
{"name": "edit", "enabled": false},
{"name": "glob", "enabled": false},
{"name": "grep", "enabled": false}
curl -X POST "$ARK_BASE_URL/agents" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
"name": "case_study_picker",
"model": {"id": "doubao-seed-2-1-pro-260628"},
"system": "你是一位案例库管理员。给定行业和企业优先事项,从 /mnt/session/uploads/case_studies/ 中挑选 2 个最相关的案例,通过 send_to_parent 返回:{picks: [{file, customer, why_relevant}, ...]}。禁止访问其他目录。",
"type": "agent_toolset_20260701",
{"name": "web_fetch", "enabled": false},
{"name": "web_search", "enabled": false},
{"name": "write", "enabled": false},
{"name": "edit", "enabled": false}
curl -X POST "$ARK_BASE_URL/agents" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
"name": "pricing_modeler",
"model": {"id": "doubao-seed-2-1-pro-260628"},
"system": "你是一位定价建模师。基于 /mnt/session/uploads/pricing_rules.md 提供的规则,为给定席位数与用量层级生成 2 至 3 个定价选项:conservative(年付低单价)、flexible(月付高单价);若席位 > 500 增加 enterprise(含平台费)。通过 send_to_parent 返回:{options: [{name, structure, year_one_total}, ...]}。",
"type": "agent_toolset_20260701",
{"name": "web_fetch", "enabled": false},
{"name": "web_search", "enabled": false},
{"name": "write", "enabled": false},
{"name": "edit", "enabled": false}
三个专家均返回类似结构:
"id": "agent-20260708162137-mzhwx",
"name": "prospect_researcher",
将返回的 id 分别记录为 RESEARCHER_ID、PICKER_ID、PRICING_ID。
每个 sub-agent 必须在 System Prompt 里明确告诉它「完成后通过 send_to_parent 返回如下 JSON 结构」。契约越清晰,Coordinator 的下游拼装越可靠。以调研员为例:
"priorities": ["cost reduction", "clinician burnout"],
"recent_moves": ["merged with X in 2025-Q3"],
"pain_points": ["fragmented ops between clinics and hospitals"],
"sources": ["https://..."]
三个专家需要访问静态资料(案例库、产品说明、定价规则)。先通过 Files API 上传:
curl -X POST "$ARK_BASE_URL/files" \
-H "Authorization: Bearer $ARK_API_KEY" \
-F "file=@./product_one_pager.md" \
响应包含 id(file-...)与 status:
"id": "file-20260708200926-txv7h",
"filename": "product_one_pager.md",
"mime_type": "text/plain; charset=utf-8",
"created_at": 1783512566,
建议一次上传的资料清单:
- product_one_pager.md:产品一页说明。
- pricing_rules.md:内部定价规则表。
- case_studies/*.md:5 至 10 个成功案例。
分别记录为 FILE_PRODUCT_ID、FILE_PRICING_ID、FILE_CASE1_ID 等。
Coordinator 负责编排三个专家的调用顺序、把上下文在专家之间传递、最后组装产物。关键在于 multiagent.type: coordinator 字段。
curl -X POST "$ARK_BASE_URL/agents" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
"name": "proposal_coordinator",
"model": {"id": "doubao-seed-2-1-pro-260628"},
"system": "你是一位销售提案作者。收到目标客户信息后,按以下顺序调度专家:\n1. 把行业和企业规模发给 prospect_researcher。\n2. 同时把席位数和用量层级发给 pricing_modeler(可并行)。\n3. 收到研究员报告后,把行业、规模、优先事项发给 case_study_picker。\n4. 基于所有专家返回结果,将最终提案作为消息文本回复给用户,并最终将 Markdown 文件写入 /mnt/session/outputs/proposal.md。",
{"type": "agent_toolset_20260701"}
{"type": "agent", "id": "$RESEARCHER_ID"},
{"type": "agent", "id": "$PICKER_ID"},
{"type": "agent", "id": "$PRICING_ID"},
关键字段说明:
将返回的 id 记录为 COORDINATOR_ID。
第 5 步:创建 Environment 与 Session
创建 Environment:
curl -X POST "$ARK_BASE_URL/environments" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
"name": "proposal-coordinator-env",
"networking": {"type": "unrestricted"}
将返回的 id 记录为 ENVIRONMENT_ID。
创建 Session 并挂载资源:
curl -X POST "$ARK_BASE_URL/sessions" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
"agent": "$COORDINATOR_ID",
"environment_id": "$ENVIRONMENT_ID",
"title": "Custom proposal generation",
"file_id": "$FILE_PRODUCT_ID",
"mount_path": "product_one_pager.md"
"file_id": "$FILE_PRICING_ID",
"mount_path": "pricing_rules.md"
"file_id": "$FILE_CASE1_ID",
"mount_path": "case_studies/st_clair.md"
mount_path 会被系统自动加上 /mnt/session/uploads/ 前缀。例如传 "product_one_pager.md",实际挂在 /mnt/session/uploads/product_one_pager.md。Agent System Prompt 中让 Agent 读文件时,须使用带前缀的完整路径。
注意
单个 Session 最多挂载 100 个文件,Environment 与 Session 的 networking.type=unrestricted 仅用于教程演示。生产环境应按最小可用范围收敛出站主机。
Session 创建后,还可以通过 Session Resources API 动态添加或查询挂载的文件资源,适合在多轮对话中根据需要补充上下文:
curl -X POST "$ARK_BASE_URL/sessions/$SESSION_ID/resources" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
"file_id": "'"$FILE_ID"'"
curl "$ARK_BASE_URL/sessions/$SESSION_ID/resources" \
-H "Authorization: Bearer $ARK_API_KEY"
注意
运行时删除单条挂载资源的 API 目前未开放。如需清理,请重建 Session。
向 Session 发送一条用户消息,携带目标客户信息:
curl -X POST "$ARK_BASE_URL/sessions/$SESSION_ID/events" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
"text": "请为以下潜在客户生成一份定制销售提案:\n- 客户名称:Meridian Health\n- 行业:Regional healthcare system\n- 员工规模:8,500\n- 预计席位:600\n- 用量层级:Heavy"
Coordinator 派生(spawn)sub-agent、sub-agent 通过 send_to_parent 回传结果,全部通过事件流暴露给客户端。
订阅事件流:
curl -N "$ARK_BASE_URL/sessions/$SESSION_ID/events/stream" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Accept: text/event-stream"
典型事件序列如下(省略中间字段),可以看到并行 spawn 与串行依赖的调度过程:
# 阶段 1:Coordinator 思考并决定调度
agent.message "我将并行调度研究员和定价专家..."
# 阶段 2:并行 spawn 前两个 sub-agent
session.thread_created agent_name = prospect_researcher
agent.thread_message_sent "请调研区域医疗系统..."
session.thread_status_running prospect_researcher
session.thread_created agent_name = pricing_modeler
agent.thread_message_sent "席位 600、Heavy 用量..."
session.thread_status_running pricing_modeler
# 阶段 3:两个 sub-agent 并行工作(事件交织)
agent.tool_use name = web_search (researcher 线程)
agent.tool_use name = web_fetch (researcher 线程)
agent.tool_use name = read (pricing 线程)
agent.thread_message_sent {options: [...]} (pricing 结果)
session.thread_status_idle agent_name = pricing_modeler
agent.thread_message_sent {priorities: [...]} (researcher 结果)
session.thread_status_idle agent_name = prospect_researcher
# 阶段 5:串行 spawn 第三个 sub-agent
session.thread_created agent_name = case_study_picker
agent.thread_message_sent "行业:..., priorities:[...]"
session.thread_status_running case_study_picker
agent.tool_use name = bash / read (picker 线程)
agent.thread_message_sent {picks: [...]}
session.thread_status_idle agent_name = case_study_picker
# 阶段 6:Coordinator 整合所有信息,输出最终提案
agent.tool_use name = write, file_path = /mnt/session/outputs/proposal.md
agent.message "# 定制销售提案 ..."
观察要点:
- 资料管理员等研究员产出后才启动——需要 priorities 作为选案例的依据。
- 这种「并行 + 串行」的调度完全由 Coordinator 的 System Prompt 用自然语言驱动,无需编写调度代码。
Coordinator 将最终产物写入 /mnt/session/outputs/proposal.md。通过 Files API 按 Session 查询产物:
curl "$ARK_BASE_URL/files?scope_id=$SESSION_ID" \
-H "Authorization: Bearer $ARK_API_KEY" |
jq '.data[]? | {id, filename, bytes, status}'
生成的 Markdown 文件可以通过控制台下载到本地或转存到持久化存储。
一个带全部工具的单一 Agent 理论上也能完成本教程的任务。拆分为多个专家 + 一个协调器,主要价值在于三点:
- 权限隔离:每个 sub-agent 只保留完成任务所需的工具,缩小事故影响范围。
- 上下文经济:案例库可能有几百个文件,让它们只出现在资料管理员的上下文中,不污染 Coordinator 的主上下文。
- 编排清晰:Coordinator 只做「派谁去干什么」的决策,不掺和专家的具体工作,可维护性更高。
推荐拆分与不推荐拆分的场景对照: