徐涛 34eec9f546 feat(engine): 实现 Agent 执行引擎(SessionManager + Checkpointer + SessionSnapshot)
Phase 17 主体交付:解决 v0.2 中 session 在变量里、无父子关系、无 checkpoint、
不可序列化的空白。

新增模块 src/engine/(5 文件,约 1300 行纯实现 + 21 个内联测试):

- error.rs(46 行)—— EngineError 枚举(6 变体)
  - SessionNotFound / SessionAlreadyExists / CheckpointNotFound
  - Memory(#[from] MemoryError) 透传(与 AgentError 风格一致)
  - Serialization / Agent(#[from] AgentError)

- snapshot.rs(36 行)—— SessionSnapshot + SessionMemoryEntry
  - 独立 struct 避开 Arc<dyn Agent> 不可序列化限制
  - SessionMemoryEntry 保留 value/metadata/created_at 完整信息
  - 所有字段 #[serde(default)] 宽松反序列化保证前向兼容

- checkpointer.rs(377 行)—— Time-travel 检查点管理器
  - checkpoint() / rollback_load() / list_checkpoints() / delete_all() / latest_snapshot()
  - 存储 key:ckpt:{session_id}:{ckpt_id}
  - ckpt_id 纳秒+计数器(无外部依赖,ponytail)
  - CkptMeta.created_at_nanos 字段确保同秒内精确降序
  - 6 个内联测试覆盖 roundtrip / 不存在 ckpt / 降序排序 / delete_all 幂等 /
    latest_snapshot / 跨 session 隔离

- session_manager.rs(906 行)—— SessionManager 会话树管理
  - 内部 RwLock<HashMap> + Arc<tokio::sync::Mutex<AgentSession>> 双重锁
  - create / create_child / get / recover / replace / children / parent /
    destroy / submit_turn / submit_turn_stream / finalize_turn_stream 共 11 个公开方法
  - SessionManagerConfig.auto_checkpoint 默认 true(同步写入 +
    tracing::error! 失败不阻断主流程,不提供强持久化保证)
  - 孤儿策略:destroy 不递归删除子 session;父被销毁后 parent() 返回 None
  - create_child 限制:父 session 必须先 get/recover 到内存(bundle 不可序列化)
  - 15 个内联测试覆盖 CRUD / recover / replace / 树形 / 孤儿 / auto_checkpoint 开关 /
    序列化兼容性 / 幂等 / 10 并发创建

- mod.rs(20 行)—— 统一 pub use 重导出 EngineError / SessionManager /
  SessionManagerConfig / Checkpointer / CkptMeta / SessionSnapshot /
  SessionMemoryEntry

AgentSession 扩展(src/agent/session.rs,+152 行):
- to_snapshot() pub async —— 从 MemoryStore 拍平 session_memory 全量数据
- from_snapshot() pub fn Result —— 纯同步构造器(pending_memory_restore 暂存)
- restore_memory() pub async &mut self —— 写回持久层并清空 pending
- has_pending_memory_restore() —— 查询 pending 状态
- pub(crate) fn bundle() —— accessor 供 SessionManager::create_child 继承

SessionMemory 扩展(src/agent/session_memory.rs,+57 行):
- list_entries() —— 返回 Vec<(key, value, metadata, created_at_unix_secs)>
- set_with_meta() —— 保留 metadata/created_at 写入(供 restore_memory 完整恢复)

src/lib.rs —— pub mod engine 声明

examples/engine_demo.rs(+251 行):
端到端演示 create → submit_turn → checkpoint → list_checkpoints →
rollback_load → from_snapshot → restore_memory → replace → destroy 完整链路,
含 rollback 一致性 assert(turn_index 和 cost 恢复到 checkpoint 时刻)。

零新外部依赖(serde_json 已有)。全量 353 → 374(+21 新测试)。
clippy 0 警告,doc 0 warning,example exit 0。

Phase 17: Agent 执行引擎 — Step 2-7(合并提交)
2026-07-15 08:59:46 +08:00

AG Core

AG Core 是一个用于构建 AI 智能体(Agent)的 Rust 工具箱,提供 LLM 调用、提示词工程、工具系统、记忆检索、Agent 运行时等核心能力,所有模块通过 trait 抽象、可插拔、可离线测试。

这是什么?

AG Core 不是 Agent 产品,而是 Agent 的底层依赖库:上层应用(TUI / Bot 网关 / 业务服务)基于 AG Core 装配出符合自身场景的 Agent。设计原则:

  • 模块化 —— 五大功能领域(LLM / Prompt / Tool / Memory / Agent)独立 crate-internal 模块,通过 trait 解耦
  • 可插拔 —— LLM Provider、记忆存储、工具注册全部通过 trait 抽象,可替换为自有实现
  • 可离线 —— 公开 MockProvider,所有示例与测试无需 API key 即可运行
  • 异步优先 —— 所有 IO API 均为 async,基于 tokio 运行时

适合用来:

  • 搭建支持多轮对话 + 工具调用的智能体服务
  • 接入多家 LLMOpenAI / Anthropic / DeepSeek / Qwen 等)
  • 在 Agent 中组合提示词模板、知识检索、MCP 工具
  • 在 Rust 中复用一套"业务无关"的 Agent 基础设施

快速上手

5 分钟上手,无需 API key(使用 MockProvider 预设响应)。

1. 添加依赖

[dependencies]
agcore = "0.2"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

2. 第一个 Agent

use std::sync::Arc;

use agcore::agent::{Agent, AgentBuilder, AgentSession};
use agcore::llm::hooks::HookExecutor;
use agcore::llm::mock::MockProvider;
use agcore::llm::provider::LlmProvider;
use agcore::llm::types::message::{ContentBlock, Message};
use agcore::llm::types::response_v2::{MessageResponse, StopReason};
use agcore::llm::types::Usage;
use agcore::tools::ToolRegistry;

struct Greeter;

impl Agent for Greeter {
    fn name(&self) -> &str { "greeter" }
    fn system_prompt(&self) -> Option<&str> { Some("你是一个中文助手,回答简短。") }
}

fn text_response(text: &str) -> MessageResponse {
    MessageResponse {
        id: "r".into(),
        model: "mock".into(),
        message: Message::Assistant {
            content: vec![ContentBlock::Text { text: text.into() }],
        },
        usage: Usage::from_input_output(2, text.chars().count() as u32),
        stop_reason: StopReason::Stop,
        extra: Default::default(),
    }
}

#[tokio::main]
async fn main() {
    // 1. MockProvider:预设响应,无须 API key
    let provider: Arc<dyn LlmProvider> =
        Arc::new(MockProvider::new(vec![text_response("你好,我是 agcore。")]));

    // 2. 装配 RuntimeBundle(必填:provider / tool_registry / hook_executor
    let bundle = Arc::new(
        AgentBuilder::new()
            .provider(provider)
            .tool_registry(Arc::new(ToolRegistry::new()))
            .hook_executor(Arc::new(HookExecutor::new()))
            .build()
            .expect("装配 RuntimeBundle 失败"),
    );

    // 3. 创建会话并提交首轮
    let agent: Arc<dyn Agent> = Arc::new(Greeter);
    let mut session = AgentSession::new(agent, "demo", bundle);
    let resp = session.submit_turn("你好").await.expect("submit_turn 失败");
    println!("LLM: {}", resp.text());
}

跑起来:

cargo run
# LLM: 你好,我是 agcore。

接真实 Provider(如 OpenAI)只需把 MockProvider 换成:

use agcore::llm::provider::{create_provider, ProviderConfig, ProviderType};

let provider = create_provider(
    ProviderType::OpenaiChat,
    ProviderConfig {
        base_url: "https://api.openai.com/v1".into(),
        api_key: std::env::var("OPENAI_API_KEY").expect("未设置 OPENAI_API_KEY"),
        model: "gpt-4o-mini".into(),
    },
).expect("创建 Provider 失败");

更多端到端示例见 examples/ 目录(共 10 个,全部可 cargo run --example <name>):

示例 说明
quick_start 30 行最小示例MockProvider + EchoTool + submit_turn,新用户 5 分钟上手
end_to_end 完整集成示例3 工具 + 3 轮对话 + SqliteStore 持久化跨连接验证
agent_session_demo Agent + 会话 + SessionMemory 完整链路(MockProvider 离线)
custom_tool 自定义工具注册、单次 / 并行调用、权限检查
prompt_composer 提示词模板与组合器(纯离线)
task_agent_demo Plan 解析、Step 状态机、错误路径
conversation_memory_demo 对话记忆滑动窗口与隔离
knowledge_search_demo 知识页面关键词检索
streaming_events_demo LLM 流式响应事件消费(含错误路径)
simple_visit 真实 LLM 调用(OpenAI / Anthropic,设置 OPENAI_* / ANTHROPIC_* 环境变量)

核心模块

模块 一句话说明
agcore::llm LLM 调用周期(LlmProvider trait + LlmCycle 重试/用量 + 流式事件 + auto-compaction + Hook + 公开 MockProvider
agcore::prompt 提示词工程(PromptTemplate 变量插值 + PromptTemplateRegistry + PromptComposer 多角色消息构造 + validate_messages
agcore::tools 工具系统(BaseTool trait + ToolRegistry 注册/调用 + PermissionChecker 黑白名单 + MCP stdio 客户端)
agcore::memory 记忆系统(MemoryStore trait + InMemoryStore 默认实现 + ConversationMemory 滑动窗口 + KnowledgeStore + MemoryRetriever
agcore::agent Agent 运行时(Agent trait 角色定义 + AgentBuilder + RuntimeBundle 依赖注入 + AgentSession 会话 + SessionMemory + Plan/Step 任务编排)

架构关系图

┌─────────────────────────────────────────────────────────────┐
│  应用层 (TUI / Bot 网关 / 业务服务)                           │
└───────────────────────────┬─────────────────────────────────┘
                            │ 使用
┌───────────────────────────▼─────────────────────────────────┐
│  Agent Runtime  (agcore::agent)                              │
│  Agent / AgentBuilder / RuntimeBundle / AgentSession /      │
│  SessionMemory / Plan / Step                                │
└─────┬───────────────┬───────────────┬───────────────┬───────┘
      │               │               │               │
┌─────▼─────┐  ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│  LLM      │  │  Prompt     │ │  Tool       │ │  Memory     │
│  agcore:: │  │  agcore::   │ │  agcore::   │ │  agcore::   │
│  llm      │  │  prompt     │ │  tools      │ │  memory     │
└─────┬─────┘  └─────────────┘ └─────┬───────┘ └──────┬──────┘
      │                               │                │
      └──────────────┬────────────────┘                │
                     ▼                                 │
            ┌─────────────────┐                       │
            │  Mock Provider  │◄──────────────────────┘
            │  公开 API       │     离线测试 / 示例
            └─────────────────┘

模块依赖关系

graph BT
    LLM["<b>llm</b><br/>Provider / Cycle /<br/>Hooks / Stream /<br/>Compact / Mock"]:::core
    Prompt["<b>prompt</b><br/>Template / Composer"]:::core
    Tool["<b>tools</b><br/>BaseTool / Registry /<br/>Permission / MCP"]:::core
    Memory["<b>memory</b><br/>Store / Conversation /<br/>Knowledge / Retriever"]:::core
    Agent["<b>agent</b><br/>Agent / Builder /<br/>Session / Plan"]:::core

    Prompt --> LLM
    Tool --> LLM
    Memory --> LLM
    Agent --> LLM
    Agent --> Tool
    Agent --> Memory

    classDef core fill:#60a5fa,stroke:#2563eb,color:#fff

依赖规则

  • llm 是叶子,被其他四个模块使用
  • prompt / tools / memory 互相不依赖,可独立使用
  • agent 编译期依赖 llm / tools / memory,与 prompt 无直接编译依赖(system prompt 以 &str 形式传入)
  • 上层应用只应依赖 agent + 必要的子模块,不应跨层直接 use

环境变量

AG Core 库本身不读环境变量。下表是 examples/simple_visit.rs 这一真实调用示例所使用的环境变量,以及通常推荐的取值。

变量 必填 推荐值 说明
OPENAI_API_KEY 用 OpenAI 时 OpenAI / 兼容 ProviderDeepSeek / Qwen)的 API key
OPENAI_BASE_URL https://api.openai.com/v1 OpenAI 兼容端点 base URLDeepSeek/Qwen 用对应地址)
OPENAI_MODEL gpt-4o-mini OpenAI 模型名
ANTHROPIC_API_KEY 用 Anthropic 时 Anthropic Claude API key
ANTHROPIC_BASE_URL https://api.anthropic.com Anthropic 兼容端点 base URL
ANTHROPIC_MODEL claude-3-5-sonnet-latest Claude 模型名
PROVIDER openai Provider 类型:openai / openai-response / anthropic / deepseek / qwen
RUST_LOG agcore=info tracing 日志级别(其他 crate 可加 =debug

示例(运行 examples/simple_visit.rs 真实调用 OpenAI):

export OPENAI_API_KEY=sk-...
export OPENAI_BASE_URL=https://api.openai.com/v1
export OPENAI_MODEL=gpt-4o-mini
export PROVIDER=openai
export RUST_LOG=agcore=debug
cargo run --example simple_visit

参考项目

AG Core 在 Phase 4 设计阶段调研了 4 个 2026 年公开的 AI Agent 项目(详见 docs/note-agent-harness-references.md):

项目 类型 语言 借鉴点
OpenClaw 消息网关 TypeScript 多渠道适配模式
Hermes Agent 自主学习智能体 Python 实体与会话解耦
OpenHuman 桌面助手 Rust + Tauri 记忆树与 Token 压缩
OpenHarness Agent Harness 框架 Python 显式依赖注入容器 + 三级权限

AG Core 不"抄代码",只参考架构模式。当前实现已经采纳:

  • OpenHarness 风格 —— 显式 RuntimeBundle 依赖注入容器
  • Hermes 风格 —— Agent trait(角色)与 AgentSession(会话)解耦

后续 v0.2+ 计划借鉴 OpenHuman 的 Memory Tree / TokenJuice 模式。

许可证

本项目基于 Apache License 2.0 授权。完整文本见 LICENSE

Copyright 2026 AG Core Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0
S
Description
AI Agent驱动库
Readme Apache-2.0 2.4 MiB
Languages
Rust 100%