Files
agcore/README.md
T
徐涛 602bd43fce fix(llm,docs): 修复 Phase C 审查发现的两个警告
- LlmError::Request 变体补可操作建议:请检查 Provider 端点地址(base_url)和网络连通性
- README.md Mermaid 依赖图删除 Agent --> Prompt 边(编译级不存在)
- README.md 依赖规则文本同步:明确 agent 实际编译依赖为 llm/tools/memory,与 prompt 无直接依赖(system prompt 以 &str 传入)

参考审查:PM Director + SA Director 对 Phase C 的联合审查结论
2026-07-04 06:35:21 +08:00

245 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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. 添加依赖**
```toml
[dependencies]
agcore = "0.1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
```
**2. 第一个 Agent**
```rust,no_run
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());
}
```
跑起来:
```bash
cargo run
# LLM: 你好,我是 agcore。
```
接真实 Provider(如 OpenAI)只需把 `MockProvider` 换成:
```rust,no_run
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/`](./examples/) 目录(共 7 个,全部可 `cargo run --example <name>`):
| 示例 | 说明 |
|------|------|
| `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 流式响应事件消费(含错误路径) |
## 核心模块
| 模块 | 一句话说明 |
|------|----------|
| `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 │ 离线测试 / 示例
└─────────────────┘
```
## 模块依赖关系
```mermaid
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`](./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):
```bash
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`](./docs/note-agent-harness-references.md)):
| 项目 | 类型 | 语言 | 借鉴点 |
|------|------|------|-------|
| [OpenClaw](https://github.com/openclaw/openclaw) | 消息网关 | TypeScript | 多渠道适配模式 |
| [Hermes Agent](https://github.com/NousResearch/hermes-agent) | 自主学习智能体 | Python | 实体与会话解耦 |
| [OpenHuman](https://github.com/tinyhumansai/openhuman) | 桌面助手 | Rust + Tauri | 记忆树与 Token 压缩 |
| [OpenHarness](https://github.com/HKUDS/OpenHarness) | Agent Harness 框架 | Python | 显式依赖注入容器 + 三级权限 |
AG Core 不"抄代码",只参考架构模式。当前实现已经采纳:
- **OpenHarness 风格** —— 显式 `RuntimeBundle` 依赖注入容器
- **Hermes 风格** —— `Agent` trait(角色)与 `AgentSession`(会话)解耦
后续 v0.2+ 计划借鉴 OpenHuman 的 Memory Tree / TokenJuice 模式。
## 许可证
本项目基于 **Apache License 2.0** 授权。完整文本见 [`LICENSE`](./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
```