之前写了好几篇用Rust构建AIAgent的文章,读者朋友们一直在问:"到底完整的项目长什么样?"今天,它来了。受nanobot启发,我用Rust重新设计了一个生产级的Agent运行时——ferrum-bot。
之前写了好几篇用 Rust 构建 AI Agent 的文章,读者朋友们一直在问:"到底完整的项目长什么样?"今天,它来了。 受 nanobot 启发,我用 Rust 重新设计了一个生产级的 Agent 运行时 —— ferrum-bot。
在 AI Agent 的赛道上,Python 凭借生态优势一家独大。但当我们想要构建一个每天稳定运行、资源可控、易于部署的个人助手时,Rust 的优势就显现出来了:
cargo build 之后就是一个可执行文件正如 ferrum-bot 的设计哲学:"不是功能堆砌,而是一个你可以信任并扩展的健壮核心。"
ferrum-bot 采用 Rust Workspace 组织代码,共包含 9 个 crate,每个都有明确的职责边界:
ferrum-bot/
├── ferrumbot-cli # CLI 入口和命令解析
├── ferrumbot-config # 配置管理和持久化
├── ferrumbot-core # 消息总线、会话管理
├── ferrumbot-agent # Agent 核心循环
├── ferrumbot-tools # 工具框架和内置工具
├── ferrumbot-providers # LLM Provider 抽象
├── ferrumbot-channels # 消息通道适配器
├── ferrumbot-cron # 定时任务系统
└── ferrumbot-runtime # 运行时和网关
这种分层设计的好处是每一层都可以独立测试、替换或复用。比如你想对接 Discord,只需要在 ferrumbot-channels 里新增一个实现即可。
Agent 的核心是一个异步消息循环,基于 Tokio 的 mpsc 通道实现:
pub struct AgentLoop {
pub bus: MessageBus, // 消息总线
pub provider: Arc<dyn LlmProvider>, // LLM Provider
pub workspace: PathBuf, // 工作目录
pub tools: ToolRegistry, // 工具注册表
pub sessions: Mutex<SessionManager>, // 会话管理
pub cron: Option<CronService>, // 定时服务
// ...
}
设计亮点:
MessageBus 分离入站和出站消息,方便接入不同通道~/.ferrum-bot/sessions/max_tool_iterations 防止工具调用死循环工具系统是 Agent 的"手脚",ferrum-bot 采用 async-trait 定义统一的 Tool 接口:
#[async_trait]
pub trait Tool: Send + Sync {
fn name(&self) -> &'static str;
fn description(&self) &'static str;
fn parameters(&self) -> Value; // JSON Schema
async fn execute(&self, args: Value, ctx: ToolContext) -> Result<String>;
}
内置工具一览:
| 工具类别 | 工具名 | 功能说明 |
|---|---|---|
| 文件操作 | file_read / file_write / file_edit / file_list |
带工作区限制的 FS 操作 |
| 命令执行 | exec |
带危险命令守卫的 shell 执行 |
| 网络工具 | web_search / web_fetch |
搜索和网页抓取 |
| 消息 | message_send |
跨通道消息发送 |
| 定时任务 | cron_add / cron_remove |
动态任务调度 |
| 进程 | spawn |
后台进程管理 |
安全设计:
restrict_to_workspace = true 时,文件操作不能越界exec 工具内置危险命令检测(如 rm -rf /)web_fetch 阻止访问内网 IP 和本地主机通过 LlmProvider trait,ferrum-bot 支持所有 OpenAI-compatible 的 API:
#[async_trait]
pub trait LlmProvider: Send + Sync {
async fn chat(
&self,
messages: Vec<Value>,
tools: Option<Vec<Value>>,
model: Option<&str>,
max_tokens: Option<usize>,
temperature: Option<f32>,
) -> Result<LlmResponse>;
}
配置示例(~/.ferrum-bot/config.json):
{
"providers": {
"openai": {
"api_key": "sk-...",
"base_url": "https://api.openai.com/v1"
}
},
"agents": {
"defaults": {
"model": "anthropic/claude-opus-4-5"
}
}
}
MessageBus 是系统的神经系统,使用 Tokio mpsc 实现:
#[derive(Clone)]
pub struct MessageBus {
inbound_tx: mpsc::Sender<InboundMessage>,
outbound_tx: mpsc::Sender<OutboundMessage>,
// ...
}
这种设计让 ferrum-bot 可以无缝对接多种通道:
让我们跟踪一次用户消息的完整处理流程:
// 1. 接收消息
impl AgentLoop {
pub async fn run(&self) {
while *self.running.lock().await {
let Some(msg) = self.bus.consume_inbound().await else { continue };
// 2. 处理消息
match self.process_message(msg).await {
Ok(Some(outbound)) => {
// 3. 发送回复
self.bus.publish_outbound(outbound).await?;
}
// ...
}
}
}
}
工具调用循环(ReAct 模式):
async fn process_message_with_session(...) -> Result<Option<OutboundMessage>> {
// 加载历史对话
let history = sessions.get_or_create(session_key)?.get_history(50);
let mut messages = self.context.build_messages(history, &msg.content, ...);
// 最多 max_iterations 轮工具调用
for _ in 0..self.max_iterations {
let resp = self.provider.chat(messages.clone(), tool_defs, ...).await?;
if resp.has_tool_calls() {
// 执行工具
for call in resp.tool_calls {
let result = self.tools.execute(&call.name, call.arguments, ctx).await;
// 将结果加入上下文
self.context.add_tool_result(&mut messages, ...);
}
} else {
// 得到最终回复
final_content = resp.content;
break;
}
}
// 持久化会话
session.add_message("user", &msg.content);
session.add_message("assistant", &final_content);
sessions.save(session_key)?;
}
这就是经典的 ReAct(Reasoning + Acting) 模式:LLM 思考 → 选择工具 → 观察结果 → 继续思考,直到得到最终答案。
ferrum-bot 的 CLI 设计遵循 "日常使用,而非演示" 的理念:
# 初始化配置
cargo run -- onboard
# 查看状态
cargo run -- status
# 进入交互式对话
cargo run -- agent
# 单次提问
cargo run -- agent -m "帮我写一个快速排序"
# 启动网关服务
cargo run -- gateway -p 8080
# 管理定时任务
cargo run -- cron add -n "早报" -m "生成今日简报" --cron "0 9 * * *" --deliver
REPL 内置命令:
/session <id> - 切换会话/new [name] - 创建新会话/multi - 多行输入模式/last - 查看上一次回复/retry - 重新生成| 特性 | nanobot | ferrum-bot |
|---|---|---|
| 语言 | Python | Rust |
| 部署 | 需要 Python 环境 | 单二进制文件 |
| 运行时稳定性 | GC 可能导致停顿 | 无 GC,确定性延迟 |
| 类型安全 | 运行时检查 | 编译期保证 |
| 工具扩展 | 动态加载 | 编译期注册(可热插拔) |
| 默认安全边界 | 基础 | 工作区限制 + 命令守卫 |
ferrum-bot 不是要取代 nanobot,而是为那些追求部署简洁、运行时稳定、资源可控的场景提供另一种选择。
已实现:
计划中:
从写第一篇 Rust Agent 文章到开源 ferrum-bot,历时数周。这个项目验证了 Rust 在 AI 应用开发中的可行性 —— 我们完全可以既享受 Rust 的性能和可靠性,又不失 Agent 的灵活和强大。
如果你也在探索 Rust + AI 的可能性,欢迎来 GitHub 看看:
🔗 https://github.com/lispking/ferrum-bot
如果觉得有帮助,给个 ⭐ 支持下吧!有问题也可以在 Issues 讨论,或者关注我的公众号获取更多 Rust + AI 的实践分享。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!