import { initChatModel } from "langchain";process.env.GOOGLE_API_KEY = "your-api-key";const model = await initChatModel("google-genai:gemini-2.5-flash-lite");
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";const model = new ChatGoogleGenerativeAI({ model: "gemini-2.5-flash-lite", apiKey: "your-api-key"});
日历智能体理解自然语言调度请求,并将其转换为精确的 API 调用。它处理日期解析、可用性检查和事件创建。
import { createAgent } from "langchain";const CALENDAR_AGENT_PROMPT = `You are a calendar scheduling assistant.Parse natural language scheduling requests (e.g., 'next Tuesday at 2pm')into proper ISO datetime formats.Use get_available_time_slots to check availability when needed.If there is no suitable time slot, stop and confirm unavailability in your response.Use create_calendar_event to schedule events.Always confirm what was scheduled in your final response.`.trim();const calendarAgent = createAgent({ model: llm, tools: [createCalendarEvent, getAvailableTimeSlots], systemPrompt: CALENDAR_AGENT_PROMPT,});
测试日历智能体,看看它如何处理自然语言调度:
const query = "Schedule a team meeting next Tuesday at 2pm for 1 hour";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: Team Meeting start_time: 2024-06-18T14:00:00 end_time: 2024-06-18T15:00:00 attendees: []================================= Tool Message =================================Name: create_calendar_eventEvent created: Team Meeting from 2024-06-18T14:00:00 to 2024-06-18T15:00:00 with 0 attendees================================== Ai Message ==================================The team meeting has been scheduled for next Tuesday, June 18th, at 2:00 PM and will last for 1 hour. If you need to add attendees or a location, please let me know!
该智能体将 “next Tuesday at 2pm” 解析为 ISO 格式(“2024-01-16T14:00:00”),计算结束时间,调用 create_calendar_event,并返回自然语言确认。
const EMAIL_AGENT_PROMPT = `You are an email assistant.Compose professional emails based on natural language requests.Extract recipient information and craft appropriate subject lines and body text.Use send_email to send the message.Always confirm what was sent in your final response.`.trim();const emailAgent = createAgent({ model: llm, tools: [sendEmail], systemPrompt: EMAIL_AGENT_PROMPT,});
使用自然语言请求测试电子邮件智能体:
const query = "Send the design team a reminder about reviewing the new 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: Reminder: Please Review the New Mockups body: Hi Design Team,This is a friendly reminder to review the new mockups at your earliest convenience. Your feedback is important to ensure that we stay on track with our project timeline.Please let me know if you have any questions or need additional information.Thank you!Best regards,================================= Tool Message =================================Name: send_emailEmail sent to design-team@example.com - Subject: Reminder: Please Review the New Mockups================================== Ai Message ==================================I've sent a reminder to the design team asking them to review the new mockups. If you need any further communication on this topic, just let me know!
现在创建协调子智能体的监督者。监督者只看到高级工具,并在领域级别(而不是单个 API 级别)做出路由决策。
const SUPERVISOR_PROMPT = `You are a helpful personal assistant.You can schedule calendar events and send emails.Break down user requests into appropriate tool calls and coordinate the results.When a request involves multiple actions, use multiple tools in sequence.`.trim();const supervisorAgent = createAgent({ model: llm, tools: [scheduleEvent, manageEmail], systemPrompt: SUPERVISOR_PROMPT,});
const query = "Schedule a team standup for tomorrow at 9am";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: Schedule a team standup for tomorrow at 9am with Alice and Bob.================================= Tool Message =================================Name: schedule_eventThe team standup has been scheduled for tomorrow at 9:00 AM with Alice and Bob. If you need to make any changes or add more details, just let me know!================================== Ai Message ==================================The team standup with Alice and Bob is scheduled for tomorrow at 9:00 AM. If you need any further arrangements or adjustments, please let me know!
const query = "Schedule a meeting with the design team next Tuesday at 2pm for 1 hour, " + "and send them an email reminder about reviewing the new 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: meeting with the design team next Tuesday at 2pm for 1 hour manage_email (call_XxqcJBvVIuKuRK794ZIzlLxx) Call ID: call_XxqcJBvVIuKuRK794ZIzlLxx Args: request: send the design team an email reminder about reviewing the new mockups================================= Tool Message =================================Name: schedule_eventYour meeting with the design team is scheduled for next Tuesday, June 18th, from 2:00pm to 3:00pm. Let me know if you need to add more details or make any changes!================================= Tool Message =================================Name: manage_emailI've sent an email reminder to the design team requesting them to review the new mockups. If you need to include more information or recipients, just let me know!================================== Ai Message ==================================Your meeting with the design team is scheduled for next Tuesday, June 18th, from 2:00pm to 3:00pm.I've also sent an email reminder to the design team, asking them to review the new mockups.Let me know if you'd like to add more details to the meeting or include additional information in the email!
/** * 个人助手监督者示例 * * 此示例演示了多智能体系统的工具调用模式。 * 一个监督者智能体协调专门的子智能体(日历和电子邮件), * 这些子智能体被包装为工具。 */import { tool, createAgent } from "langchain";import { ChatAnthropic } from "@langchain/anthropic";import { z } from "zod";// ============================================================================// 步骤 1:定义底层 API 工具(存根)// ============================================================================const createCalendarEvent = tool( async ({ title, startTime, endTime, attendees, location }) => { // 存根:在实践中,这会调用 Google Calendar API、Outlook API 等。 return `Event created: ${title} from ${startTime} to ${endTime} with ${attendees.length} attendees`; }, { name: "create_calendar_event", description: "Create a calendar event. Requires exact ISO datetime format.", schema: z.object({ title: z.string(), startTime: z.string().describe("ISO format: '2024-01-15T14:00:00'"), endTime: z.string().describe("ISO format: '2024-01-15T15:00:00'"), attendees: z.array(z.string()).describe("email addresses"), location: z.string().optional().default(""), }), });const sendEmail = tool( async ({ to, subject, body, cc }) => { // 存根:在实践中,这会调用 SendGrid、Gmail API 等。 return `Email sent to ${to.join(", ")} - Subject: ${subject}`; }, { name: "send_email", description: "Send an email via email API. Requires properly formatted addresses.", schema: z.object({ to: z.array(z.string()).describe("email addresses"), subject: z.string(), body: z.string(), cc: z.array(z.string()).optional().default([]), }), });const getAvailableTimeSlots = tool( async ({ attendees, date, durationMinutes }) => { // 存根:在实践中,这会查询日历 API return ["09:00", "14:00", "16:00"]; }, { name: "get_available_time_slots", description: "Check calendar availability for given attendees on a specific date.", schema: z.object({ attendees: z.array(z.string()), date: z.string().describe("ISO format: '2024-01-15'"), durationMinutes: z.number(), }), });// ============================================================================// 步骤 2:创建专门的子智能体// ============================================================================const llm = new ChatAnthropic({ model: "gpt-5.4",});const calendarAgent = createAgent({ model: llm, tools: [createCalendarEvent, getAvailableTimeSlots], systemPrompt: `You are a calendar scheduling assistant.Parse natural language scheduling requests (e.g., 'next Tuesday at 2pm')into proper ISO datetime formats.Use get_available_time_slots to check availability when needed.If there is no suitable time slot, stop and confirm unavailability in your response.Use create_calendar_event to schedule events.Always confirm what was scheduled in your final response. `.trim(),});const emailAgent = createAgent({ model: llm, tools: [sendEmail], systemPrompt: `You are an email assistant.Compose professional emails based on natural language requests.Extract recipient information and craft appropriate subject lines and body text.Use send_email to send the message.Always confirm what was sent in your final response. `.trim(),});// ============================================================================// 步骤 3:将子智能体包装为监督者的工具// ============================================================================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: `Schedule calendar events using natural language.Use this when the user wants to create, modify, or check calendar appointments.Handles date/time parsing, availability checking, and event creation.Input: Natural language scheduling request (e.g., 'meeting with design team next Tuesday at 2pm') `.trim(), schema: z.object({ request: z.string().describe("Natural language scheduling request"), }), });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: `Send emails using natural language.Use this when the user wants to send notifications, reminders, or any email communication.Handles recipient extraction, subject generation, and email composition.Input: Natural language email request (e.g., 'send them a reminder about the meeting') `.trim(), schema: z.object({ request: z.string().describe("Natural language email request"), }), });// ============================================================================// 步骤 4:创建监督者智能体// ============================================================================const supervisorAgent = createAgent({ model: llm, tools: [scheduleEvent, manageEmail], systemPrompt: `You are a helpful personal assistant.You can schedule calendar events and send emails.Break down user requests into appropriate tool calls and coordinate the results.When a request involves multiple actions, use multiple tools in sequence. `.trim(),});// ============================================================================// 步骤 5:使用监督者// ============================================================================// 示例:需要日历和电子邮件协调的用户请求const userRequest = "Schedule a meeting with the design team next Tuesday at 2pm for 1 hour, " + "and send them an email reminder about reviewing the new mockups.";console.log("User Request:", 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 工具。中间层包含接受自然语言、将其转换为结构化 API 调用并返回自然语言确认的子智能体。顶层包含路由到高级功能并综合结果的监督者。这种关注点分离提供了几个好处:每层都有一个专注的职责,你可以添加新领域而不影响现有领域,并且你可以独立测试和迭代每一层。
const query = "Schedule a meeting with the design team next Tuesday at 2pm for 1 hour, " + "and send them an email reminder about reviewing the new 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: Schedule a meeting with the design team next Tuesday at 2pm for 1 hour. manage_email (call_JWj4vDJ5VMnvkySymhCBm4IR) Call ID: call_JWj4vDJ5VMnvkySymhCBm4IR Args: request: Send an email reminder to the design team about reviewing the new mockups before our meeting next Tuesday at 2pm.INTERRUPTED: 4f994c9721682a292af303ec1a46abb7INTERRUPTED: 2b56f299be313ad8bc689eff02973f16
这次我们中断了执行。让我们检查中断事件:
for (const interrupt of interrupts) { for (const request of interrupt.value.actionRequests) { console.log(`INTERRUPTED: ${interrupt.id}`); console.log(`${request.description}\n`); }}
INTERRUPTED: 4f994c9721682a292af303ec1a46abb7Calendar event pending approvalTool: create_calendar_eventArgs: {'title': 'Meeting with the Design Team', 'start_time': '2024-06-18T14:00:00', 'end_time': '2024-06-18T15:00:00', 'attendees': ['design team']}INTERRUPTED: 2b56f299be313ad8bc689eff02973f16Outbound email pending approvalTool: send_emailArgs: {'to': ['designteam@example.com'], 'subject': 'Reminder: Review New Mockups Before Meeting Next Tuesday at 2pm', 'body': "Hello Team,\n\nThis is a reminder to review the new mockups ahead of our meeting scheduled for next Tuesday at 2pm. Your feedback and insights will be valuable for our discussion and next steps.\n\nPlease ensure you've gone through the designs and are ready to share your thoughts during the meeting.\n\nThank you!\n\nBest regards,\n[Your Name]"}
我们可以通过使用 Command 引用其 ID 来为每个中断指定决策。有关更多详细信息,请参阅人在回路中指南。为演示目的,这里我们将接受日历事件,但编辑外发电子邮件的主题:
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 reminder"; 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_eventYour meeting with the design team has been scheduled for next Tuesday, June 18th, from 2:00 pm to 3:00 pm.================================= Tool Message =================================Name: manage_emailYour email reminder to the design team has been sent. Here’s what was sent:- Recipient: designteam@example.com- Subject: Mockups reminder- Body: A reminder to review the new mockups before the meeting next Tuesday at 2pm, with a request for feedback and readiness for discussion.Let me know if you need any further assistance!================================== Ai Message ==================================- Your meeting with the design team has been scheduled for next Tuesday, June 18th, from 2:00 pm to 3:00 pm.- An email reminder has been sent to the design team about reviewing the new mockups before the meeting.Let me know if you need any further assistance!