作为 TypeScript 开发人员,我们一直在寻找让应用程序更智能、更具交互性的方法。虽然将人工智能集成到我们的应用程序中在传统上意味着要编写复杂的 Python 代码或管理大型语言模型,但这种情况正在发生变化。多亏了ADK-TS等框架,我们现在可以在 TypeScript 项目中直接构建智能 AI 代理。
在本教程中,我们将构建一个简单的多代理系统,该系统可处理天气查询和讲笑话。您将学习如何创建 AI 代理,这些代理可以:
- 理解和响应自然语言请求
- 使用外部 API 和工具获取真实数据
- 作为一个协调的系统协同工作
- 智能地处理不同类型的用户查询
在本教程结束时,您将拥有一个可用的 AI 代理系统,并了解如何将其扩展到您自己的项目中。
What are AI Agents?
当我们谈论 AI 代理时,我们是在谈论如何使我们的应用程序在处理用户请求时更加智能。与仅仅响应特定命令不同,人工智能代理可以理解用户的需求,并找出帮助他们的方法。
想想天气应用程序。传统应用可能需要用户点击特定按钮或输入准确的城市名称。而人工智能代理则可以理解自然问题,例如 "我今天需要雨伞吗?"或 "伦敦的天气如何?"并知道如何获取这些信息。
人工智能代理与普通的人工智能集成有何不同?它们能够:
- 理解对话的上下文
- 在需要时使用不同的工具和 API
- 决定如何处理请求
- 与其他代理合作解决问题
这些功能使 agentic 工作流模式(如顺序、并行和分层流水线)为现实世界中的人工智能应用提供了动力。
Why Build AI Agents in TypeScript?
作为 TypeScript 开发人员,我们习惯于构建结构良好、类型安全的应用。虽然 Python 一直是人工智能开发的首选语言,但 TypeScript 仍具有一些真正的优势:
- 我们可以使用现有的 TypeScript 技能和工具
- 我们可以获得强大的 IDE 支持和类型检查
- 我们的代理可以轻松地与我们的 TypeScript/JavaScript 后端集成
- 我们可以将 AI 代理无缝添加到现有的 Web 应用程序中
- 我们可以在部署现有服务的同时部署我们的代理
此外,使用 ADK-TS 等框架,我们无需学习复杂的 AI 概念或处理模型训练。框架将为您处理繁重的工作--模型集成、内置会话和内存管理、工具处理、可观察性等。
What Makes ADK-TS Different
ADK-TS 是一个 TypeScript 优先框架,可简化 AI 代理和多代理系统的构建。它使用 TypeScript 和 Zod 提供类型安全的 API,支持多个 LLM 提供商(OpenAI、Anthropic、Gemini 等),支持实时交互的流式响应,并包含用于有状态对话的内置内存管理。该框架完全开源,您可以在 GitHub 上查看 ADK-TS 源代码。
您还可以协调多个代理协同工作,为外部集成创建可重复使用的工具,并将代理作为 HTTP 服务器部署或集成到现有应用中。该框架使用熟悉的模式,例如流畅构建器和工厂函数,可自然融入您的 TypeScript 工作流。
Building Our First AI Agent System(构建我们的第一个人工智能代理系统)
我们将构建一个多代理系统,该系统有一个根代理,并协调两个专门的子代理:
- 根代理(路由器):接受用户请求并将工作委托给相应的子代理
- 天气代理:使用
weatherTool - Joke 代理:使用
jokeTool
每个子代理都有自己的工具和逻辑,而根代理则专注于路由请求。
Let's set up our project.
项目文件夹结构
以下是组织您的项目的推荐结构:
my-first-ai-agent/ Let's set up our project.项目文件夹结构以下是组织您的项目的推荐结构:my-first-ai-agent/ 这种结构将每个代理与其工具分隔到各自的文件夹中,有助于保持代码的条理性。您可以根据自己的偏好调整这种布局,但这种方法更易于维护,并可在添加更多代理时进行扩展。早期的复杂性管理会随着项目的增长而得到回报,您可以在了解软件开发中的技术债务中阅读更多相关信息。设置项目接下来,打开终端并运行以下命令:mkdir my-first-ai-agent
cd my-first-ai-agent
pnpm init
安装必要的依赖:pnpm add @iqai/adk dotenv zod
pnpm add -D typescript @types/node tsx
在 tsconfig.json 中创建基本的 TypeScript 配置:// tsconfig.json
{
"compilerOptions":{
"target":"ES2020"、
"module": "CommonJS"、
"outDir":"./dist"、
"rootDir":"./src"、
"strict": true、
"esModuleInterop": true
}
}
创建一个 .env 文件来存储您的环境变量:# .env
GOOGLE_API_KEY=your_google_api_key_here
LLM_MODEL=gemini-2.5-flash # 默认模型
您可以从 Google AI Studio 获取 Google API 密钥。ADK-TS 支持多个 LLM 提供商,但我们将使用 Gemini(默认提供商)。要了解有关配置不同 LLM 提供商的更多信息,请查看 ADK-TS 文档。最后,创建一个 .env.ts 文件来加载环境变量:// src/env.ts
import { config } from "dotenv";
import { z } from "zod";
config();
export const envSchema = z.object({
GOOGLE_API_KEY: z.string()、
LLM_MODEL: z.string().default("gemini-2.5-flash")、
});
export const env = envSchema.parse(process.env); 这就设置了我们的项目结构和配置。代理交互流程在深入了解代码之前,让我们先直观地了解一下我们的多代理系统是如何工作的:显示根代理如何与专门的子代理协调,通过外部 API 处理用户请求的综合图表。 该图显示了用户请求通过我们系统的完整流程:用户提出请求 - 用户提出一个自然语言问题,例如 "伦敦天气如何?"根代理分析 - 根代理接收请求并确定应由哪个专门代理来处理该请求根代理委托 - 根代理根据分析结果将任务分配给不同的代理、根代理将任务路由到相应的子代理(本例中为天气代理)选定的子代理执行 - 只有选定的子代理才会激活并使用其工具从外部 API 获取数据交付响应 - 子代理通过根代理将数据返回给用户如果用户请求的是一个笑话,那么笑话代理将被选中,而天气代理将保持不活动状态。 现在,让我们开始构建我们的工具和代理。Creating Tools for Our Agents 在构建代理之前,我们需要创建它们将使用的工具。工具是可重复使用的组件,它们封装了特定的功能,使代理更容易执行任务。这些工具使代理能够以结构化的方式与外部 API 或服务交互,从而扩展了代理的功能。我们将创建两个工具:一个用于获取天气信息,另一个用于获取笑话。 创建一个新文件 src/agents/weather-agent/tools.ts:// src/agents/weather-agent/tools.ts
import { createTool } from "@iqai/adk";
import * as z from "zod";
export const weatherTool = createTool({
name: "get_weather"、
description:"获取一个城市的当前天气"、
schema: z.object({
city: z.string().describe("City name")、
}),
fn: async ({ city }) => {
try {
const response = await fetch(
`https://wttr.in/${encodeURIComponent(city)}?
);
return await response.text();
} catch {
return `Weather unavailable for ${city}`;
}
},
}); 接下来,创建 src/agents/joke-agent/tools.ts:// src/agents/joke-agent/tools.ts
import { createTool } from "@iqai/adk";
export const jokeTool = createTool({
name: "get_joke"、
description:"获取随机笑话
fn: async () => {
try {
const response = await fetch(
"<https://official-joke-api.appspot.com/random_joke>"、
);
return await response.text();
} catch {
return "Joke unavailable right now.";
}
},
}); 这些工具提供了我们的代理所需的基本功能。天气工具可获取任何城市的天气信息,而笑话工具则可从 API 中获取随机笑话。Creating Our Specialized Agents 现在我们已准备好工具,让我们来创建将使用这些工具的代理。在 src/agents/weather-agent/agent.ts 中,创建天气代理:// src/agents/weather-agent/agent.ts
import { LlmAgent } from "@iqai/adk";
import { env } from ".../../env";
import { weatherTool } from "./tools";
export const getWeatherAgent = () => {
const weatherAgent = new LlmAgent({
name: "weather_agent"、
description:"提供给定城市的天气"、
model: env.LLM_MODEL、
tools:[weatherTool]、
});
返回 weatherAgent;
}; 类似地,在 src/agents/joke-agent/agent.ts 中,创建笑话代理:// src/agents/joke-agent/agent.ts
import { LlmAgent } from "@iqai/adk";
import { env } from ".../../env";
import { jokeTool } from "./tools";
export const getJokeAgent = () => {
const jokeAgent = new LlmAgent({
name: "joke_agent"、
description:"提供随机笑话"、
model: env.LLM_MODEL、
工具[jokeTool]、
});
返回 jokeAgent;
}; 每个代理都根据特定目的和完成工作所需的工具进行配置。 创建根代理根代理充当协调者的角色,将用户请求引导至相应的专门代理。当用户提出诸如 "巴黎天气如何?"或 "给我讲个笑话 "之类的问题时,根代理将决定由哪个子代理来处理该请求。如果用户提出的问题不属于这两个类别,根代理可使用默认消息进行响应,或优雅地进行处理。以下是我们在 src/agents/agent.ts 中的设置:// src/agents/agent.ts
import { AgentBuilder } from "@iqai/adk";
import { env } from ".../env";
import { getJokeAgent } from "./joke-agent/agent";
import { getWeatherAgent } from "./weather-agent/agent";
export const getRootAgent = () => {
const jokeAgent = getJokeAgent();
const weatherAgent = getWeatherAgent();
返回 AgentBuilder.create("root_agent")
.withDescription(
"根代理将任务分配给子代理,由子代理负责讲笑话和提供天气信息"。
)
.withInstruction(
`
您是路由代理。分析用户请求并将任务分配给相应的子代理:
- 对于任何有关天气、天气状况、温度或基于位置的天气查询的请求:委托给 weather_agent。
- 对于任何有关笑话、幽默、喜剧或要求讲笑话的请求:委托给笑话代理
不要自己回答问题。请始终根据请求类型委托给相应的子代理。
)
.withModel(env.LLM_MODEL)
.withSubAgents([jokeAgent, weatherAgent])
.build();
};Putting It All Together 最后,让我们创建使用代理系统的主应用程序文件。在 src/index.ts 中:// src/index.ts
import * as dotenv from "dotenv";
import { getRootAgent } from "./agents/agent";
dotenv.config();
async function main() {
const questions = ["How is weather in london?", "tell me a random joke"];
const { runner } = await getRootAgent();
for (const question of questions) {
console.log(`📝 Question: ${question}`);
const response = await runner.ask(question);
console.log(`🤖 Response: ${response}`);
}
}
main().catch(console.error);这段代码创建了我们的代理系统,并通过几个简单的问题对其进行了测试。根代理会自动找出哪个专门代理应处理每个请求。 运行您的代理要运行您的代理系统,请将这些脚本添加到您的 package.json 中:{
"脚本":{
"dev":"tsx watch src/index.ts"、
"build":"tsc"、
"start":"node dist/index.js"
}
} 然后使用以下命令运行代理:pnpm dev
你应该看到类似的输出:📝 问题:伦敦的天气如何?
🤖 答复:伦敦的天气是 ⛅️ +14°C。
📝问题:随便给我讲个笑话吧
🤖 回应:不知道:为什么程序员喜欢黑暗模式?因为光线会吸引虫子!运行代理测试脚本的输出示例使用 CLI 进行交互式测试您可以直接使用 ADK-TS CLI 与代理交互,而无需编写测试脚本。首先,安装 CLI:# 全局安装
pnpm add -g @iqai/adk-cli
# 或者使用 npx 而不进行全局安装
npx @iqai/adk-cli
CLI 提供了两种测试代理的方法:基于终端 聊天(adk run):基于 Web 的界面(adk web):这两种方法都能从 src/agents 目录中自动发现您的代理,让您无需编写任何脚本即可进行测试。有关详细的安装和使用说明,请查看 CLI 文档。Using ADK-TS Built-in ToolsADK-TS 还包含多个内置工具,您无需创建自定义实现即可立即使用。例如,如果您想在代理中添加网络搜索功能,您可以使用内置的 GoogleSearch 工具:import { GoogleSearch, LlmAgent } from "@iqai/adk";
import { env } from ".../env";
export const getSearchAgent = () => {
return new LlmAgent({
name: "search_agent"、
description:"搜索网络信息"、
model: env.LLM_MODEL、
tools:[new GoogleSearch()], // 使用内置工具
});
}; 请查看 工具文档,了解有哪些可用工具以及如何使用它们。Taking Your Agent Further 虽然我们的天气和笑话示例很简单,但您可以应用这些相同的模式来构建更复杂的代理。以下是一些现实世界中的应用:客户服务代理您可以扩展此模式来创建一个客户服务代理,使用产品数据库来回答产品问题,通过连接到您的订单系统来处理订单状态查询,在需要时将复杂问题升级到人工支持,并在多个问题中保持对话上下文。开发助理创建一个代理,通过分析拉取请求和提出改进建议来帮助完成编码任务,帮助 通过运行测试和分析日志来调试代码、根据代码注释生成文档以及审查代码中的安全问题。区块链投资组合代理构建一个代理,通过跟踪多个交易所的投资组合表现、使用价格数据 API 分析市场趋势、针对重大价格变化发送警报以及根据历史数据和当前市场条件提供有关潜在投资机会的见解,帮助用户管理其加密货币投资。Conclusion 在本教程中,我们使用 TypeScript 和 ADK-TS 构建了一个多代理系统。我们已经了解了如何创建专门的代理来处理特定任务,如何为我们的代理配备工具以赋予其真正的能力,如何通过根代理来协调多个代理,以及如何以可维护的方式构建我们的代码。这仅仅是您在 TypeScript 中使用 AI 代理所能做的工作的开始。无论您是在构建客户服务系统、区块链投资组合管理器,还是在构建全新的应用程序,我们在此介绍的模式都将帮助您创建有序而有效的基于代理的应用程序。下一步要查看本教程中使用的完整代码,您可以:运行 npx @iqai/adk-cli new --template simple-agent my-first-agent 以搭建一个新项目访问 GitHub 代码库探索源代码准备好构建自己的人工智能代理了吗?请查看 ADK-TS 文档,了解更多示例和高级功能。常见问题What is an AI agent, and how is it-different from a chatbot?A chatbot 遵循预定义脚本或基于模式匹配进行响应。人工智能代理则更进一步,它可以推理用户的需求,选择要调用的工具,并自行采取行动。例如,聊天机器人可能会将 "天气 "识别为一个关键字并返回一个预制回复,而人工智能代理则会理解 "我在伦敦需要雨伞吗?"并调用天气 API 来给出一个真实的答案。代理还可以将工作委托给其他代理,在不同的回合中保持上下文,并根据情况在多个工具之间做出决定。Can you build AI agents in TypeScript instead of Python? Yes. TypeScript 框架(如 ADK-TS、Vercel AI SDK 和 LangChain.js)均支持构建 AI 代理。您将获得相同的核心功能(工具调用、多代理协调、内存),并获得类型安全、IDE 自动完成以及与现有 Node.js 后端无缝集成等额外优势。What is a multi-agent system and when should you use one?多代理系统使用多个专门的代理来处理特定任务,并由一个路由请求的根代理进行协调。 例如,您不需要一个代理同时处理天气、笑话和搜索任务,而是将其分为一个天气代理、一个笑话代理和一个搜索代理。每个代理都将保持专注,更易于测试,并且可以独立更新。AgentBuilder.create("root_agent").withSubAgents([...]) 这样的根代理可以处理路由。 人工智能代理工具如何工作?工具是使代理能够与外部世界交互的功能。当代理收到仅靠训练数据无法回答的请求时,它会决定调用哪个工具,传递正确的参数,并使用结果形成响应。每个工具都有名称、描述、输入模式和执行功能。描述有助于 LLM 理解何时使用该工具。What LLM providers can you use with TypeScript AI agent frameworks?Most TypeScript 代理框架开箱即支持多个提供程序。常见的选项包括 OpenAI (GPT-4.1、GPT-5.4)、Anthropic (Claude)、Google (Gemini),以及通过 Ollama 或 Together AI 提供的开源模型。在创建代理时,您通常会配置提供程序和模型名称,例如 model:"gemini-2.5-flash" 或 model:"gpt-4.1"。切换提供商通常意味着更改一个配置值,而不是重写代理逻辑。