3398 words
17 minutes
TypeScript 在 AI Agent 上的应用
2026-04-10

TypeScript 在 AI Agent 上的应用#

在 AI Agent 开发领域,TypeScript 正在成为应用层开发的首选语言。本文将深入探讨 TypeScript 在 AI Agent 应用中的优势、核心库使用、类型安全的工具调用机制,以及实际的架构设计。

1. 为什么 AI Agent 项目需要 TypeScript + Python#

现代 AI Agent 项目通常采用双语言架构,这种分工充分发挥了各自的优势。

Python 的角色:模型层#

Python 在 AI Agent 的模型层占据主导地位,这得益于其丰富的生态系统:

  • AI/ML 生态:PyTorch、TensorFlow、transformers、LangChain 等框架为模型训练和推理提供了坚实基础
  • 数据处理能力:列表推导式、NumPy、Pandas 等工具使数据处理变得简洁高效
  • 胶水语言特性:易于与 C/C++、Rust 等底层语言集成,能够调用高性能计算库
  • 低学习曲线:对于 AI 研究人员来说,Python 的入门门槛较低
  • 最完整的 API SDK:OpenAI、HuggingFace 等主流平台的 SDK 首先支持 Python

TypeScript 的角色:应用层#

TypeScript 在应用层发挥着不可替代的作用:

  • 类型安全:静态类型检查和 IDE 自动补全能够在编译时发现错误,减少运行时异常
  • npm 生态:Vercel AI SDK、LangChain.js 等库提供了完善的工具链支持
  • 前后端统一:共享类型定义而非业务逻辑耦合,既保证类型一致性又不增加复杂度
  • Node.js 运行时:成熟的异步 I/O 模型,非常适合并发工具调用场景
  • VS Code 生态:微软背书,Copilot 支持良好,重构和调试体验出色
┌─────────────────────────────────────────────────────────────┐
│ AI Agent 架构 │
├─────────────────────────────────────────────────────────────┤
│ 展现层 │ 前端界面、Web 服务 │ TypeScript │
├─────────────────────────────────────────────────────────────┤
│ 应用层 │ 工具调用、状态管理、类型安全 │ TypeScript │
├─────────────────────────────────────────────────────────────┤
│ 控制层 │ Agent 逻辑、工具编排 │ Python/TypeScript │
├─────────────────────────────────────────────────────────────┤
│ 模型层 │ LLM 调用、RAG、向量检索 │ Python │
└─────────────────────────────────────────────────────────────┘

2. 核心 TypeScript 库#

2.1 LangChain.js / LangGraph.js#

LangChain.js 是 LangChain 的 TypeScript 版本,为构建 Agent 提供了丰富的抽象。

import { createReactAgent } from '@langchain/langgraph/prebuilt';
import { ChatAnthropic } from '@langchain/anthropic';
// 创建 ReAct Agent
const agent = createReactAgent({
llm: new ChatAnthropic({ model: 'claude-3-5-sonnet' }),
tools: [webSearchTool, calculatorTool],
});
// 流式输出
const stream = await agent.stream({
messages: [{ role: 'user', content: '帮我查今天天气' }],
});
for await (const chunk of stream) {
console.log(chunk);
}

LangGraph.js 则提供了更细粒度的状态管理能力,适合复杂的多步骤 Agent 流程。

2.2 Vercel AI SDK#

Vercel AI SDK 是专为现代 AI 应用设计的 TypeScript 优先框架,提供了优雅的工具调用抽象。

import { anthropic } from '@ai-sdk/anthropic';
import { generateText, tool } from 'ai';
import { z } from 'zod';
const { text, toolCalls } = await generateText({
model: anthropic('claude-3-5-sonnet'),
prompt: '帮我查北京天气',
tools: {
getWeather: tool({
description: '获取天气信息',
parameters: z.object({
city: z.string(),
unit: z.enum(['celsius', 'fahrenheit']).optional().default('celsius'),
}),
execute: async ({ city, unit }) => {
// 实际调用天气 API
return { temp: 22, weather: '晴', unit };
},
}),
},
});
console.log(text);
console.log(toolCalls);

