手写一个能日常使用的 Agent 实现Chatbot

时间:2026-07-08 08:28:41 来源:互联网

AI技术的快速发展正推动智能Agent在日常开发中扮演更重要的角色,亲自实现一个mini项目能深入理解其工作机制。本文以Rust语言为例,系统记录从零构建可日常使用的编码Agnet全过程,涵盖架构设计、技术选型、项目初始化与核心功能实现,为开发者提供清晰的实践指南。

在日常开发中,我频繁借助Codex和Claude Code完成编码任务。虽然大致了解对话循环、工具调用、上下文管理、文件编辑和命令执行等底层机制,但许多细节仍停留在概念层面,并未真正深入拆解分析。

要彻底理清这些细节,最直接的方式是阅读源码或自主实现一遍。目前Codex已有开源版本,Claude Code也可通过反编译和行为观察进行研究,但仅阅读源码容易停留在旁观者视角。相比之下,亲手开发一个能用于日常工作的微型Agnet,可以在实现过程中逐步理解其关键机制。

因此,我决定从零开始编写一个名为 mini-agent 的自用项目。

为什么选择 Rust

在技术选型上,我决定采用Rust语言来实现此项目。

选择理由很简单:我最近刚完成Rust语法的学习,熟练程度还不算高。如果只通过看书或编写简单示例,许多知识点很快就会遗忘。借助真实Agnet项目,可以系统串起所有权、生命周期、异步编程、错误处理、模块组织以及trait抽象等内容。

当然,依靠这个项目就“精通Rust”有些夸张,但至少能迫使我在真实场景中反复使用Rust,不再停留在纯粹的语法练习阶段。

项目定位

该项目的目标并非复刻完整的Claude Code或Codex。

主流编码Agnet已经非常成熟且功能完整。我的目标更加务实:先构建一个能用于日常编码的mini-Agnet,再在使用过程中持续迭代。

初始版本会较为简单,但后续会逐步实现以下能力:

  1. TUI 交互界面
  2. 多轮对话
  3. 流式输出
  4. Tool use
  5. MCP 支持
  6. Plan 模式
  7. Memory
  8. Skill
  9. Subagent
  10. mini-agent 迭代 mini-agent

最后一点最令我期待:当基础能力足够后,将用它来继续开发自身。这样既能验证Agnet的可用性,也能更深入地理解编码Agnet在真实开发中的能力边界。

架构图先行

img_6a4d99b8b96fd30.webp

目前先按最小可运行版本进行设计,后续边开发边调整。许多架构细节无需一开始就固定,先让核心loop运行起来,再逐步补齐各项能力。

第一阶段:先实现一个 Chatbot

第一阶段的目标非常明确:实现基础对话loop,支持流式输出和多轮对话。

这实际上是Agnet的前身——Chatbot。

它目前只能聊天,无法真正完成实际工作。没有工具调用,就不能读取文件、修改代码、执行命令;缺乏上下文压缩和状态管理,长对话很快就会失控。但所有Agnet的核心都离不开这个基础循环:

  1. 接收用户输入
  2. 构造 messages
  3. 调用模型
  4. 流式输出回复
  5. 把 assistant response 写回上下文
  6. 等待下一轮用户输入

这个loop运行通顺后,再叠加工具调用、Plan模式、Memory、Skill和Subagent,Agnet的整体形态才会逐渐清晰。

项目初始化

首先建立workspace和三个核心crate:

cargo new mini-agent
cd mini-agent
mkdir cratescargo new crates/agent-cli --bin
cargo new crates/agent-core --lib
cargo new crates/provider --lib

然后在根目录的 Cargo.toml 中配置workspace:

[workspace]
resolver = "2"members = [
    "crates/agent-cli",
    "crates/agent-core",
    "crates/provider",
]

当前项目结构大致如下:

crates/
  agent-cli/    # CLI / TUI 入口,负责用户交互
  agent-core/   # Agent 核心逻辑:对话、消息、loop、工具调度等
  provider/     # 模型 provider 抽象:OpenAI-compatible、Claude API 等

拆分的思路如下:

  1. agent-cli 仅负责交互入口,不直接关注模型调用细节。
  2. agent-core 存放Agnet的核心行为,包括message管理、会话循环、上下文维护等。
  3. provider 抽象不同模型供应商,避免核心逻辑与特定API绑定过紧。

这样设计的优点是后续扩展会更加自然。例如,先接入OpenAI-compatible API,后续接入Claude API、Gemini或本地模型时,只需实现新的provider,无需改动整个Agnet核心。

API 设计

第一阶段的API无需设计得太复杂,先确保最小对话链路能够运行通顺。

当前代码中的核心骨架大致如下:

img_6a4d99b8c427931.webp

实际调用流程可以理解为:

img_6a4d99b8d4f7d32.webp

此处最关键的在于 Agent 不直接关注具体API的调用方式,它仅依赖 Provider trait。当前的 OpenAIProvider 只是其中一个实现,内部再根据 ApiType 划分为 completionsresponses 两条路径。

第一版先确保以下能力稳定运行:

  1. 初始化一个 Agent
  2. 接收用户输入
  3. 保存多轮上下文
  4. 通过 Provider 发起流式请求
  5. 在 CLI 中流式输出模型回复
  6. 输出完成后,将 assistant response 写回历史记录

后续正式加入tool use时,再扩展 tool_usetool_result 以及 tool dispatch loop。

测试

简单测试确认在终端中可以正常运行!

img_6a4d99b8e5ff333.webp

代码

github.com/Groos-dev/m…

小结

本文记录了mini-agent项目的启动历程,从最简单的多轮对话切入,逐步规划工具调用、计划模式、记忆系统、MCP以及子Agnet等进阶能力。通过亲手拆解和实现Agnet的核心机制,最终目标是构建一个真正可用且能持续迭代的编码Agnet,未来将在此基础上扩展更复杂的工具调度与自适应学习功能。