
这两周 openclaw 非常的火热,大家都在探索它的使用方法和用应用场景。我也对它产生了浓厚的兴趣,深入研究了它 也有一些网易在研究它的架构设计和实现细节,贡献了 nanbot、miniclaw 等个别的项目。我也花了一些时间研究了 openclaw 的代码,并基于它的设计理念,使用 Go 语言重新实现了一个类似的项目,命名为 goclaw。
goclaw 使用和 openclaw 相同的配置文件、技能系统和类似的 cli 命令,并且兼容 openclaw 的技能生态。同时,goclaw 也借鉴了 openclaw 的核心设计理念,但在实现细节上做了一些不同的选择,以充分利用 Go 语言的优势,构建了一个更加健壮、高性能的 AI 助手。

项目地址: https://github.com/smallnest/goclaw
概述
GoClaw 是一个用 Go 语言编写的个人 AI 助手,灵感来自 OpenClaw(原 Clawdbot/Moltbot)。它运行在本地服务器上,通过 WebSocket/HTTP 暴露服务,支持多种消息 channel(Telegram、WhatsApp、飞书、QQ、Slack 等)接入。
核心定位
|
|
|
|---|---|
| 语言 |
|
| 架构 |
|
| 部署 |
|
| 扩展性 |
|
| 可靠性 |
|
核心架构
系统全景图
┌──────────────────────────────────────────────────────────────────────────────┐
│ GoClaw 系统架构 │
├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 输入Channel │── →│ 网关服务器 │───→│ Agent Loop │───→│ LLM/工具 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │ │
│ │ │ │ │ │
│ v v v v │
│ Telegram/WhatsApp MessageBus SessionManager Providers │
│ 飞书/QQ/Slack 串行队列 JSONL存储 OpenAI/AI... │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
消息处理流程
用户消息 → Channel适配器 → 网关服务器 → Agent Loop → LLM 调用 → 工具执行 → 响应返回
Agent Loop 执行引擎
Agent Loop 是 GoClaw 的大脑,负责思考、规划和执行。它受到 OpenClaw 的 PI Agent 架构启发。
PI Agent 理念
PI = 极简编码代理(Mario Zechner 创建)
"LLMs 本身就擅长编写和运行代码,不需要过多的包装"
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
执行流程图
┌───────────────────────────────────────────────────────────────────┐
│ GoClaw Agent Loop │
├───────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 接收消息 │────→│ 构建上下文 │────→│ LLM 调用 │────→│ 执行工具 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │
│ v │
│ ┌─────────────────┐ │
│ │ 工具结果返回 │ │
│ └─────────────────┘ │
│ │ │
│ v │
│ ┌─────────────────┐ │
│ │ 反思机制判断 │ │
│ │ (可选) │ │
│ └─────────────────┘ │
│ │ │
│ ┌─────────────┴────────────┐ │
│ v v │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 继续迭代 │ │ 返回响应 │ │
│ └─────────────┘ └─────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────┘
核心组件
1. 上下文构建器 (ContextBuilder)
文件: agent/context.go
type ContextBuilder struct {
memory *MemoryStore
workspace string
agentID string
defaultModel string
provider string
}
职责:
-
动态组装系统提示词 -
注入可用工具定义 -
添加会话历史(从 JSONL) -
整合相关记忆 -
上下文窗口保护与压缩
上下文压缩策略:
// agent/loop.go:571
func (l *Loop) compressSession(sess *session.Session) {
// 保留最近 10 轮对话
// 保留所有系统消息
// 丢弃早期历史,保留关键上下文
}
2. 工具注册表 (Tools Registry)
文件: agent/tools/registry.go
核心工具集(对应 PI 的四个工具):
|
|
|
|
|---|---|---|
read_file |
|
read |
write_file |
|
write |
edit_file |
|
edit |
run_shell |
|
bash |
GoClaw 扩展工具:
-
browser_*– 浏览器操作 (Chrome DevTools Protocol) -
smart_search– 混合搜索 (向量 + FTS5) -
spawn– 子代理管理 -
message– 消息发送
工具执行与重试:
// agent/loop.go:526
func (l *Loop) executeToolWithRetry(ctx context.Context, toolName string, params map[string]interface{}) (string, error) {
// 网络错误自动重试
// 错误分类与降级建议
// 结构化错误返回给 LLM 自我校正
}
3. 反思器 (Reflector)
文件: agent/reflection.go
解决传统 Agent "何时停止" 的难题:
type Reflector struct {
config *ReflectionConfig
provider providers.Provider
workspace string
}
type TaskReflection struct {
Status TaskStatus // "completed", "in_progress", "failed", "blocked"
Confidence float64 // 0.0 - 1.0
CompletedSteps []string // 已完成步骤
RemainingSteps []string // 剩余步骤
Reasoning string // 思考过程
NextAction string // 下一步行动
}
反思流程:
// agent/loop.go:487
reflection, reflectErr := l.reflector.Reflect(ctx, userRequest, reflectionHistory)
if l.reflector.ShouldContinueIteration(reflection, iteration, l.maxIteration) {
continuePrompt = l.reflector.GenerateContinuePrompt(reflection)
continue
}
与传统 max-iterations 的区别:
-
传统:固定步数后强制停止 -
反思:动态判断任务状态,智能决定是否继续
4. 错误分类器 (ErrorClassifier)
文件: agent/error_classifier.go
type ErrorClassifier struct {
authPatterns []string
rateLimitPatterns []string
timeoutPatterns []string
billingPatterns []string
}
错误分类:
-
auth– 认证错误(需要故障转移) -
rate_limit– 限流错误(需要冷却) -
timeout– 超时错误(可重试) -
billing– 计费错误(需要故障转移) -
tool– 工具错误(返回给 LLM)
智能降级策略:
// agent/loop.go:628
func (l *Loop) formatToolError(toolName string, params map[string]interface{}, err error) string {
// 根据工具类型和错误提供具体建议
// 例如:write_file 失败 → 建议输出到控制台
// 例如:browser 失败 → 建议使用 web_fetch
}
GoClaw vs OpenClaw PI Agent
架构对比
OpenClaw PI (TypeScript) – 极简循环:
while (true) {
const response = await streamCompletion(model, context);
if (!response.toolCalls?.length) break;
for (const call of response.toolCalls) {
const result = await executeToolCall(call, context);
context.messages.push(result);
}
}
GoClaw (Go) – 增强循环:
for iteration < l.maxIteration {
response, err := l.provider.Chat(ctx, messages, tools)
if len(response.ToolCalls) > 0 {
for _, tc := range response.ToolCalls {
result, err := l.executeToolWithRetry(ctx, tc.Name, tc.Params)
}
continue
}
if response.Content == "" && l.reflector != nil {
reflection := l.reflector.Reflect(ctx, userRequest, history)
if !l.reflector.ShouldContinueIteration(reflection, iteration, l.maxIteration) {
break
}
continue
}
break
}
会话存储对比
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
扩展系统对比
OpenClaw PI – TypeScript Hooks:
hooks: {
onSessionStart: async (session) => { ... },
onBeforeTurn: async (session) => { ... },
onToolCall: async (tool, params) => { ... },
// 20+ 生命周期钩子
}
GoClaw – Skills System:
type Skill struct {
Name string
Description string
Triggers []string // 触发关键词
Content string // Markdown 指令
Requires []string // 环境依赖 (Gating)
}
设计哲学对比
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GoClaw 独特创新
-
反思机制 – 解决 Agent "何时停止" 难题 -
错误分类与重试 – 三层容错(工具级、迭代级、提供商级) -
混合搜索 – 向量 + FTS5 双重检索 -
技能准入 (Gating) – 根据环境自动加载技能 -
上下文压缩 – 智能保留关键历史
网关服务器
文件: gateway/server.go
网关服务器是 GoClaw 的心脏,负责任务/会话协调:
type Server struct {
config *config.GatewayConfig
wsConfig *WebSocketConfig
bus *bus.MessageBus
channelMgr *channels.Manager
sessionMgr *session.Manager
connections map[string]*Connection
}
核心功能:
-
处理多个重叠请求 -
基于队列的消息总线(串行默认) -
WebSocket 连接支持 -
Webhook 回调处理 -
HTTP 健康检查端点
内存系统
双重记忆架构
会话记录 (JSONL)
-
每行一个 JSON 对象 -
包含用户消息、工具调用、结果、响应 -
会话基础的持久化记忆
记忆文件 (Markdown)
-
MEMORY.md或memory/文件夹 -
由代理使用标准文件写入工具生成 -
没有特殊的记忆写入 API
混合搜索
|
|
|
|
|---|---|---|
| 向量搜索 |
|
|
| 关键词搜索 (FTS5) |
|
|
文件: memory/search.go
type MemoryManager struct {
store Store
provider EmbeddingProvider
cache map[string]*VectorEmbedding
}
计算机使用
Shell 执行
|
|
|
|---|---|
| 沙箱
|
|
| 直接主机 |
|
| 远程设备 |
|
文件系统工具
-
read_file– 读取文件 -
write_file– 写入文件 -
edit_file– 编辑文件 -
list_files– 列出目录
浏览器工具 (Chrome DevTools Protocol)
-
browser_navigate– 导航到 URL -
browser_screenshot– 截取页面截图 -
browser_execute_script– 执行 JavaScript -
browser_click– 点击元素 -
browser_fill_input– 填写输入框 -
browser_get_text– 获取页面文本
文件: agent/tools/browser.go
type BrowserTool struct {
headless bool
timeout time.Duration
outputDir string
}
进程管理
-
后台长期命令 -
终止进程
安全机制
允许列表 (Allowlist)
{
"agents": {
"main": {
"allowlist": [
{ "pattern": "/usr/bin/npm", "lastUsedAt": 1706644800 },
{ "pattern": "/opt/homebrew/bin/git", "lastUsedAt": 1706644900 }
]
}
}
}
预批准的安全命令
jq、grep、cut、sort、uniq、head、tail、tr、wc 等
危险构造阻止
# 这些在执行前会被拒绝:
npm install $(cat /etc/passwd) # 命令替换
cat file > /etc/hosts # 重定向
rm -rf / || echo "failed" # 用 || 链接
(sudo rm -rf /) # 子shell
LLM 提供商与故障转移
支持的提供商
-
OpenAI(兼容接口) -
Anthropic -
OpenRouter
故障转移机制
文件: providers/failover.go
type FailoverProvider struct {
primary Provider
fallback Provider
circuitBreaker *CircuitBreaker
errorClassifier types.ErrorClassifier
}
特性:
-
断路器模式 – 防止连续失败时持续调用失败的提供商 -
错误分类 – 区分可重试和不可重试错误 -
自动切换 – 主提供商失败时自动切换到备用
技能系统 (Skills)
特性
-
Prompt-Driven – 技能本质上是注入到 System Prompt 中的指令集 -
OpenClaw 兼容 – 完全兼容 OpenClaw 的技能生态 -
自动准入 (Gating) – 智能检测系统环境
技能加载顺序
-
传入的自定义目录 -
workspace/skills/ -
workspace/.goclaw/skills/ -
可执行文件路径 /skills/ -
./skills/(当前目录,优先级最高)
项目结构
goclaw/
├── agent/ # Agent 核心逻辑
│ ├── loop.go # Agent 循环(含重试逻辑)
│ ├── context.go # 上下文构建器
│ ├── memory.go # 记忆系统
│ ├── skills.go # 技能加载器
│ ├── reflection.go # 反思机制
│ ├── error_classifier.go # 错误分类器
│ └── tools/ # 工具系统
│ ├── registry.go
│ ├── browser.go
│ ├── filesystem.go
│ ├── shell.go
│ └── ...
├── channels/ # 消息通道
├── bus/ # 消息总线
├── config/ # 配置管理
├── providers/ # LLM 提供商
│ ├── failover.go
│ ├── circuit.go
│ └── ...
├── session/ # 会话管理
├── memory/ # 记忆存储
├── cli/ # 命令行界面
└── gateway/ # 网关服务器
与 OpenClaw 的主要区别
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
快速开始
# 构建
go build -o goclaw .
# 配置
cat > config.json << EOF
{
"agents": {
"defaults": {
"model": "openrouter:anthropic/claude-opus-4-5",
"max_iterations": 15
}
},
"providers": {
"openrouter": {
"api_key": "your-key"
}
},
"channels": {
"telegram": {
"enabled": true,
"token": "your-bot-token"
}
}
}
EOF
# 启动
./goclaw start
总结
GoClaw 继承了 OpenClaw 的核心设计理念,同时利用 Go 语言的特性构建了一个更加健壮、高性能的 AI 助手。
设计原则:
-
极简核心 + 可扩展技能 -
串行默认,显式并行 -
可靠性优于复杂性 -
完全可观测(日志 + 会话持久化)
"这种简单性可能是优势也可能是陷阱,取决于你的视角。但我总是倾向于可解释的简单性,而不是复杂的意大利面条代码。"


