概览
supervisor pattern 是一种 multi-agent 架构,其中中心 supervisor agent 会协调专门的工作 agent。当任务需要不同类型的专业能力时,这种方法尤其有效。与其构建一个跨领域管理工具选择的 agent,不如创建多个聚焦的专家,并由理解整体工作流的 supervisor 负责协调。 在本教程中,你将构建一个个人助手系统,并通过贴近真实场景的工作流展示这些优势。系统将协调两个职责根本不同的专家:- 一个处理日程安排、可用性检查和事件管理的 calendar agent。
- 一个管理沟通、起草消息和发送通知的 email agent。
为什么使用 supervisor?
Multi-agent 架构允许你将工具分配给不同 worker,每个 worker 都有自己的 prompt 或指令。设想一个可以直接访问所有日历和电子邮件 API 的 agent:它必须从许多相似工具中做选择,理解每个 API 要求的精确格式,并同时处理多个领域。如果性能下降,将相关工具及其 prompt 拆分为逻辑分组会很有帮助,也便于迭代改进。概念
本教程将介绍以下概念:设置
安装
本教程需要langchain 包:
npm install langchain
LangSmith
设置 LangSmith,以检查 agent 内部发生了什么。然后设置以下环境变量:export LANGSMITH_TRACING="true"
export LANGSMITH_API_KEY="..."
组件
你需要从 LangChain 的集成套件中选择一个聊天模型:- OpenAI
- Anthropic
- Azure
- Google Gemini
- Bedrock Converse
👉 Read the OpenAI chat model integration docs
npm install @langchain/openai
import { initChatModel } from "langchain";
process.env.OPENAI_API_KEY = "your-api-key";
const model = await initChatModel("gpt-5.4");
👉 Read the Anthropic chat model integration docs
npm install @langchain/anthropic
import { initChatModel } from "langchain";
process.env.ANTHROPIC_API_KEY = "your-api-key";
const model = await initChatModel("claude-sonnet-4-6");
👉 Read the Azure chat model integration docs
npm install @langchain/azure
import { initChatModel } from "langchain";
process.env.AZURE_OPENAI_API_KEY = "your-api-key";
process.env.AZURE_OPENAI_ENDPOINT = "your-endpoint";
process.env.OPENAI_API_VERSION = "your-api-version";
const model = await initChatModel("azure_openai:gpt-5.4");
👉 Read the Google GenAI chat model integration docs
npm install @langchain/google-genai
import { initChatModel } from "langchain";
process.env.GOOGLE_API_KEY = "your-api-key";
const model = await initChatModel("google-genai:gemini-2.5-flash-lite");
👉 Read the AWS Bedrock chat model integration docs
npm install @langchain/aws
import { initChatModel } from "langchain";
// Follow the steps here to configure your credentials:
// https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started.html
const model = await initChatModel("bedrock:gpt-5.4");
1. 定义工具
首先定义需要结构化输入的工具。在真实应用中,这些工具会调用实际 API,例如 Google Calendar、SendGrid 等。在本教程中,你将使用 stub 来演示这种模式。import { tool } from "langchain";
import { z } from "zod";
const createCalendarEvent = tool(
async ({ title, startTime, endTime, attendees, location }) => {
// Stub:在实践中,这会调用 Google Calendar API、Outlook API 等。
return `Event created: ${title} from ${startTime} to ${endTime} with ${attendees.length} attendees`;
},
{
name: "create_calendar_event",
description: "创建日历事件。需要精确的 ISO 日期时间格式。",
schema: z.object({
title: z.string(),
startTime: z.string().describe("ISO 格式:'2024-01-15T14:00:00'"),
endTime: z.string().describe("ISO 格式:'2024-01-15T15:00:00'"),
attendees: z.array(z.string()).describe("电子邮件地址"),
location: z.string().optional(),
}),
}
);
const sendEmail = tool(
async ({ to, subject, body, cc }) => {
// Stub:在实践中,这会调用 SendGrid、Gmail API 等。
return `Email sent to ${to.join(', ')} - Subject: ${subject}`;
},
{
name: "send_email",
description: "通过电子邮件 API 发送邮件。需要格式正确的地址。",
schema: z.object({
to: z.array(z.string()).describe("电子邮件地址"),
subject: z.string(),
body: z.string(),
cc: z.array(z.string()).optional(),
}),
}
);
const getAvailableTimeSlots = tool(
async ({ attendees, date, durationMinutes }) => {
// Stub:在实践中,这会查询日历 API
return ["09:00", "14:00", "16:00"];
},
{
name: "get_available_time_slots",
description: "检查指定日期中给定参会者的日历可用性。",
schema: z.object({
attendees: z.array(z.string()),
date: z.string().describe("ISO 格式:'2024-01-15'"),
durationMinutes: z.number(),
}),
}
);
2. 创建专门的 sub-agents
接下来,你将创建处理各个领域的专门 sub-agents。创建 calendar agent
Calendar agent 会理解自然语言日程安排请求,并将其转换为精确的 API 调用。它会处理日期解析、可用性检查和事件创建。import { createAgent } from "langchain";
const CALENDAR_AGENT_PROMPT = `
你是日历日程安排助手。
将自然语言日程安排请求(例如“下周二下午 2 点”)
解析为正确的 ISO 日期时间格式。
需要时使用 get_available_time_slots 检查可用性。
如果没有合适的时间段,请停止并在回复中确认不可用。
使用 create_calendar_event 安排事件。
始终在最终回复中确认已安排的内容。
`.trim();
const calendarAgent = createAgent({
model: llm,
tools: [createCalendarEvent, getAvailableTimeSlots],
systemPrompt: CALENDAR_AGENT_PROMPT,
});
const query = "将团队会议安排在下周二下午 2 点,持续 1 小时";
const stream = await calendarAgent.stream({
messages: [{ role: "user", content: query }]
});
for await (const step of stream) {
for (const update of Object.values(step)) {
if (update && typeof update === "object" && "messages" in update) {
for (const message of update.messages) {
console.log(message.toFormattedString());
}
}
}
}
================================== Ai Message ==================================
Tool Calls:
get_available_time_slots (call_EIeoeIi1hE2VmwZSfHStGmXp)
Call ID: call_EIeoeIi1hE2VmwZSfHStGmXp
Args:
attendees: []
date: 2024-06-18
duration_minutes: 60
================================= Tool Message =================================
Name: get_available_time_slots
["09:00", "14:00", "16:00"]
================================== Ai Message ==================================
Tool Calls:
create_calendar_event (call_zgx3iJA66Ut0W8S3NpT93kEB)
Call ID: call_zgx3iJA66Ut0W8S3NpT93kEB
Args:
title: 团队会议
start_time: 2024-06-18T14:00:00
end_time: 2024-06-18T15:00:00
attendees: []
================================= Tool Message =================================
Name: create_calendar_event
Event created: 团队会议 from 2024-06-18T14:00:00 to 2024-06-18T15:00:00 with 0 attendees
================================== Ai Message ==================================
团队会议已安排在下周二 6 月 18 日下午 2:00,持续 1 小时。如果需要添加参会者或地点,请告诉我!
"2024-01-16T14:00:00"),计算结束时间,调用 create_calendar_event,并返回自然语言确认。
创建 email agent
Email agent 负责消息撰写和发送。它专注于提取收件人信息、生成合适的主题行和正文,并管理电子邮件沟通。const EMAIL_AGENT_PROMPT = `
你是电子邮件助手。
根据自然语言请求撰写专业邮件。
提取收件人信息,并生成合适的主题行和正文。
使用 send_email 发送消息。
始终在最终回复中确认已发送的内容。
`.trim();
const emailAgent = createAgent({
model: llm,
tools: [sendEmail],
systemPrompt: EMAIL_AGENT_PROMPT,
});
const query = "向设计团队发送提醒,请他们审阅新的 mockups";
const stream = await emailAgent.stream({
messages: [{ role: "user", content: query }]
});
for await (const step of stream) {
for (const update of Object.values(step)) {
if (update && typeof update === "object" && "messages" in update) {
for (const message of update.messages) {
console.log(message.toFormattedString());
}
}
}
}
================================== Ai Message ==================================
Tool Calls:
send_email (call_OMl51FziTVY6CRZvzYfjYOZr)
Call ID: call_OMl51FziTVY6CRZvzYfjYOZr
Args:
to: ['design-team@example.com']
subject: 提醒:请审阅新的 mockups
body: 设计团队你好,
这是一封友好提醒,请你们尽早审阅新的 mockups。你们的反馈很重要,可以帮助确保项目时间线按计划推进。
如果有任何问题或需要更多信息,请告诉我。
谢谢!
此致,
================================= Tool Message =================================
Name: send_email
Email sent to design-team@example.com - Subject: 提醒:请审阅新的 mockups
================================== Ai Message ==================================
我已向设计团队发送提醒,请他们审阅新的 mockups。如果你还需要围绕这个主题进行其他沟通,请告诉我!
send_email,并返回确认。每个 sub-agent 都聚焦于狭窄任务,并配有特定领域的工具和 prompt,因此能更好地完成自己的任务。
3. 将 sub-agents 包装成工具
现在,将每个 sub-agent 包装成 supervisor 可以调用的工具。这是创建分层系统的关键架构步骤。Supervisor 会看到"schedule_event" 这样的高层工具,而不是 "create_calendar_event" 这样的低层工具。
const scheduleEvent = tool(
async ({ request }) => {
const result = await calendarAgent.invoke({
messages: [{ role: "user", content: request }]
});
const lastMessage = result.messages[result.messages.length - 1];
return lastMessage.text;
},
{
name: "schedule_event",
description: `
使用自然语言安排日历事件。
当用户想要创建、修改或检查日历约会时使用。
处理日期/时间解析、可用性检查和事件创建。
输入:自然语言日程安排请求(例如“下周二下午 2 点和设计团队开会”)
`.trim(),
schema: z.object({
request: z.string().describe("自然语言日程安排请求"),
}),
}
);
const manageEmail = tool(
async ({ request }) => {
const result = await emailAgent.invoke({
messages: [{ role: "user", content: request }]
});
const lastMessage = result.messages[result.messages.length - 1];
return lastMessage.text;
},
{
name: "manage_email",
description: `
使用自然语言发送电子邮件。
当用户想要发送通知、提醒或任何电子邮件沟通时使用。
处理收件人提取、主题生成和邮件撰写。
输入:自然语言电子邮件请求(例如“向他们发送会议提醒”)
`.trim(),
schema: z.object({
request: z.string().describe("自然语言电子邮件请求"),
}),
}
);
4. 创建 supervisor agent
现在创建用于编排 sub-agents 的 supervisor。Supervisor 只会看到高层工具,并在领域层级做路由决策,而不是在单个 API 层级做决策。const SUPERVISOR_PROMPT = `
你是乐于助人的个人助手。
你可以安排日历事件并发送电子邮件。
将用户请求拆解为合适的工具调用,并协调结果。
当请求涉及多个操作时,按顺序使用多个工具。
`.trim();
const supervisorAgent = createAgent({
model: llm,
tools: [scheduleEvent, manageEmail],
systemPrompt: SUPERVISOR_PROMPT,
});
5. 使用 supervisor
现在,使用需要跨多个领域协调的复杂请求测试完整系统:示例 1:简单单领域请求
const query = "将团队站会安排在明天上午 9 点";
const stream = await supervisorAgent.stream({
messages: [{ role: "user", content: query }]
});
for await (const step of stream) {
for (const update of Object.values(step)) {
if (update && typeof update === "object" && "messages" in update) {
for (const message of update.messages) {
console.log(message.toFormattedString());
}
}
}
}
================================== Ai Message ==================================
Tool Calls:
schedule_event (call_mXFJJDU8bKZadNUZPaag8Lct)
Call ID: call_mXFJJDU8bKZadNUZPaag8Lct
Args:
request: 将 Alice 和 Bob 的团队站会安排在明天上午 9 点。
================================= Tool Message =================================
Name: schedule_event
团队站会已安排在明天上午 9:00,参会者包括 Alice 和 Bob。如果你需要修改或添加更多详情,请告诉我!
================================== Ai Message ==================================
Alice 和 Bob 的团队站会已安排在明天上午 9:00。如果还需要其他安排或调整,请告诉我!
schedule_event,然后 calendar agent 处理日期解析和事件创建。
如需完整了解信息流,包括每次聊天模型调用的 prompt 和响应,请查看上述运行的 LangSmith trace。
示例 2:复杂多领域请求
const query =
"将和设计团队的会议安排在下周二下午 2 点,持续 1 小时," +
"并给他们发送电子邮件提醒,请他们审阅新的 mockups。";
const stream = await supervisorAgent.stream({
messages: [{ role: "user", content: query }]
});
for await (const step of stream) {
for (const update of Object.values(step)) {
if (update && typeof update === "object" && "messages" in update) {
for (const message of update.messages) {
console.log(message.toFormattedString());
}
}
}
}
================================== Ai Message ==================================
Tool Calls:
schedule_event (call_YA68mqF0koZItCFPx0kGQfZi)
Call ID: call_YA68mqF0koZItCFPx0kGQfZi
Args:
request: 下周二下午 2 点和设计团队开会,持续 1 小时
manage_email (call_XxqcJBvVIuKuRK794ZIzlLxx)
Call ID: call_XxqcJBvVIuKuRK794ZIzlLxx
Args:
request: 给设计团队发送电子邮件提醒,请他们审阅新的 mockups
================================= Tool Message =================================
Name: schedule_event
你与设计团队的会议已安排在下周二 6 月 18 日下午 2:00 到 3:00。如果你需要添加更多详情或进行修改,请告诉我!
================================= Tool Message =================================
Name: manage_email
我已向设计团队发送电子邮件提醒,请他们审阅新的 mockups。如果需要包含更多信息或收件人,请告诉我!
================================== Ai Message ==================================
你与设计团队的会议已安排在下周二 6 月 18 日下午 2:00 到 3:00。
我也已向设计团队发送电子邮件提醒,请他们审阅新的 mockups。
如果你想向会议添加更多详情,或在邮件中加入其他信息,请告诉我!
schedule_event,然后为提醒调用 manage_email。每个 sub-agent 完成自己的任务,supervisor 再将两个结果合成为连贯响应。
请参阅 LangSmith trace,查看上述运行的详细信息流,包括每次聊天模型调用的 prompt 和响应。
完整工作示例
以下是整合后的可运行脚本:Show 查看完整代码
Show 查看完整代码
/**
* 个人助手 Supervisor 示例
*
* 此示例演示 multi-agent 系统的工具调用模式。
* Supervisor agent 会协调包装成工具的专门 sub-agents(日历和电子邮件)。
*/
import { tool, createAgent } from "langchain";
import { ChatAnthropic } from "@langchain/anthropic";
import { z } from "zod";
// ============================================================================
// 步骤 1:定义低层 API 工具(stub)
// ============================================================================
const createCalendarEvent = tool(
async ({ title, startTime, endTime, attendees, location }) => {
// Stub:在实践中,这会调用 Google Calendar API、Outlook API 等。
return `Event created: ${title} from ${startTime} to ${endTime} with ${attendees.length} attendees`;
},
{
name: "create_calendar_event",
description: "创建日历事件。需要精确的 ISO 日期时间格式。",
schema: z.object({
title: z.string(),
startTime: z.string().describe("ISO 格式:'2024-01-15T14:00:00'"),
endTime: z.string().describe("ISO 格式:'2024-01-15T15:00:00'"),
attendees: z.array(z.string()).describe("电子邮件地址"),
location: z.string().optional().default(""),
}),
}
);
const sendEmail = tool(
async ({ to, subject, body, cc }) => {
// Stub:在实践中,这会调用 SendGrid、Gmail API 等。
return `Email sent to ${to.join(", ")} - Subject: ${subject}`;
},
{
name: "send_email",
description:
"通过电子邮件 API 发送邮件。需要格式正确的地址。",
schema: z.object({
to: z.array(z.string()).describe("电子邮件地址"),
subject: z.string(),
body: z.string(),
cc: z.array(z.string()).optional().default([]),
}),
}
);
const getAvailableTimeSlots = tool(
async ({ attendees, date, durationMinutes }) => {
// Stub:在实践中,这会查询日历 API
return ["09:00", "14:00", "16:00"];
},
{
name: "get_available_time_slots",
description:
"检查指定日期中给定参会者的日历可用性。",
schema: z.object({
attendees: z.array(z.string()),
date: z.string().describe("ISO 格式:'2024-01-15'"),
durationMinutes: z.number(),
}),
}
);
// ============================================================================
// 步骤 2:创建专门的 sub-agents
// ============================================================================
const llm = new ChatAnthropic({
model: "gpt-5.4",
});
const calendarAgent = createAgent({
model: llm,
tools: [createCalendarEvent, getAvailableTimeSlots],
systemPrompt: `
你是日历日程安排助手。
将自然语言日程安排请求(例如“下周二下午 2 点”)
解析为正确的 ISO 日期时间格式。
需要时使用 get_available_time_slots 检查可用性。
如果没有合适的时间段,请停止并在回复中确认不可用。
使用 create_calendar_event 安排事件。
始终在最终回复中确认已安排的内容。
`.trim(),
});
const emailAgent = createAgent({
model: llm,
tools: [sendEmail],
systemPrompt: `
你是电子邮件助手。
根据自然语言请求撰写专业邮件。
提取收件人信息,并生成合适的主题行和正文。
使用 send_email 发送消息。
始终在最终回复中确认已发送的内容。
`.trim(),
});
// ============================================================================
// 步骤 3:将 sub-agents 包装为 supervisor 可用的工具
// ============================================================================
const scheduleEvent = tool(
async ({ request }) => {
const result = await calendarAgent.invoke({
messages: [{ role: "user", content: request }],
});
const lastMessage = result.messages[result.messages.length - 1];
return lastMessage.text;
},
{
name: "schedule_event",
description: `
使用自然语言安排日历事件。
当用户想要创建、修改或检查日历约会时使用。
处理日期/时间解析、可用性检查和事件创建。
输入:自然语言日程安排请求(例如“下周二下午 2 点和设计团队开会”)
`.trim(),
schema: z.object({
request: z.string().describe("自然语言日程安排请求"),
}),
}
);
const manageEmail = tool(
async ({ request }) => {
const result = await emailAgent.invoke({
messages: [{ role: "user", content: request }],
});
const lastMessage = result.messages[result.messages.length - 1];
return lastMessage.text;
},
{
name: "manage_email",
description: `
使用自然语言发送电子邮件。
当用户想要发送通知、提醒或任何电子邮件沟通时使用。
处理收件人提取、主题生成和邮件撰写。
输入:自然语言电子邮件请求(例如“向他们发送会议提醒”)
`.trim(),
schema: z.object({
request: z.string().describe("自然语言电子邮件请求"),
}),
}
);
// ============================================================================
// 步骤 4:创建 supervisor agent
// ============================================================================
const supervisorAgent = createAgent({
model: llm,
tools: [scheduleEvent, manageEmail],
systemPrompt: `
你是乐于助人的个人助手。
你可以安排日历事件并发送电子邮件。
将用户请求拆解为合适的工具调用,并协调结果。
当请求涉及多个操作时,按顺序使用多个工具。
`.trim(),
});
// ============================================================================
// 步骤 5:使用 supervisor
// ============================================================================
// 示例:需要同时协调日历和电子邮件的用户请求
const userRequest =
"将和设计团队的会议安排在下周二下午 2 点,持续 1 小时," +
"并给他们发送电子邮件提醒,请他们审阅新的 mockups。";
console.log("用户请求:", userRequest);
console.log(`\n${"=".repeat(80)}\n`);
const stream = await supervisorAgent.stream({
messages: [{ role: "user", content: userRequest }],
});
for await (const step of stream) {
for (const update of Object.values(step)) {
if (update && typeof update === "object" && "messages" in update) {
for (const message of update.messages) {
console.log(message.toFormattedString());
}
}
}
}
理解架构
你的系统有三层。底层包含需要精确格式的严格 API 工具。中间层包含 sub-agents,它们接收自然语言,将其转换为结构化 API 调用,并返回自然语言确认。顶层包含 supervisor,它会路由到高层能力并综合结果。 这种关注点分离带来多个好处:每一层都有聚焦的职责,你可以添加新领域而不影响现有领域,也可以独立测试和迭代每一层。6. 添加 human-in-the-loop 审查
对于敏感操作,加入 human-in-the-loop 审查 是谨慎做法。LangChain 提供内置 middleware 用于审查工具调用,在本例中也就是 sub-agents 调用的工具。 为两个 sub-agents 添加 human-in-the-loop 审查:- 将
create_calendar_event和send_email工具配置为触发中断,并允许所有响应类型(approve、edit、reject) - 仅向顶层 agent 添加 checkpointer。暂停和恢复执行需要它。
import { createAgent, humanInTheLoopMiddleware } from "langchain";
import { MemorySaver } from "@langchain/langgraph";
const calendarAgent = createAgent({
model: llm,
tools: [createCalendarEvent, getAvailableTimeSlots],
systemPrompt: CALENDAR_AGENT_PROMPT,
middleware: [
humanInTheLoopMiddleware({
interruptOn: { create_calendar_event: true },
descriptionPrefix: "日历事件待批准",
}),
],
});
const emailAgent = createAgent({
model: llm,
tools: [sendEmail],
systemPrompt: EMAIL_AGENT_PROMPT,
middleware: [
humanInTheLoopMiddleware({
interruptOn: { send_email: true },
descriptionPrefix: "外发电子邮件待批准",
}),
],
});
const supervisorAgent = createAgent({
model: llm,
tools: [scheduleEvent, manageEmail],
systemPrompt: SUPERVISOR_PROMPT,
checkpointer: new MemorySaver(),
});
const query =
"将和设计团队的会议安排在下周二下午 2 点,持续 1 小时," +
"并给他们发送电子邮件提醒,请他们审阅新的 mockups。";
const config = { configurable: { thread_id: "6" } };
const interrupts: any[] = [];
const stream = await supervisorAgent.stream(
{ messages: [{ role: "user", content: query }] },
config
);
for await (const step of streamA) {
for (const update of Object.values(step)) {
for (const message of update.messages) {
console.log(message.toFormattedString());
}
const interrupt = update.__interrupt__?.[0];
interrupts.push(interrupt);
console.log(`\nINTERRUPTED: ${interrupt?.id}`);
}
}
================================== Ai Message ==================================
Tool Calls:
schedule_event (call_t4Wyn32ohaShpEZKuzZbl83z)
Call ID: call_t4Wyn32ohaShpEZKuzZbl83z
Args:
request: 将和设计团队的会议安排在下周二下午 2 点,持续 1 小时。
manage_email (call_JWj4vDJ5VMnvkySymhCBm4IR)
Call ID: call_JWj4vDJ5VMnvkySymhCBm4IR
Args:
request: 给设计团队发送电子邮件提醒,请他们在下周二下午 2 点的会议前审阅新的 mockups。
INTERRUPTED: 4f994c9721682a292af303ec1a46abb7
INTERRUPTED: 2b56f299be313ad8bc689eff02973f16
for (const interrupt of interrupts) {
for (const request of interrupt.value.actionRequests) {
console.log(`INTERRUPTED: ${interrupt.id}`);
console.log(`${request.description}\n`);
}
}
INTERRUPTED: 4f994c9721682a292af303ec1a46abb7
日历事件待批准
Tool: create_calendar_event
Args: {'title': '和设计团队开会', 'start_time': '2024-06-18T14:00:00', 'end_time': '2024-06-18T15:00:00', 'attendees': ['design team']}
INTERRUPTED: 2b56f299be313ad8bc689eff02973f16
外发电子邮件待批准
Tool: send_email
Args: {'to': ['designteam@example.com'], 'subject': '提醒:请在下周二下午 2 点会议前审阅新的 mockups', 'body': "团队你好,\n\n这是一封提醒,请在下周二下午 2 点的会议前审阅新的 mockups。你们的反馈和见解会对我们的讨论和后续步骤很有价值。\n\n请确保你们已经看过设计,并准备好在会议中分享想法。\n\n谢谢!\n\n此致,\n[你的名字]"}
Command 并通过 ID 引用每个中断,为其指定决策。更多细节请参阅 human-in-the-loop guide。为了演示,这里会接受日历事件,但编辑外发电子邮件的主题:
import { Command } from "@langchain/langgraph";
const resume: Record<string, any> = {};
for (const interrupt of interrupts) {
const actionRequest = interrupt.value.actionRequests[0];
if (actionRequest.name === "send_email") {
// 编辑电子邮件
const editedAction = { ...actionRequest };
editedAction.args.subject = "Mockups 提醒";
resume[interrupt.id] = {
decisions: [{ type: "edit", editedAction }]
};
} else {
resume[interrupt.id] = { decisions: [{ type: "approve" }] };
}
}
const resumeStream = await supervisorAgent.stream(
new Command({ resume }),
config
);
for await (const step of resumeStream) {
for (const update of Object.values(step)) {
if (update && typeof update === "object" && "messages" in update) {
for (const message of update.messages) {
console.log(message.toFormattedString());
}
}
}
}
================================= Tool Message =================================
Name: schedule_event
你与设计团队的会议已安排在下周二 6 月 18 日下午 2:00 到 3:00。
================================= Tool Message =================================
Name: manage_email
你给设计团队的电子邮件提醒已发送。发送内容如下:
- 收件人:designteam@example.com
- 主题:Mockups 提醒
- 正文:提醒他们在下周二下午 2 点会议前审阅新的 mockups,并请求他们准备反馈和讨论内容。
如果你还需要其他帮助,请告诉我!
================================== Ai Message ==================================
- 你与设计团队的会议已安排在下周二 6 月 18 日下午 2:00 到 3:00。
- 已向设计团队发送电子邮件提醒,请他们在会议前审阅新的 mockups。
如果你还需要其他帮助,请告诉我!
7. 高级:控制信息流
默认情况下,sub-agents 只会接收来自 supervisor 的请求字符串。你可能想传递额外上下文,例如对话历史或用户偏好。向 sub-agents 传递额外对话上下文
import { getCurrentTaskInput } from "@langchain/langgraph";
import { type BuiltInState, HumanMessage } from "langchain";
const scheduleEvent = tool(
async ({ request }, config) => {
// 自定义 sub-agent 接收的上下文
// 从 config 访问完整线程消息
const currentMessages = getCurrentTaskInput<BuiltInState>(config).messages;
const originalUserMessage = currentMessages.find(HumanMessage.isInstance);
const prompt = `
你正在协助处理以下用户问题:
${originalUserMessage?.content || "没有可用上下文"}
你负责处理以下子请求:
${request}
`.trim();
const result = await calendarAgent.invoke({
messages: [{ role: "user", content: prompt }],
});
const lastMessage = result.messages[result.messages.length - 1];
return lastMessage.text;
},
{
name: "schedule_event",
description: "使用自然语言安排日历事件。",
schema: z.object({
request: z.string().describe("自然语言日程安排请求"),
}),
}
);
你可以在 LangSmith trace 的聊天模型调用中查看 sub-agent 接收到的完整上下文。
控制 supervisor 接收的信息
你还可以自定义哪些信息会回流到 supervisor:const scheduleEvent = tool(
async ({ request }) => {
const result = await calendarAgent.invoke({
messages: [{ role: "user", content: request }]
});
const lastMessage = result.messages[result.messages.length - 1];
// 选项 1:仅返回确认消息
return lastMessage.text;
// 选项 2:返回结构化数据
// return JSON.stringify({
// status: "success",
// event_id: "evt_123",
// summary: lastMessage.text
// });
},
{
name: "schedule_event",
description: "使用自然语言安排日历事件。",
schema: z.object({
request: z.string().describe("自然语言日程安排请求"),
}),
}
);
如需查看演示完整 supervisor pattern、human-in-the-loop 审查和高级信息流控制的完整工作示例,请参阅 LangChain.js 示例中的
supervisor_complete.ts。8. 关键要点
Supervisor pattern 会创建多层抽象,其中每一层都有明确职责。设计 supervisor 系统时,应从清晰的领域边界开始,并为每个 sub-agent 提供聚焦的工具和 prompt。为 supervisor 编写清晰的工具描述,在集成前独立测试每一层,并根据具体需求控制信息流。何时使用 supervisor pattern当你有多个彼此不同的领域(日历、电子邮件、CRM、数据库)、每个领域都有多个工具或复杂逻辑、希望集中控制工作流,并且 sub-agents 不需要直接与用户对话时,请使用 supervisor pattern。对于只有少量工具的简单场景,请使用单个 agent。当 agents 需要与用户对话时,请改用 handoffs。对于 agents 之间的 peer-to-peer 协作,请考虑其他 multi-agent patterns。
后续步骤
了解用于 agent-to-agent 对话的 handoffs,探索 context engineering 以微调信息流,阅读 multi-agent overview 以比较不同模式,并使用 LangSmith 调试和监控你的 multi-agent 系统。Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

