multi-agent-orchestrator TypeScript 本地快速上手:用 MultiAgentOrchestrator 构建多智能体编排应用
【免费下载链接】agent-squadFlexible and powerful framework for managing multiple AI agents and handling complex conversations项目地址: https://gitcode.com/GitHub_Trending/mu/agent-squad
本文是 TypeScript 本地 Demo 的实战指南,围绕
multi-agent-orchestrator框架讲解如何在一个普通 Node.js 项目中通过MultiAgentOrchestrator初始化编排器、注册多个专业化BedrockLLMAgent、调用routeRequest完成意图分类与智能体路由,最终在本地终端跑通第一个多智能体问答应用。读完本文,你将掌握编排器的配置项含义、默认模型与默认存储行为,并能对照仓库中的交互式 Demo 扩展出流式输出、工具调用(Function Calling)与多类型智能体(Lex、Lambda、Bedrock Agent)混编的完整方案。
一、这份指南解决什么问题
多智能体应用的关键难点在于:如何把"哪个智能体来回答"这件事交给系统自动决策。multi-agent-orchestrator给出的答案是"编排器 + 意图分类器 + 智能体注册表"三层结构:用户输入先经过分类器判定意图并选出最合适的智能体,再由该智能体生成回答。
本文对应的官方入门文档(typescript-local-demo.md)给出了一个最小可运行示例:只用两个BedrockLLMAgent(Tech Agent 与 Health Agent),通过默认的 Bedrock 分类器实现"科技问题找技术智能体、健康问题找医疗智能体"的路由效果。仓库中的 本地交互式 Demo 则是该示例的超集版本,额外演示了流式输出、天气工具调用以及 Lex/Lambda/Bedrock Agent 的混编,两相结合即可从"能跑"走向"能用于生产场景"。
二、前置条件
在开始之前,请确保本地环境满足以下条件(与入门文档一致,并补充说明):
- Node.js 与 npm:本示例通过
npm init+npm install搭建工程,并依赖ts-node运行 TypeScript 文件,需要可用的 Node.js 环境。 - AWS 账户与相应权限:分类器与智能体都通过 Amazon Bedrock 的
Converse API发起推理请求,因此需要配置 AWS 凭证(如环境变量AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_REGION,或本机~/.aws/credentials),并确保账户已开通所需模型(anthropic.claude-3-5-sonnet-20240620-v1:0与anthropic.claude-3-haiku-20240307-v1:0)的访问权限。 - TypeScript 与 async/await 基础:示例大量使用
async function、await与异步迭代器(for await),需要对此有基本了解。
三、快速初始化项目
按照入门文档,在本地任意目录新建工程并安装依赖:
mkdir test_multi_agent_orchestrator cd test_multi_agent_orchestrator npm init npm install multi-agent-orchestrator安装完成后,在package.json的dependencies中会出现multi-agent-orchestrator依赖。仓库中的 examples/local-demo/package.json 使用了"multi-agent-orchestrator": "^0.0.17"并额外引入了dotenv,用于从.env文件加载环境变量。如果希望运行本文后面的交互式 Demo,建议同样安装dotenv与ts-node:
npm install dotenv npm install -D ts-node typescript四、编写第一个多智能体应用
4.1 初始化编排器
新建quickstart.ts,首先初始化MultiAgentOrchestrator:
import { MultiAgentOrchestrator } from "multi-agent-orchestrator"; const orchestrator = new MultiAgentOrchestrator({ config: { LOG_AGENT_CHAT: true, LOG_CLASSIFIER_CHAT: true, LOG_CLASSIFIER_RAW_OUTPUT: false, LOG_CLASSIFIER_OUTPUT: true, LOG_EXECUTION_TIMES: true, } });config是OrchestratorConfig的部分配置,未显式给出的项会与DEFAULT_CONFIG合并。对照 orchestrator.ts 中的默认配置,可梳理出每个开关的真实含义与默认值:
| 配置项 | 默认值 | 作用 |
|---|---|---|
LOG_AGENT_CHAT | false | 是否记录与智能体的对话交互日志 |
LOG_CLASSIFIER_CHAT | false | 是否记录与分类器的对话交互日志 |
LOG_CLASSIFIER_RAW_OUTPUT | false | 是否记录分类器未加工的原始输出 |
LOG_CLASSIFIER_OUTPUT | false | 是否记录分类器处理后的输出(即最终意图判定结果) |
LOG_EXECUTION_TIMES | false | 是否记录"分类耗时""智能体处理耗时"等各阶段执行时间 |
MAX_RETRIES | 3 | 分类器返回异常 XML 时的最大重试次数 |
USE_DEFAULT_AGENT_IF_NONE_IDENTIFIED | true | 分类器未识别出任何智能体时,是否回退到默认智能体;为false时向用户返回提示语 |
NO_SELECTED_AGENT_MESSAGE | "I'm sorry, I couldn't determine how to handle your request..." | 未选中任何智能体时展示给用户的兜底消息 |
GENERAL_ROUTING_ERROR_MSG_MESSAGE | 未定义 | 路由过程中发生异常时的通用错误消息 |
MAX_MESSAGE_PAIRS_PER_AGENT | 100 | 每个智能体保留的最大"用户-助手"消息对数(实际存储量为该值 × 2 条消息) |
需要说明的是:USE_DEFAULT_AGENT_IF_NONE_IDENTIFIED只有在通过setDefaultAgent或构造参数defaultAgent设置了默认智能体时才生效,该回退逻辑可在 orchestrator.ts 的 classifyRequest 方法 中看到。
4.2 添加专业化智能体
随后注册两个负责不同领域的BedrockLLMAgent:
import { BedrockLLMAgent } from "multi-agent-orchestrator"; orchestrator.addAgent( new BedrockLLMAgent({ name: "Tech Agent", description: "Specializes in technology areas including software development, hardware, AI, cybersecurity, blockchain, cloud computing, emerging tech innovations, and pricing/costs related to technology products and services.", }) ); orchestrator.addAgent( new BedrockLLMAgent({ name: "Health Agent", description: "Focuses on health and medical topics such as general wellness, nutrition, diseases, treatments, mental health, fitness, healthcare systems, and medical terminology or concepts.", }) );description不是装饰性字段,它同时服务于两条链路:
- 分类阶段:分类器把全部智能体的
name+description注入系统提示词,据此把用户输入路由到语义最匹配的智能体; - 生成阶段:
BedrockLLMAgent的默认系统提示词模板为You are a ${this.name}. ${this.description} ...,即智能体在回答时也会携带该描述作为角色设定(见 bedrockLLMAgent.ts 的构造函数)。
addAgent会以智能体name生成唯一 ID(去除非字母数字字符、空格转连字符、转小写),重复注册相同 ID 会抛出异常(见 orchestrator.ts 的 addAgent)。
BedrockLLMAgent除name/description外还支持以下常用选项(bedrockLLMAgent.ts 的类型定义):
modelId:使用的 Bedrock 模型 ID,默认anthropic.claude-3-haiku-20240307-v1:0(常量定义见 types/index.ts);region:Bedrock 服务区域,缺省时使用默认凭证链;streaming:是否流式返回,默认false;inferenceConfig:maxTokens、temperature、topP、stopSequences等推理参数;guardrailConfig:Bedrock Guardrails 的guardrailIdentifier与guardrailVersion;retriever:接入向量检索器,自动把检索上下文拼入系统提示词;toolConfig:tool(工具定义)、useToolHandler(工具执行回调)、toolMaxRecursions(工具调用最大轮数,默认 20);customSystemPrompt:自定义系统提示词模板与模板变量。
4.3 实现主逻辑并路由请求
接下来编写入口逻辑,向编排器提交一条用户查询:
const userId = "quickstart-user"; const sessionId = "quickstart-session"; const query = "What are the latest trends in AI?"; console.log(`\nUser Query: ${query}`); async function main() { try { const response = await orchestrator.routeRequest(query, userId, sessionId); console.log("\n** RESPONSE ** \n"); console.log(`> Agent ID: ${response.metadata.agentId}`); console.log(`> Agent Name: ${response.metadata.agentName}`); console.log(`> User Input: ${response.metadata.userInput}`); console.log(`> User ID: ${response.metadata.userId}`); console.log(`> Session ID: ${response.metadata.sessionId}`); console.log(`> Additional Parameters:`, response.metadata.additionalParams); console.log(`\n> Response: ${response.output}`); } catch (error) { console.error("An error occurred:", error); } } main();这里值得展开说明routeRequest的完整调用链(实现在 orchestrator.ts 的 routeRequest):
classifyRequest:先从存储中取出该userId + sessionId的聊天历史,再调用分类器classifier.classify(userInput, chatHistory);agentProcessRequest:把分类结果(selectedAgent)交给dispatchToAgent,后者从存储取回该智能体的历史对话后调用selectedAgent.processRequest(...)生成回答;- 结果封装:若智能体返回的是异步可迭代对象(流式响应),则返回
{ metadata, output: AccumulatorTransform, streaming: true };否则返回{ metadata, output: string, streaming: false },并在智能体saveChat开启时把本次问答写入存储; - 异常兜底:分类失败时
metadata.agentId为"no_agent_selected"、agentName为"No Agent",输出为NO_SELECTED_AGENT_MESSAGE。
response.metadata携带agentId、agentName、userInput、userId、sessionId、additionalParams等字段(接口定义见 orchestrator.ts 的 RequestMetadata),便于上层 UI 展示"由哪个智能体回答"。
4.4 运行应用
npx ts-node quickstart.ts运行后终端会依次打印:User Query→ 分类与路由日志(取决于LOG_*开关)→RESPONSE块(含 Agent ID / Agent Name / 最终回答)。由于示例查询 "What are the latest trends in AI?" 属于技术话题,分类器应将其路由给 Tech Agent。
五、默认行为与底层机制解读
入门文档的"Implementation Notes"部分点明了三条默认行为,这里结合源码给出更完整的解释。
5.1 默认分类器:BedrockClassifier + Claude 3.5 Sonnet
未显式传入classifier时,编排器使用new BedrockClassifier()(见 orchestrator.ts 构造函数)。该分类器的默认模型为anthropic.claude-3-5-sonnet-20240620-v1:0(见 bedrockClassifier.ts)。
分类器的判定并非"纯文本提示",而是通过工具调用(Function Calling)约束结构化输出:它把analyzePrompt工具(输入 schema 含userinput、selected_agent、confidence三个必填字段)注入ConverseCommand,强制模型返回结构化的分类结果,再据此查表定位智能体并解析置信度(见 bedrockClassifier.ts 的 processRequest)。若使用 Anthropic 或 Mistral Large 模型,还会额外设置toolChoice强制命中该工具。这解释了LOG_CLASSIFIER_RAW_OUTPUT(查看原始输出)与LOG_CLASSIFIER_OUTPUT(查看解析后的意图结果)两个开关的差异来源。
5.2 默认智能体:BedrockLLMAgent + Claude 3 Haiku
示例中的BedrockLLMAgent未指定modelId,因此使用默认的anthropic.claude-3-haiku-20240307-v1:0(见 bedrockLLMAgent.ts 的构造函数)。其底层通过 AWS SDK 的ConverseCommand/ConverseStreamCommand与 Bedrock 交互:非流式模式下会循环处理"模型输出 → 若含toolUse则执行工具 → 结果回填 → 再次调用",直到end_turn或达到toolMaxRecursions上限;流式模式下则逐 chunkyield文本增量(见 bedrockLLMAgent.ts 的 processRequest 与 handleStreamingResponse)。
5.3 默认存储:InMemoryChatStorage
未传入storage时使用new InMemoryChatStorage()(见 orchestrator.ts 构造函数)。它的实现基于内存Map,以${userId}#${sessionId}#${agentId}为键保存按时间戳排序的消息列表,并提供连续消息去重、maxHistorySize截断、跨智能体历史合并(供分类器参考)等能力(见 memoryChatStorage.ts)。这意味着服务重启后对话历史即丢失,生产环境应按需替换为 DynamoDB 或 SQL 存储。
六、进阶:仓库中的交互式本地 Demo
入门文档只覆盖了"单次请求",而仓库的 local-orchestrator.ts 是一个完整的终端交互式版本:通过readline循环接收用户输入,直到键入exit退出。它在快速入门示例基础上叠加了四类能力,非常适合作为下一步的参考实现。
6.1 多类型智能体混编
Demo 同时注册了四类智能体,展示了编排器对异构智能体的统一抽象(它们都继承自 agent.ts 的 Agent 基类):
BedrockLLMAgent(Tech Agent):开启streaming: true,并设置inferenceConfig.temperature: 0.1以获得更确定性的回答;LexBotAgent:接入 Amazon Lex 机器人,需要botId、botAliasId、localeId(必填,缺失会抛异常),底层通过RecognizeTextCommand调用 Lex Runtime V2(见 lexBotAgent.ts);AmazonBedrockAgent:接入 Bedrock 中已创建的 Agent,需要agentId与agentAliasId,支持enableTrace与streaming(见 amazonBedrockAgent.ts);LambdaAgent:把请求转发给 AWS Lambda 函数,支持自定义inputPayloadEncoder/outputPayloadDecoder编解码载荷(见 lambdaAgent.ts)。
Lex、Bedrock Agent、Lambda 三者的占位符({{REPLACE_WITH_...}})需要替换为你实际的 AWS 资源 ID 才能运行。
6.2 工具调用:天气智能体
Demo 中最具实战价值的是 Weather Agent:它通过toolConfig注册了一个Weather_Tool(输入为 WGS84 经纬度),并配套weatherToolHanlder回调与自定义系统提示词:
const weatherAgent = new BedrockLLMAgent({ name: "Weather Agent", description: "Specialized agent for giving weather condition from a city.", streaming: true, inferenceConfig: { temperature: 0.1 }, toolConfig: { tool: weatherToolDescription, useToolHandler: weatherToolHanlder, toolMaxRecursions: 5, } }); weatherAgent.setSystemPrompt(WEATHER_PROMPT); orchestrator.addAgent(weatherAgent);其中WEATHER_PROMPT明确约束"只调用 Weather_Tool、绝不编造数据、按经纬度推断城市位置"等行为(见 weather_tool.ts),而weatherToolHanlder在收到模型的toolUse请求后调用 Open-Meteo 公共天气 API,并把结果以toolResult消息回填给模型。这正是BedrockLLMAgent内部"工具调用循环"(见 5.2 节)的完整落地样例。
6.3 流式响应的消费方式
Demo 通过response.streaming标志区分两种响应:流式时用for await (const chunk of response.output)逐块写出文本,并先打印 metadata 再输出内容流;非流式时直接打印response.output字符串(见 local-orchestrator.ts)。该判断与编排器内部"输出是否为异步可迭代对象"的判定一一对应。
6.4 智能体注册表与重叠分析
Demo 还演示了两个实用 API:
orchestrator.getAllAgents():遍历已注册智能体的name与description;orchestrator.analyzeAgentOverlap():调用AgentOverlapAnalyzer对智能体描述做语义重叠分析,帮助开发者发现描述过于相似的智能体(可能引发错误路由),实现位于 agentOverlapAnalyzer.ts。
6.5 运行交互式 Demo
在仓库 examples/local-demo 目录下执行:
npm install # 配置 AWS 凭证与 REGION(可通过 .env 文件) npx ts-node local-orchestrator.ts启动后会打印全部已注册智能体并进入对话循环,输入问题后回车即可看到对应智能体的流式回答。注意:除 Tech Agent 与 Weather Agent 外,其余智能体需先替换占位符为真实 AWS 资源 ID;分类器所在区域通过REGION环境变量读取(见 bedrockClassifier.ts 构造函数)。
七、下一步:从 Demo 走向生产
入门文档的"Next Steps"给出了四条演进路径,这里补充对应的仓库依据:
- 添加更多专业化智能体:继续用
addAgent注册新的BedrockLLMAgent,并通过analyzeAgentOverlap()验证描述区分度;描述写得越具体、越不重叠,分类准确率越高; - 实现持久化存储:将默认的
InMemoryChatStorage替换为 DynamoDB 存储(storage/dynamoDbChatStorage.ts)或 SQL 存储(storage/sqlChatStorage.ts),在构造MultiAgentOrchestrator时通过storage参数注入,即可在服务重启后保留对话上下文; - 自定义错误处理:通过
config中的CLASSIFICATION_ERROR_MESSAGE、NO_SELECTED_AGENT_MESSAGE、GENERAL_ROUTING_ERROR_MSG_MESSAGE定制面向用户的兜底文案,并借助MAX_RETRIES、USE_DEFAULT_AGENT_IF_NONE_IDENTIFIED调节容错行为; - 实现流式响应:为
BedrockLLMAgent开启streaming: true,按 6.3 节的模式在服务端逐 chunk 消费response.output,即可向前端提供类打字机效果。
若想对比 Python 侧的实现,可参考仓库中的 python-local-demo.md,其 API 设计与 TypeScript 版本一一对应。至此,从入门文档的最小示例到仓库的交互式 Demo,你已经掌握了multi-agent-orchestrator在 TypeScript 本地环境下的完整实践路径。
【免费下载链接】agent-squadFlexible and powerful framework for managing multiple AI agents and handling complex conversations项目地址: https://gitcode.com/GitHub_Trending/mu/agent-squad
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考