Vercel AI SDK 的核心优势在于其简洁的 API 设计和开箱即用的流式支持。

3. 类型安全的工具调用#

工具调用是 Agent 与外部世界交互的桥梁,类型安全在这个环节至关重要。

3.1 使用 Zod 定义工具 Schema#

Zod 是一个 TypeScript 优先的模式验证库,与 TypeScript 的类型推断完美配合。

import { z } from 'zod';
// 定义工具 schema - 类型自动推断
const tools = {
search: {
description: '搜索网页',
parameters: z.object({
query: z.string(),
limit: z.number().optional().default(10),
site: z.string().optional(),
}),
},
calculator: {
description: '计算数学表达式',
parameters: z.object({
expression: z.string().describe('要计算的数学表达式'),
}),
},
weather: {
description: '获取城市天气',
parameters: z.object({
city: z.string(),
days: z.number().min(1).max(7).optional().default(1),
}),
},
} as const;
// 从 schema 推断类型
type ToolName = keyof typeof tools;
type ToolParams<T extends ToolName> = z.infer<typeof tools[T]['parameters']>;
// 执行工具 - IDE 自动补全和类型检查
async function executeTool(name: ToolName, params: ToolParams<typeof name>) {
const tool = tools[name];
// 验证参数
const validated = tool.parameters.parse(params);
// 执行对应的工具逻辑
switch (name) {
case 'search':
return await performSearch(validated);
case 'calculator':
return await evaluateExpression(validated.expression);
case 'weather':
return await fetchWeather(validated.city, validated.days);
}
}

3.2 LLM 工具调用的类型化处理#

当 LLM 返回工具调用请求时,我们需要将原始输出转换为类型安全的结构。

interface ToolCallRequest {
name: ToolName;
params: ToolParams<ToolName>;
}
interface ToolCallResult {
request: ToolCallRequest;
result: unknown;
error?: string;
}
// 处理 LLM 返回的工具调用
async function handleToolCalls(
llmOutput: unknown
): Promise<ToolCallResult[]> {
const results: ToolCallResult[] = [];
// 假设 llmOutput 包含 tool_calls 数组
const toolCalls = extractToolCalls(llmOutput);
for (const call of toolCalls) {
try {
// 类型守卫:确保工具名称有效
if (!isValidToolName(call.name)) {
throw new Error(`Unknown tool: ${call.name}`);
}
const result = await executeTool(call.name, call.params);
results.push({ request: call, result });
} catch (error) {
results.push({
request: call,
result: null,
error: error instanceof Error ? error.message : 'Unknown error',
});
}
}
return results;
}
// 类型守卫函数
function isValidToolName(name: string): name is ToolName {
return name in tools;
}

这种类型安全的设计带来三大好处:编译期检查减少运行时错误、IDE 自动补全提升开发效率、重构时能够自动发现所有引用点。

4. 多 Agent 编排#

复杂的 AI Agent 系统通常需要多个专门化的 Agent 协同工作,这就涉及到多 Agent 编排问题。

4.1 Agent 定义与注册#

interface Tool {
name: string;
description: string;
parameters: z.ZodSchema;
execute: (params: unknown) => Promise<unknown>;
}
interface SubAgent {
name: string;
description: string;
systemPrompt: string;
tools: Tool[];
model?: string;
}
class AgentRegistry {
private agents: Map<string, SubAgent> = new Map();
register(agent: SubAgent): void {
if (this.agents.has(agent.name)) {
throw new Error(`Agent ${agent.name} already registered`);
}
this.agents.set(agent.name, agent);
}
get(name: string): SubAgent | undefined {
return this.agents.get(name);
}
list(): SubAgent[] {
return Array.from(this.agents.values());
}
findBestMatch(userInput: string): SubAgent[] {
// 基于描述相似度或 LLM 判断选择合适的 Agent
return this.list().sort((a, b) =>
calculateRelevance(userInput, b.description) -
calculateRelevance(userInput, a.description)
);
}
}

4.2 编排器实现#

