从零打造你的专属 AI Agent

学习如何通过 6 个步骤从头构建一个 AI Agent


为什么要自己构建 Agent?

AI 应用的演进

AI 应用经历了三个重叠的发展阶段:

  1. 聊天机器人 (Chatbots):简单的问答,被动响应(早期实现,随着 2022 年底 ChatGPT 的发布加速普及)
  2. RAG (检索增强生成):外部知识检索,单轮调用(自 2020 年开始研究,2023 年起广泛采用)
  3. Agents (智能体):自主规划,使用工具,迭代执行(ReAct 论文于 2022 年发表,2023 年起迅速普及)

Agent 的独特之处在哪里? 它们不仅仅是回答问题------它们可以:

  • 将复杂任务拆解为多个步骤
  • 自主调用工具来收集信息或采取行动
  • 在遇到错误时进行迭代和自我修正
  • 端到端地完成整个工作流

为什么不使用框架?

像 LangChain 和 AutoGPT 这样的框架非常方便,但从头构建能够提供:

  • 深度理解:透彻了解 Agent 的底层运作机制
  • 完全控制:针对生产环境需求定制每一个细节
  • 可扩展性:在不与框架抽象层"搏斗"的情况下添加功能

本指南 将通过 6 个循序渐进的步骤,带你构建一个类似 Claude Code 的 Agent,每一步都建立在前一步的基础上。


第一步:对话基础

提交 (Commit) : be88f03 - 带有流式输出的基本对话功能

做什么 & 为什么

在 Agent 能够行动之前,它必须能够记忆。这一步构建:

  • 一个用于用户交互的 CLI (命令行) 界面
  • 连接到 LLM (使用 OpenAI 协议)
  • 流式输出 (Token 随生成实时显示)
  • 对话历史管理 (万物之基)

为什么从这里开始? 每一个 Agent 功能都建立在对话管理之上。没有它,Agent 就没有记忆。

注意:我们在这一步构建的是一个聊天机器人,还不是 Agent。Agent 需要采取行动的能力------这将在第二步实现。

核心组件

对话管理器 (Conversation Manager):按顺序存储消息 (system → user → assistant → user → ...)。在每一轮对话中将完整历史提供给 LLM。

LLM 客户端 (LLM Client) :封装支持流式的 OpenAI API。使用 AsyncGenerator 在 Token 到达时逐个产出。

CLI 循环 (CLI Loop) :读取用户输入,调用 LLM,显示响应,重复。while (true) 循环维持着交互会话。

你将得到

一个有记忆的聊天机器人。虽然简单,但它是每一个后续功能构建的骨架。


第二步:工具调用 - 给 Agent 装上"双手"

提交 (Commit) : dae56bc - 带有 6 个工具的函数调用

做什么 & 为什么

纯语言模型只能"说话"------它们不能行动。函数调用 (Function Calling,又称 Tool Use) 让 LLM 能够:

  • 执行 Shell 命令 (bash)
  • 读写文件 (read, write, edit)
  • 搜索代码 (glob, grep)

突破点 :Agent 不再只是回答"你应该运行 ls",而是真正运行 ls 并看到输出结果。

这就是你的聊天机器人变身为 Agent 的时刻。

ReAct 模式

每个 Agent 的核心都是一个 ReAct 循环 (Reasoning + Acting,推理 + 行动)。这个模式由 ReAct 论文 引入,它在以下步骤间交替:

  • 推理 (Reasoning):LLM 思考下一步做什么
  • 行动 (Acting):执行工具以收集信息或做出更改
  • 观察 (Observing):查看工具结果并再次推理

伪代码

bash 复制代码
function agent_loop(user_message):
    conversation.add(user_message)
    
    while true:
        # 推理:LLM 决定做什么
        response = llm.generate(conversation, available_tools)
        
        # 检查 LLM 是否想要使用工具
        if response.has_tool_calls():
            for tool_call in response.tool_calls:
                # 行动:执行工具
                result = execute_tool(tool_call)
                # 观察:将结果添加到对话中
                conversation.add(tool_result(result))
            # 继续循环 - LLM 根据新的观察结果进行推理
        else:
            # 没有工具调用 = 任务完成
            return response.text

关键洞察 :这是一个 while 循环,而不是单次调用。每一次观察都会为下一步的推理提供信息,使 Agent 能够:

  • 将复杂任务拆解为步骤
  • 根据工具结果进行调整
  • 处理错误并尝试不同的方法

工作原理

工具注册表 (Tool Registry):可用工具的目录。每个工具都有:

  • 定义 (Definition) (名称、描述、参数):告诉 LLM 这个工具是做什么的
  • 执行 (Execute) 函数:执行实际操作

Agent 循环 (Agent Loop):实现上面的 ReAct 伪代码。循环持续进行,直到 LLM 仅回复文本 (无工具调用),标志着任务完成。

你将得到

你的 Agent 现在可以自主执行命令和操作文件。它从一个被动的聊天机器人变成了一个主动的自动化助手。


第三步:MCP - 连接生态系统

