/** * AG-UI 工具调用示例 * * 展示 Agent 如何调用工具并流式传输参数和结果 * * 参考文档: modules/events.md (行 938-1066) * * 事件流: * 1. ToolCallStart - 工具调用开始 * 2. ToolCallArgs (多次) - 流式传输参数 * 3. ToolCallEnd - 参数传输完成 * 4. ToolCallResult - 工具执行结果 */ import { AbstractAgent, RunAgent, RunAgentInput, EventType, BaseEvent, } from "@ag-ui/client" import { Observable } from "rxjs" /** * 工具定义示例 */ interface Tool { name: string description: string parameters: Record } const weatherTool: Tool = { name: "get_weather", description: "Get current weather for a location", parameters: { type: "object", properties: { location: { type: "string", description: "City name", }, unit: { type: "string", enum: ["celsius", "fahrenheit"], }, }, required: ["location"], }, } class ToolCallingAgent extends AbstractAgent { run(input: RunAgentInput): RunAgent { const { threadId, runId } = input return () => new Observable((observer) => { observer.next({ type: EventType.RUN_STARTED, threadId, runId, }) // 模拟 Agent 分析用户请求后决定调用工具 const toolCallId = `tool_${Date.now()}` const messageId = `msg_${Date.now()}` // 1. 发送文本消息说明 observer.next({ type: EventType.TEXT_MESSAGE_START, messageId, role: "assistant", }) observer.next({ type: EventType.TEXT_MESSAGE_CONTENT, messageId, delta: "Let me check the weather for you.", }) observer.next({ type: EventType.TEXT_MESSAGE_END, messageId, }) // 2. 开始工具调用 observer.next({ type: EventType.TOOL_CALL_START, toolCallId, toolCallName: "get_weather", parentMessageId: messageId, }) // 3. 流式传输参数(分块发送) observer.next({ type: EventType.TOOL_CALL_ARGS, toolCallId, delta: '{"loc', // 参数片段 1 }) observer.next({ type: EventType.TOOL_CALL_ARGS, toolCallId, delta: 'ation":', // 参数片段 2 }) observer.next({ type: EventType.TOOL_CALL_ARGS, toolCallId, delta: ' "San Francisco"}', // 参数片段 3 }) // 4. 参数传输完成 observer.next({ type: EventType.TOOL_CALL_END, toolCallId, }) // 5. 工具执行结果(模拟) setTimeout(() => { observer.next({ type: EventType.TOOL_CALL_RESULT, toolCallId, content: JSON.stringify({ location: "San Francisco", temperature: "18°C", condition: "Partly cloudy", }), }) // 6. 基于工具结果的响应 const responseMsgId = `msg_${Date.now()}_response` observer.next({ type: EventType.TEXT_MESSAGE_START, messageId: responseMsgId, role: "assistant", }) observer.next({ type: EventType.TEXT_MESSAGE_CONTENT, messageId: responseMsgId, delta: "The current weather in San Francisco is 18°C and partly cloudy.", }) observer.next({ type: EventType.TEXT_MESSAGE_END, messageId: responseMsgId, }) observer.next({ type: EventType.RUN_FINISHED, threadId, runId, }) observer.complete() }, 1000) }) } } // 使用示例 const agent = new ToolCallingAgent() agent .runAgent({ runId: "run_tool_example", threadId: "thread_123", messages: [ { id: "user_1", role: "user", content: "What's the weather in San Francisco?", }, ], tools: [weatherTool as any], context: [], }) .subscribe({ next: (event) => { switch (event.type) { case EventType.TOOL_CALL_START: console.log(`[Tool Call] Starting: ${(event as any).toolCallName}`) break case EventType.TOOL_CALL_ARGS: process.stdout.write((event as any).delta) break case EventType.TOOL_CALL_END: console.log("\n[Tool Call] Arguments complete") break case EventType.TOOL_CALL_RESULT: console.log("[Tool Result]", (event as any).content) break default: console.log(`[${event.type}]`) } }, complete: () => console.log("Tool call flow completed"), }) export { ToolCallingAgent, weatherTool }