interface OrchestrationResult {
agentName: string;
response: string;
toolCalls: ToolCallResult[];
reasoning: string;
}
class AgentOrchestrator {
private registry: AgentRegistry;
private supervisor: LLMChain;
constructor(registry: AgentRegistry, supervisor: LLMChain) {
this.registry = registry;
this.supervisor = supervisor;
}
async route(userInput: string): Promise<OrchestrationResult> {
// 1. 使用 supervisor 决定使用哪个 Agent
const decision = await this.supervisor.predictMessages([{
role: 'user',
content: `用户输入: ${userInput}\n可用 Agent: ${this.listAgents()}`,
}]);
// 2. 解析决策结果
const targetAgent = this.parseDecision(decision);
// 3. 调用目标 Agent
const response = await this.callAgent(targetAgent, userInput);
return {
agentName: targetAgent.name,
response: response.content,
toolCalls: response.toolCalls,
reasoning: decision.reasoning,
};
}
private listAgents(): string {
return this.registry.list()
.map(a => `- ${a.name}: ${a.description}`)
.join('\n');
}
private parseDecision(decision: unknown): SubAgent {
// 解析 LLM 返回的决策,提取目标 Agent 名称
const agentName = extractAgentName(decision);
const agent = this.registry.get(agentName);
if (!agent) {
throw new Error(`Agent not found: ${agentName}`);
}
return agent;
}
private async callAgent(
agent: SubAgent,
userInput: string
): Promise<AgentResponse> {
// 实现 Agent 调用逻辑
const context = await this.buildContext(agent, userInput);
return this.executeAgent(agent, context);
}
}

4.3 并发 Agent 调用#

在某些场景下,我们可能需要同时调用多个 Agent 并综合它们的结果。

async function concurrentAgents(
userInput: string,
agentNames: string[]
): Promise<OrchestrationResult[]> {
const agents = agentNames
.map(name => registry.get(name))
.filter((a): a is SubAgent => a !== undefined);
// 并发执行所有 Agent
const results = await Promise.all(
agents.map(agent => orchestrator.callAgent(agent, userInput))
);
// 综合结果
return results.map((response, index) => ({
agentName: agents[index].name,
response: response.content,
toolCalls: response.toolCalls,
reasoning: 'Concurrent execution',
}));
}

5. 记忆与状态管理#

Agent 的记忆系统是实现连续对话和上下文理解的关键。

5.1 记忆类型定义#

type MemoryType = 'short_term' | 'long_term' | 'vector';
interface MemoryMetadata {
timestamp: Date;
importance: number; // 0-1, 记忆重要性评分
accessCount: number; // 访问次数
source: 'user' | 'agent' | 'tool';
tags?: string[];
}
interface MemoryEntry {
id: string;
type: MemoryType;
content: string;
embedding?: number[]; // 用于向量检索
metadata: MemoryMetadata;
}
interface ConversationContext {
sessionId: string;
messages: Message[];
memories: MemoryEntry[];
createdAt: Date;
updatedAt: Date;
}

5.2 分层记忆实现#

class AgentMemory {
private shortTerm: MemoryBuffer;
private longTerm: VectorStore;
private workingMemory: Map<string, unknown>;
constructor(config: MemoryConfig) {
this.shortTerm = new MemoryBuffer(config.shortTermLimit);
this.longTerm = new VectorStore(config.vectorDimensions);
this.workingMemory = new Map();
}
// 添加记忆
async add(
content: string,
type: MemoryType,
metadata: Partial<MemoryMetadata> = {}
): Promise<MemoryEntry> {
const entry: MemoryEntry = {
id: generateId(),
type,
content,
embedding: type === 'vector' ? await this.embed(content) : undefined,
metadata: {
timestamp: new Date(),
importance: metadata.importance ?? 0.5,
accessCount: 0,
source: metadata.source ?? 'agent',
tags: metadata.tags,
},
};
if (type === 'short_term') {
this.shortTerm.add(entry);
} else if (type === 'long_term' || type === 'vector') {
await this.longTerm.add(entry);
}
return entry;
}
// 检索记忆
async retrieve(
query: string,
limit: number = 5,
type?: MemoryType
): Promise<MemoryEntry[]> {
if (type === 'short_term') {
return this.shortTerm.getRecent(limit);
}
if (type === 'vector' || !type) {
const queryEmbedding = await this.embed(query);
return this.longTerm.similaritySearch(queryEmbedding, limit);
}
return [];
}
// 遗忘低重要性记忆
async prune(minImportance: number = 0.3): Promise<number> {
const toRemove = await this.longTerm.query({
filter: { importance: { $lt: minImportance } },
});
for (const entry of toRemove) {
await this.longTerm.delete(entry.id);
}
return toRemove.length;
}
// 总结短期记忆为长期记忆
async summarize(): Promise<void> {
const recent = this.shortTerm.getAll();
const summary = await this.summarizeContent(recent.map(e => e.content));
await this.add(summary, 'long_term', {
importance: 0.8,
source: 'agent',
tags: ['summary'],
});
this.shortTerm.clear();
}
}