提交 (Commit) : d238b9d - 模型上下文协议 (Model Context Protocol) 支持

做什么 & 为什么

内置工具是有限的。MCP (Model Context Protocol) 是 Anthropic 推出的用于连接外部工具服务器的标准:

  • GitHub 操作
  • 数据库查询
  • 网络搜索
  • ...任何社区构建的工具

愿景:你的 Agent 成为一个中心枢纽,可以通过标准协议连接无限的能力。

工作原理

MCP 客户端 :使用 stdio transport (进程管道) 通过标准输入/输出管道连接到外部服务器。这是本地工具服务器最常用的方法,也是我们在这一步中实现的。

客户端从连接的 MCP 服务器获取工具定义,并将它们转换为与内置工具相同的 Tool 接口。

统一工具注册表:LLM 将所有工具 (内置和 MCP) 视为一个扁平列表。它不知道 (也不在乎) 它们来自哪里。

自动加载 :在启动时,读取 mcp-servers.json 并自动连接到所有配置的服务器。

你将得到

无需修改代码即可扩展功能。需要 GitHub 集成?在 mcp-servers.json 中添加一行即可。你的 Agent 瞬间获得新能力。


第四步:TODO 管理 - 让进度可视化

提交 (Commit) : 6e25680 - 任务列表追踪

做什么 & 为什么

复杂的任务需要许多步骤,如果只在模型的大脑中,随着上下文变长,很容易搞不清初始的计划。所以需要一个Todo List来不断标记执行到哪一步,以及下一步该执行什么。

TODO 管理 让 Agent 能够:

  • 在开始时列出计划 ("我将做 X,然后 Y,最后 Z")
  • 实时更新状态 (pending 等待中 → in_progress 进行中 → completed 已完成)
  • 展示当前正在处理的内容

关键洞察:这不是给用户的待办事项列表------这是 Agent 自己的工作计划,并将其可视化。

工作原理

TODO 管理器:追踪带有状态的任务列表。检测变化 (新任务、状态变更、完成),并仅渲染增量部分。

TODO 工具 :LLM 调用 todo_write 来更新其计划。系统提示词 (System Prompt) 指示它在多步骤任务中使用此工具。

智能渲染:仅显示变更以避免终端刷屏。已完成的任务会获得绿色复选框。当前任务显示加载微调器 (spinner)。

使用示例

yaml 复制代码
用户: "重构 auth.ts 以提取验证器"

Agent 调用 todo_write:
📋 Tasks:
  ⏳ 读取 auth.ts
  ⏸ 提取验证函数
  ⏸ 创建 validators.ts
  ⏸ 更新导入

[Agent 工作中...]
  ✓ Completed: 读取 auth.ts
  ⏳ 提取验证函数
...

你将得到

用户可以实时看到 Agent 的计划和进度。不再是黑盒操作------他们确切地知道每一步发生了什么。


第五步:Subagents

提交 (Commit) : 0f25524 - SubAgent

做什么 & 为什么

一个 Agent 做所有事情效率很低。子 Agent 实现了专业化:

  • 主 Agent:负责规划和协调
  • 子 Agent:执行特定任务 (搜索、研究、规划)

类比:CEO 不写代码------他们委派给工程师。

工作原理

子 Agent 配置:每个子 Agent 都有:

  • 专门的系统提示词 (例如,"你是一个代码搜索专家")
  • 受限的工具访问权限 (例如,explorer 只能使用 glob/grep/read)
  • 独立的对话历史

工作者 Agent (Worker Agent):运行子 Agent 任务的微型 Agent。它有自己的工具循环和最大迭代限制 (防止无限循环)。

委派工具 (Delegation Tool) :主 Agent 调用 delegate_task(agent_name="explorer", task="查找所有 API 端点")。子 Agent 执行任务,返回结果,其对话历史随后被丢弃。

内置子 Agent

名称 用途 工具
explorer (探索者) 搜索代码库结构 glob, grep, read
researcher (研究员) 阅读并理解代码 read, glob, grep
planner (规划者) 创建实施计划 glob, grep, read

为什么要委派?

  1. 专注:专门的提示词能针对特定任务产生更好的结果
  2. 隔离:子 Agent 的对话不会污染主 Agent 的上下文窗口

可选优化:你可以为处理简单任务的子 Agent 使用不同 (可能更便宜) 的模型,虽然这是一种设计选择,并非硬性要求。

你将得到

一个模块化系统,每个 Agent 各司其职。主 Agent 充当编排者,将专业任务委派给专家子 Agent。


第六步:技能 (Skills) - 注入领域专家知识

提交 (Commit) : aa15e81 - 按需知识加载

做什么 & 为什么

工具 = Agent 能做什么 (bash, read, write) 技能 = Agent 知道怎么做 (代码审查, PDF 处理, MCP 开发)

问题:如何在其不进行微调 (fine-tuning) 的情况下教给 Agent 专业知识?

解决方案:技能------包含专家指令的 Markdown 文件,按需加载。

技能系统设计

