引言:AI Agent 的基础与发展趋势
AI Agent 作为当前热门技术,正从单纯的语言模型向智能执行系统演进。早期产品如千问、豆包、元宝等,通过 AI 推理完成复杂任务,标志着计算范式的转变。更先进的如 OpenClaw 项目,以一人公司模式运营多 Agent 系统,包括编程助手、PPT 生成、财务分析等。这些系统通过任务拆解、规划,调用特定 Agent 实现目标。另一个例子是 Seedance,利用视频数据进行分析,展示了 Agent 在实时处理上的潜力。
从 Prompt Engineering 到 Agent Engineering,这一演进强调全栈能力。直接调用大模型如 Gemini 1.5 Pro 虽便捷,但存在痛点:缺少记忆(Memory)导致忘记历史对话;无法执行外部操作(如访问网页);难以整合私有知识(RAG)。因此,AI Agent 的核心组成是 LLM + Memory + Tool + RAG。这让大模型能思考、规划、记忆,并自动执行任务。
本文聚焦一个 LLM + Tools 的小 demo,基于提供的笔记和代码,逐步构建一个简单 Agent。它不是完整的 Cursor(一个高级编程 Agent,能自动生成、编辑项目),而是基础版本:用 LangChain 集成工具,实现文件读写和命令执行。我们将用 JavaScript 示例代码演示如何让 Agent “手写”一个 React TodoList 项目。通过这个 demo,你能理解 Tool 的作用,并扩展到更复杂场景。
AI Agent 的本质与组件
AI Agent 本质上是扩展的大模型:添加 Tool 赋予执行能力,Memory 管理上下文,RAG 查询知识库。原本 LLM 能思考规划,但 Tool 让它能读写文件、执行 Bash 命令,实现自动化。例如,用 React 创建 TodoList:Agent 思考生成代码,用 Tool 保存文件、运行 npm 安装。这比纯 LLM 更实用。
LangChain 框架简化了 Agent 开发,提供 Memory、Tool、RAG 支持。需 Node.js 基础(如 NestJS)。我们选择 qwen-coder-turbo 作为 LLM,专精代码生成。Tool 包括 read_file、write_file 和 exec_command,这些是编程 Agent 的基石。
这个 demo 强调 LLM 与 Tool 的集成:LLM 决策调用 Tool,处理结果,形成循环,直到任务完成。它是一个小起点,向 Cursor 风格的 Agent 靠近。
Tool 的设计与集成原理
选择 LLM:qwen-coder-turbo,temperature=0 确保输出稳定。Tool 是函数,接受参数、执行操作、返回结果。LangChain 的 tool 模块用 Zod 校验参数。
示例中,read_file Tool 读取文件,用于代码分析。write_file 保存内容,exec_command 执行 shell 命令(如 npm init)。绑定 Tool 后,LLM 在对话中可调用。
消息系统:SystemMessage 定义流程,HumanMessage 用户输入,ToolMessage 反馈结果。循环处理 tool_calls:执行 Tool,加入消息,再调用 LLM。
这实现了 Agent 的“智能”:规划 → 调用 → 处理 → 迭代。
完整代码示例详解
首先,导入模块:
JavaScript
import 'dotenv/config';
import { ChatOpenAI } from '@langchain/openai';
import { tool } from '@langchain/core/tools';
import {
HumanMessage,
SystemMessage,
ToolMessage,
} from '@langchain/core/messages';
import fs from 'node:fs/promises';
import { z } from 'zod';
import { exec } from 'child_process';
import util from 'util';
const execAsync = util.promisify(exec);
初始化模型:
JavaScript
const model = new ChatOpenAI({
modelName: 'qwen-coder-turbo',
apiKey: process.env.OPENAI_API_KEY,
configuration: {
baseURL: process.env.OPENAI_API_BASE_URL,
},
temperature: 0,
});
定义 Tool:
JavaScript
const readFileTool = tool(
async ({ path }) => {
const content = await fs.readFile(path, 'utf-8');
console.log(`[工具调用] read_file("${path}") 成功读取 ${content.length} 个字符`);
return content;
},
{
name: 'read_file',
description: `用此工具来读取文件内容,当用户需要读取文件、查看代码时、分析文件内容时,调用此工具,输入文件路径(可以是相对路径或者绝对路径)`,
schema: z.object({ path: z.string().describe('要读取的文件路径') }),
}
);
const writeFileTool = tool(
async ({ path, content }) => {
await fs.writeFile(path, content, 'utf-8');
console.log(`[工具调用] write_file("${path}") 成功写入`);
return `文件 ${path} 已成功写入`;
},
{
name: 'write_file',
description: `用此工具写入文件内容,当需要创建或修改文件时调用,输入路径和内容`,
schema: z.object({
path: z.string().describe('要写入的文件路径'),
content: z.string().describe('要写入的文件内容'),
}),
}
);
const execCommandTool = tool(
async ({ command }) => {
const { stdout, stderr } = await execAsync(command);
console.log(`[工具调用] exec_command("${command}") 执行完成`);
return `stdout: ${stdout}\nstderr: ${stderr}`;
},
{
name: 'exec_command',
description: `用此工具执行 shell 命令,如安装依赖或运行项目,当需要运行 npm、git 等命令时调用`,
schema: z.object({ command: z.string().describe('要执行的 shell 命令') }),
}
);
const tools = [readFileTool, writeFileTool, execCommandTool];
绑定 Tool:
JavaScript
const modelWithTools = model.bindTools(tools);
消息数组与用户查询示例:
JavaScript
const messages = [
new SystemMessage(`
你是一个编程 Agent,像 Cursor 一样,能生成代码、读写文件、执行命令。
工作流程:
1. 理解用户任务(如创建 React TodoList)。
2. 规划步骤:生成代码 → 写文件 → 执行命令(如 npm init)。
3. 使用工具执行:read_file 查看现有文件,write_file 保存代码,exec_command 运行命令。
4. 如果需要,迭代优化。
可用工具:
- read_file: 读取文件内容
- write_file: 写入文件内容
- exec_command: 执行 shell 命令
`),
new HumanMessage('请帮我创建一个简单的 React TodoList 项目,生成代码并保存到 ./todo-app 目录下,然后安装依赖。'),
];
主循环:
JavaScript
let response = await modelWithTools.invoke(messages);
messages.push(response);
while (response.tool_calls && response.tool_calls.length > 0) {
console.log(`\n[检测到] ${response.tool_calls.length} 个工具`);
const toolResults = await Promise.all(
response.tool_calls.map(async (toolCall) => {
const tool = tools.find((t) => t.name === toolCall.name);
if (!tool) {
return `错误:找不到工具 ${toolCall.name}`;
}
console.log(`[执行工具] ${toolCall.name}(${JSON.stringify(toolCall.args)})`);
try {
const result = await tool.invoke(toolCall.args);
return result;
} catch (err) {
return `错误:${err.message}`;
}
})
);
response.tool_calls.forEach((toolCall, index) => {
messages.push(
new ToolMessage({
content: toolResults[index],
tool_call_id: toolCall.id,
})
);
});
response = await modelWithTools.invoke(messages);
}
console.log(response.content);
运行过程:Agent 规划创建目录(exec_command 'mkdir todo-app')、生成代码(LLM 输出)、写文件(write_file 保存 App.js 等)、安装依赖(exec_command 'cd todo-app && npm init -y && npm install react react-dom')。最终输出项目创建成功。
扩展到更高级 Agent
当前是小 demo,添加 Memory(LangChain BufferMemory)实现多轮对话。集成 RAG 查询代码库。向 Cursor 靠近:支持 VS Code 插件、代码迭代优化。
安全考虑:限制 Tool 路径/命令,避免风险。性能:Promise.all 并行执行。
结语:
通过这个小 demo,我们看到 AI Agent 的潜力:LLM + Tool 让大模型从思考者变为执行者。基于 LangChain,你可以扩展到 Memory 和 RAG,构建全栈 Agent。