5.3 状态持久化#

interface PersistedState {
version: number;
sessions: Record<string, ConversationContext>;
memories: MemoryEntry[];
lastUpdated: string;
}
class PersistentAgentState {
private storage: StateStorage;
private currentSession: ConversationContext | null = null;
async saveSession(session: ConversationContext): Promise<void> {
const state = await this.loadState();
state.sessions[session.sessionId] = session;
state.lastUpdated = new Date().toISOString();
await this.storage.save(state);
}
async loadSession(sessionId: string): Promise<ConversationContext | null> {
const state = await this.loadState();
return state.sessions[sessionId] ?? null;
}
async createSession(): Promise<ConversationContext> {
const session: ConversationContext = {
sessionId: generateId(),
messages: [],
memories: [],
createdAt: new Date(),
updatedAt: new Date(),
};
await this.saveSession(session);
this.currentSession = session;
return session;
}
}

6. 项目架构结构#

一个典型的 TypeScript AI Agent 项目应该遵循清晰的模块化架构。

src/
├── agents/
│ ├── base.ts # Agent 基类,定义通用接口
│ ├── react-agent.ts # ReAct 模式实现
│ ├── planner-agent.ts # 规划器 Agent
│ ├── executor-agent.ts # 执行器 Agent
│ └── index.ts # 统一导出
├── tools/
│ ├── registry.ts # 工具注册表
│ ├── web-search.ts # 网页搜索工具
│ ├── calculator.ts # 计算器工具
│ ├── weather.ts # 天气查询工具
│ └── types.ts # 工具类型定义
├── memory/
│ ├── buffer.ts # 短期记忆缓冲区
│ ├── vector-store.ts # 向量存储实现
│ ├── persistent.ts # 持久化存储
│ └── index.ts
├── orchestration/
│ ├── router.ts # Agent 路由逻辑
│ ├── supervisor.ts # 监督器
│ └── concurrent.ts # 并发编排
├── types/
│ ├── messages.ts # 消息类型定义
│ ├── tools.ts # 工具类型定义
│ └── agent.ts # Agent 相关类型
├── utils/
│ ├── logger.ts # 日志工具
│ ├── embedding.ts # 向量化工具
│ └── validation.ts # 验证工具
├── config/
│ └── index.ts # 配置管理
├── index.ts # 入口文件
└── app.ts # 应用启动

核心模块说明#

agents/base.ts 提供了所有 Agent 的抽象基类:

abstract class BaseAgent {
protected name: string;
protected description: string;
protected tools: Tool[];
protected memory: AgentMemory;
abstract execute(input: string, context?: Context): Promise<AgentResponse>;
protected async think(input: string): Promise<string> {
// Agent 的思考逻辑
throw new Error('Not implemented');
}
protected async act(input: string): Promise<Action> {
// Agent 的行动逻辑
throw new Error('Not implemented');
}
}

tools/registry.ts 实现类型安全的工具注册:

class ToolRegistry {
private tools: Map<string, Tool> = new Map();
register<T extends z.ZodSchema>(
name: string,
description: string,
schema: T,
execute: (params: z.infer<T>) => Promise<unknown>
): void {
this.tools.set(name, {
name,
description,
parameters: schema,
execute,
});
}
get(name: string): Tool | undefined {
return this.tools.get(name);
}
list(): Tool[] {
return Array.from(this.tools.values());
}
getSchema(name: string): z.ZodSchema | undefined {
return this.tools.get(name)?.parameters;
}
}