方面 实现
存储 skills/*/SKILL.md 文件,带有 YAML 头信息
启动 仅加载元数据 (~100 tokens/技能)
激活 LLM 在需要时调用 load_skill("code-review")
注入 完整内容 (~2000 tokens) 通过 tool_result 返回

为什么按需加载?

将所有技能放入系统提示词存在问题:

  • 成本:每个请求都要为 10,000+ tokens 付费
  • 噪音:不相关的技能会干扰模型

技能系统解决了这个问题:

  • 元数据始终加载:便宜 (每项技能约 100 tokens)
  • 完整内容按需加载:只在实际使用时付费
  • 系统提示词稳定性:添加/修改技能不会改变系统提示词的前缀

关于缓存的说明 :Anthropic 的提示词缓存 (Prompt Caching) 是基于前缀的。由于技能是通过 tool_result (出现在对话中,而不是系统提示词中) 注入的,系统提示词前缀保持可缓存状态。但是,整体缓存效率取决于你的对话模式。

SKILL.md 格式

markdown 复制代码
---
name: code-review
description: 包含安全检查的全面代码审查
---

# Code Review Skill

你现在是一位代码审查专家。请遵循此清单:

## Security
- [ ] SQL 注入漏洞
- [ ] XSS 漏洞
...

## Performance
- [ ] N+1 查询问题
...

[详细说明, 示例, 输出格式...]

渐进式披露

  1. 启动 :扫描 skills/ 目录,加载所有元数据
  2. 系统提示词:列出可用技能 ("Available skills: code-review, pdf-processing...")
  3. 使用时 :LLM 调用 load_skill 工具
  4. 注入:完整的 SKILL.md 内容通过工具结果注入
  5. 应用:LLM 将加载的专业知识应用于当前任务

你将得到

通过编写 Markdown 文件赋予 Agent 领域知识。想要代码审查技能?写一个 SKILL.md。想要 PDF 处理?再写一个 SKILL.md。无需模型再训练,无需代码部署------只有知识文件。


融会贯通

6 步回顾

步骤 能力 关键技术 提交 (Commit)
1. 对话基础 记忆 历史管理 + 流式输出 be88f03
2. 工具调用 行动 + ReAct 函数调用 + 工具循环 dae56bc
3. MCP 生态系统 协议适配器 + 统一注册表 d238b9d
4. TODO 透明度 状态追踪 + 增量渲染 6e25680
5. 子 Agent 专业化 委派 + 隔离上下文 0f25524
6. 技能 专业知识 元数据索引 + 按需加载 aa15e81

各部分如何组装

每一步都向核心 ReAct 循环添加了一项能力:

css 复制代码
[步骤 1] 对话历史维持上下文
         ↓
[步骤 2] 工具注册表 + ReAct 循环 = Agent 核心
         ↓
[步骤 3] MCP 扩展可用工具
         ↓
[步骤 4-6] 增强决策能力:
         ├─ 更新 TODO (进度可见性)
         ├─ 委派给子 Agent (专业化)
         └─ 加载技能 (领域知识)
         ↓
所有这些都反馈到 ReAct 循环中:
  推理 → 行动 → 观察 → (重复直到完成)

每个功能都是模块化增量。你可以一步步构建,每一个添加都在不破坏现有功能的情况下增强 Agent 的能力。

代码仓库

完整代码:mini-agent

提交历史:

  • be88f03: 第一步 - 基本对话
  • dae56bc: 第二步 - 工具调用 + ReAct 模式
  • d238b9d: 第三步 - MCP 支持
  • 6e25680: 第四步 - TODO 管理
  • 0f25524: 第五步 - 子 Agent
  • aa15e81: 第六步 - 技能系统

每个提交对应一步。使用 git checkout <commit> 来查看演进过程。

相关推荐
Miku1611 小时前
使用 Claude Code 的 pptx-skills 技能生成精美 EVA 主题 PPT 完整指南
aigc·agent·claude
且去填词17 小时前
DeepSeek :基于 AST 与 AI 的遗留系统“手术刀”式治理方案
人工智能·自动化·llm·ast·agent·策略模式·deepseek
TaiKuLaHa17 小时前
Agent中的深度思考是什么,有什么区别: ReAct模式 和 Plan-and-Solve模式
agent
roamingcode1 天前
超越 Context Window:为何文件系统是 AI Agent 的终极记忆体
人工智能·agent·cursor·claude code·上下文工程·skill 技能
大模型真好玩2 天前
LangGraph智能体开发设计模式(四)——LangGraph多智能体设计模式:网络架构
人工智能·langchain·agent
明月(Alioo)2 天前
AIGC入门,在Mac上基于Ollama和phi3:mini的完整Agent/Subagent例子
机器学习·aigc·agent·subagent
视觉&物联智能2 天前
【杂谈】-多智能体系统的效能悖论:协作优势的认知边界
ai·llm·agent·智能体·人工 智能
爱吃泡芙的小白白2 天前
Agent学习——反思模式
学习·agent·学习记录
沈询-阿里2 天前
Skills vs MCP:竞合关系还是互补?深入解析Function Calling、MCP和Skills的本质差异
人工智能·ai·agent·ai编程