添加 READMIN.md

This commit is contained in:
大森 2026-05-23 18:05:04 +08:00
parent 24d34f695f
commit a6001e3688

416
READMIN.md Normal file
View File

@ -0,0 +1,416 @@
---
date: 2026-05-07
topic: "Go Agent Framework - Orca"
status: validated
---
# Go Agent Framework (Orca) 设计文档
## Problem Statement
构建一个基于 Go 的基础 Agent 框架,支持多 Agent 协作、持久化会话记忆、Skill 技能自动识别、沙箱安全执行、自定义 Tool 注册扩展,并接入 Ollama 本地模型gemma4:e4b
**核心挑战:**
- 如何在 Go 中实现轻量、高并发的多 Agent 系统
- 如何安全地执行用户命令和 Skill 脚本
- 如何设计可扩展的插件机制Skill / Tool
- 如何管理会话上下文和记忆
## Constraints
1. **语言约束:** 纯 Go 实现,最小化外部依赖
2. **存储约束:** 使用 JSON Lines无 SQLite/数据库依赖)
3. **隔离约束:** 进程级限制chroot + 资源限制),不依赖 Docker
4. **模型约束:** 仅接入 Ollama 本地模型,默认 gemma4:e4b
5. **Skill 目录:** 读取 `~/.agents/skills/` 下的 Skill 定义
6. **部署约束:** 单二进制文件,零配置启动
## Approach
### 架构风格:微内核 + Actor 模型
采用**微内核架构**作为基础所有功能Skill、Tool、LLM 驱动)都以**插件**形式注册到核心。
每个 **Agent 实例是一个独立的 Actor**,通过 **消息总线Message Bus** 进行通信。这完美契合 Go 的 goroutine + channel 并发模型。
**为什么选择这个组合?**
- 微内核保证核心最小化Skill 和 Tool 热插拔
- Actor 模型天然支持高并发,避免共享状态
- 两者结合 = 轻量级、高扩展、Go 原生友好
**放弃的其他方案:**
- Docker 沙箱:太重,违背最小依赖原则
- SQLite 存储增加依赖JSONL 已足够
- 中央协调器:单点瓶颈,不如 Actor 模型灵活
## Architecture
### 整体架构图
```
┌─────────────────────────────────────────────────────────────┐
│ CLI / API Layer │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Core Kernel (微内核) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Message Bus │ │ Plugin Reg │ │ Session Manager │ │
│ │ (channel) │ │ (registry) │ │ (JSONL-based) │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Agent Actor │ │ Agent Actor │ │ Agent Actor │
│ (Specialist 1) │ │ (Specialist 2) │ │ (Orchestrator) │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
└───────────────────┼───────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Plugin Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐│
│ │ Skills │ │ Tools │ │ Ollama │ │ Custom Tools ││
│ │(Skill Mgr)│ │(Tool Mgr)│ │ (Driver) │ │ (Registry) ││
│ └──────────┘ └──────────┘ └──────────┘ └──────────────┘│
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Sandbox Layer │
│ (Process-level isolation + Resource limits) │
└─────────────────────────────────────────────────────────────┘
```
### 模块职责
| 模块 | 职责 |
|------|------|
| **Core Kernel** | 消息路由、插件生命周期管理、会话协调 |
| **Message Bus** | 基于 Go channel 的异步消息传递系统 |
| **Plugin Registry** | 统一的 Skill/Tool/LLM 驱动注册中心 |
| **Session Manager** | 基于 JSONL 的会话历史读写和上下文窗口管理 |
| **Agent Actor** | 独立 goroutine持有状态接收/发送消息 |
| **Skill Manager** | 扫描 `~/.agents/skills/`,解析 SKILL.md加载技能 |
| **Tool Manager** | 管理内置工具和自定义工具的注册/调用 |
| **Ollama Driver** | 封装 Ollama HTTP API支持流式响应 |
| **Sandbox** | 安全执行 shell 命令和脚本,限制资源和时间 |
## Components
### 1. Core Kernel (微内核)
**职责:** 框架的最小化核心,只负责消息路由和插件生命周期。
**设计要点:**
- 使用 Go 的 `interface{}` 或泛型定义插件契约
- 启动时加载所有已注册的插件
- 提供事件总线供插件间通信
- **不**包含任何业务逻辑(如 LLM 调用、命令执行)
**核心接口:**
```
// 所有插件必须实现
Plugin interface {
Name() string
Init(kernel *Kernel) error
Shutdown() error
}
// 消息总线
MessageBus interface {
Publish(topic string, msg Message) error
Subscribe(topic string, handler Handler) (Subscription, error)
}
```
### 2. Actor System (多 Agent 引擎)
**职责:** 管理 Agent 生命周期和消息通信。
**设计要点:**
- 每个 Agent 是一个独立的 goroutine通过 channel 接收消息
- Agent 持有自己的状态(角色、上下文、工具列表)
- 支持三种 Agent 类型Orchestrator协调者、Worker执行者、Specialist专家
- 消息类型:`TaskRequest``TaskResponse``ToolCall``Observation`
**Agent 状态机:**
```
Idle → Processing → [ToolCall] → WaitingForTool → Processing → Completed
[Error] → Failed
```
### 3. Session Manager (会话记忆)
**职责:** 持久化会话历史,支持上下文窗口管理。
**设计要点:**
- 每个会话一个 JSONL 文件:`~/.orca/sessions/{session_id}.jsonl`
- 每行一个 JSON 对象:`{role, content, timestamp, metadata}`
- 提供 `GetContext(windowSize)` 方法,返回最近的 N 条消息
- 支持会话列表、搜索、归档
**为什么 JSON Lines**
- 追加写入 O(1),无需加载整个文件
- 人类可读,便于调试
- 零依赖,无需数据库驱动
- 通过简单文件锁保证并发安全
### 4. Skill Manager (技能系统)
**职责:** 自动发现和加载 Skill。
**设计要点:**
- 启动时扫描 `~/.agents/skills/` 下的所有子目录
- 解析每个 Skill 目录下的 `SKILL.md`
- 提取元数据:`name``description``triggers`(触发词)
- Skill 可以包含脚本文件(`scripts/` 目录)
- 提供 `FindSkill(query string)` 方法,基于触发词匹配
**Skill 结构:**
```yaml
name: "md2pdf"
description: "Convert Markdown to PDF..."
triggers: ["pdf", "markdown", "export"]
scripts:
- "scripts/convert.py"
- "scripts/setup.sh"
```
### 5. Tool Manager (工具系统)
**职责:** 管理可执行工具的注册和调用。
**设计要点:**
- **内置工具:** `exec`(执行命令)、`read_file``write_file``list_dir`
- **Skill 工具:** 从 Skill 的 `scripts/` 目录自动注册
- **自定义工具:** 通过代码注册,实现 `Tool` 接口
- 每个工具定义:名称、描述、参数 schema、执行函数
- LLM 通过 Function Calling 调用工具
**Tool 接口:**
```
Tool interface {
Name() string
Description() string
Parameters() JSONSchema
Execute(ctx Context, args map[string]any) (Result, error)
}
```
### 6. Ollama Driver (LLM 驱动)
**职责:** 封装 Ollama API提供统一的 LLM 调用接口。
**设计要点:**
- 默认模型:`gemma4:e4b`
- 支持流式响应SSE
- 支持 Function Calling通过 tools 参数)
- 自动处理上下文窗口截断
- 可配置参数temperature、top_p、max_tokens
**API 封装:**
```
LLMClient interface {
Chat(messages []Message, tools []Tool) (Response, error)
ChatStream(messages []Message, tools []Tool) (Stream, error)
}
```
### 7. Sandbox (沙箱执行)
**职责:** 安全地执行终端命令和脚本。
**设计要点:**
- 使用 `os/exec` 创建子进程
- 资源限制CPU 时间、内存、输出大小
- 超时控制:默认 30 秒,可配置
- 工作目录限制:可选 chroot 或指定工作目录
- 环境变量隔离:只允许白名单环境变量
- **不**使用 Docker保持轻量
**安全策略:**
```yaml
sandbox:
timeout: 30s
max_memory: 512MB
max_output: 64KB
allowed_env: [PATH, HOME, USER]
working_dir: /tmp/orca-sandbox
read_only_dirs: []
blocked_commands: [rm -rf /, mkfs, dd]
```
## Data Flow
### 典型交互流程
```
用户输入
┌─────────────┐
│ CLI/API │
└──────┬──────┘
┌─────────────┐ ┌─────────────┐
│ Session Mgr │────▶│ 加载历史上下文 │
└──────┬──────┘ └─────────────┘
┌─────────────┐
│ Orchestrator │ (Agent Actor)
│ Agent │
└──────┬──────┘
┌─────────────┐ ┌─────────────┐
│ Skill Mgr │────▶│ 匹配相关 Skill │
└──────┬──────┘ └─────────────┘
┌─────────────┐ ┌─────────────┐
│ Ollama Driver│────▶│ 发送 prompt │
└──────┬──────┘ └─────────────┘
┌─────────────┐
│ LLM Response │
│ (Function │
│ Calling) │
└──────┬──────┘
┌─────────────┐ ┌─────────────┐
│ Tool Call │────▶│ 执行 Tool/ │
│ │ │ 沙箱命令 │
└──────┬──────┘ └─────────────┘
┌─────────────┐
│ Observation │ (工具执行结果)
└──────┬──────┘
┌─────────────┐ ┌─────────────┐
│ Orchestrator │────▶│ 决策:继续/完成 │
└──────┬──────┘ └─────────────┘
┌─────────────┐
│ 保存会话 │
│ 返回结果 │
└─────────────┘
```
### 消息类型定义
```go
type Message struct {
ID string
Type MessageType // TaskRequest, TaskResponse, ToolCall, Observation, Error
From string // Agent ID
To string // Agent ID or "broadcast"
Content interface{} // 根据 Type 不同而变化
Timestamp time.Time
}
type TaskRequest struct {
Query string
SessionID string
Context []ChatMessage
}
type ToolCall struct {
ToolName string
Arguments map[string]interface{}
}
type Observation struct {
ToolCallID string
Output string
Error string
}
```
## Error Handling
### 策略
1. **分层错误处理:**
- **Kernel 层:** 插件加载失败 → 记录日志,跳过该插件,继续启动
- **Agent 层:** 任务执行失败 → 返回错误消息,让 Orchestrator 决策重试或终止
- **Tool 层:** 工具执行失败 → 返回结构化错误LLM 可据此调整策略
- **Sandbox 层:** 命令超时/内存超限 → 强制终止进程,返回错误
2. **重试机制:**
- LLM API 调用:指数退避重试 3 次
- 工具执行:不重试(避免循环),由 LLM 决策
3. **优雅降级:**
- Ollama 不可用 → 提示用户检查服务
- Skill 解析失败 → 跳过该 Skill不影响其他
- 沙箱执行失败 → 返回错误信息LLM 可尝试其他工具
### 错误类型
```go
type ErrorCategory int
const (
ErrCategoryKernel ErrorCategory = iota // 内核错误
ErrCategoryAgent // Agent 错误
ErrCategoryTool // 工具错误
ErrCategorySandbox // 沙箱错误
ErrCategoryLLM // LLM 错误
ErrCategoryNetwork // 网络错误
)
```
## Testing Strategy
### 测试金字塔
1. **单元测试60%**
- `Kernel`:插件注册/卸载、消息路由
- `SessionManager`JSONL 读写、上下文窗口截断
- `SkillManager`Skill 解析、触发词匹配
- `Sandbox`:资源限制、超时控制
- `OllamaDriver`HTTP 请求封装(使用 mock server
2. **集成测试30%**
- Agent + Tool端到端任务执行
- Agent + LLM使用 mock LLM 测试 Function Calling 流程
- Skill + Sandbox加载 Skill 并执行其脚本
3. **E2E 测试10%**
- 完整 CLI 工作流
- 多 Agent 协作场景
### Mock 策略
- `LLMClient`:使用接口,测试时注入 mock
- `Sandbox`:提供 `DryRun` 模式,记录命令但不执行
- `MessageBus`:内存实现,用于测试
## Open Questions
1. **Skill 执行方式:** Skill 脚本是用 Shell 调用还是直接在 Go 中执行?当前设计倾向 Shell 调用(通过 Sandbox但 Python/Node 脚本需要对应运行时。
- **假设:** 用户环境已安装所需运行时Python、Node 等Sandbox 只负责安全执行。
2. **Function Calling 格式:** gemma4:e4b 对 Function Calling 的支持程度?
- **假设:** 使用 Ollama 的 `tools` 参数格式,如果不支持则 fallback 到 prompt-based tool calling。
3. **多 Agent 协作粒度:** Agent 之间是平等协作还是有层级?
- **假设:** 支持两种模式层级Orchestrator + Workers和平等对等协作由用户配置。
4. **会话共享:** 多个 Agent 是否可以共享同一个会话上下文?
- **假设:**Session Manager 通过文件锁支持并发读取,但同一时间只有一个 Agent 写入。
5. **Tool 参数 Schema** 使用 JSON Schema 还是简化格式?
- **假设:** 使用简化版 JSON Schema支持 string/number/boolean/array/object + description