7. Python 与 TypeScript 对比:Agent 控制层#

在 Agent 控制层,Python 和 TypeScript 各有优劣,选择取决于具体场景。

方面PythonTypeScript
复杂状态管理运行时错误编译时错误
工具 Schema 变更静默失败编译器警告
多 Agent 路由手动处理类型保护
前端集成额外 HTTP 层直接调用
IDE 与重构一般支持VS Code 强大支持
并发工具调用asyncio 繁琐Promise.all 简洁
运行时性能优秀良好
启动速度较慢快速

Python 的适用场景#

  • 模型训练和微调相关的实验性工作
  • 需要深度定制 LangChain/LangGraph 内部逻辑
  • 数据处理和特征工程为主的任务
  • 团队成员以 Python 为主,没有前端背景

TypeScript 的适用场景#

  • 需要前后端类型统一的场景
  • 复杂的多 Agent 系统,需要编译时检查
  • 生产环境,需要长期维护和重构
  • 需要与 React/Vue 等前端框架集成
  • 强调开发体验和代码可靠性

8. 前后端统一不等于耦合#

TypeScript 的”统一”常被误解为前后端耦合,这是一个需要澄清的误区。

正确的理解#

前后端统一指的是类型定义的共享,而非业务逻辑的耦合:

传统架构:
┌─────────────┐ HTTP ┌─────────────┐
│ Frontend │ ───────────────→ │ Backend │
│ (TS/React) │ ←─────────────── │ (Python) │
└─────────────┘ └─────────────┘
类型定义需要重复维护
TypeScript 统一架构:
┌─────────────┐ HTTP ┌─────────────┐
│ Frontend │ ───────────────→ │ Backend │
│ (TS/React) │ ←─────────────── │ (TS/Node) │
└─────────────┘ └─────────────┘
│ │
└──── 共享类型 @shared/types ←───┘
(仅 npm 包,无业务逻辑)

实施方式#

packages/
└── @shared/
└── types/
├── agent.ts # Agent 相关类型
├── tool.ts # 工具类型定义
├── message.ts # 消息类型定义
└── index.ts # 统一导出
# frontend 和 backend 分别独立部署
# 仅通过 HTTP/API 通信
# 共享类型包确保接口一致性

前后端仍然是独立的服务、独立部署,只是都使用 TypeScript 并通过 npm 包共享类型定义。

9. 总结与建议#

技术选型建议#

场景推荐方案理由
全 Python 团队Python (LangGraph)无学习成本,生态完整
有前端参与,需类型安全TypeScript前后端统一,编译期检查
快速原型,验证想法Python开发速度快,迭代敏捷
生产环境,需重构安全TypeScript编译时检查,重构信心
复杂多 Agent,强类型TypeScript类型保护,多 Agent 协调

最佳实践#

  1. 类型安全优先:使用 Zod 定义所有工具 Schema,充分利用 TypeScript 类型推断

  2. 模块化设计:按职责分离 Agent、工具、记忆、编排逻辑,便于测试和维护

  3. 记忆分层:短期记忆处理当前会话,长期记忆支持跨会话知识积累

  4. 错误边界:为每个工具调用和 Agent 执行添加错误处理,避免级联失败

  5. 可观测性:集成日志和追踪,便于调试 Agent 行为和问题定位

未来趋势#

随着 AI Agent 应用的成熟,TypeScript 在这个领域的优势将更加明显:

  • 微软等大厂推动 TypeScript 在 AI 领域的应用
  • 更多 AI 原生的 TypeScript 库涌现
  • 前端与 Agent 的深度集成需求增长
  • 类型安全的工具调用成为行业标准

TypeScript 不仅是前端开发的选择,更是构建可靠、可维护 AI Agent 应用的重要基础设施。

TypeScript 在 AI Agent 上的应用
https://sgjki547.top/posts/typescript/
Author
SGJki
Published at
2026-04-10
License
CC BY-NC-SA 4.0