[转][译] 从零开始构建 OpenClaw — 第一部分(智能体核心)
[转][译] 从零开始构建 OpenClaw — 第二部分(技能插件系统)
[转][译] 从零开始构建 OpenClaw — 第三部分(元技能)
在这里,我们将构建一个精简版的 openclaw。一个功能齐全的 AI 编码平台,简化到其本质——没有 Web UI,没有通道抽象,没有部署开销——并在您的终端中作为一个简单的 REPL 运行?这正是 openclaw-mini 的目标。
这是源代码的链接
它是一个仅依赖终端的 AI 编程智能体,使用与完整 OpenClaw 平台相同的引擎。它可以读取、写入和编辑您的文件,运行 Shell 命令,搜索网络,获取文档,并维护持久会话——所有这些都可以从一个 > 提示符中完成。
在本文中,我将介绍它的功能、构建方式以及完整的架构——从 REPL 循环到工具执行层。
openclaw-mini 能做什么
openclaw-mini 的核心是一个智能编码助手。你输入一个请求,它就会自动使用工具来满足你的需求。以下是它的全部功能:
文件操作
- 读取文件以理解你的代码库
- 从零开始编写新文件
- 对现有文件进行精确、有针对性的修改
Shell 执行
- 具有完全访问您终端环境的 Bash 命令
- 运行测试、安装包、管理 git——任何你在 shell 中会做的事情
网络研究
- 使用 Brave Search API 或 Perplexity 进行网络搜索(自动回退)
- 网络获取,用于从任何 URL 抓取和提取可读内容,使用 Mozilla 的 Readability 算法将 HTML 转换为干净的 markdown
会话持久化
- 每场对话都会以 JSON 文件的形式保存到磁盘上
- 从这里继续,或者使用
/new从头开始
多提供者 LLM 支持
- 开箱即用,支持 9 家 AI 提供商:Anthropic、OpenAI、Google、Groq、X.AI、Mistral、OpenRouter、Cerebras 和 Ollama
- 通过单个环境变量切换提供商
项目上下文感知
- 自动从您的工作区加载上下文文件:
CONTEXT.md、INSTRUCTIONS.md、SOUL.md、CLAUDE.md、.github/copilot-instructions.md - 您的项目特定指令成为智能体的系统提示的一部分
扩展思考
- 使用
/think on或/think stream切换 Claude 的扩展思考模式 - 观看模型逐步推理复杂问题
交互式 REPL 命令
/new— 开始一个新的会话/think [off|on|stream]— 控制扩展思考/model— 显示当前模型信息/status— 显示完整会话状态/quit— 优雅退出
架构概述
以下是单个用户提示词如何通过系统的层级架构:
┌─────────────────────────────────────────────────────────────┐
│ TERMINAL (REPL) │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ User types: "Add error handling to the login route" │ │
│ └───────────────────────┬───────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ SLASH COMMAND ROUTER │ │
│ │ /new /think /model /status /quit │ │
│ │ (if not a command → continue to agent) │ │
│ └───────────────────────┬───────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ SESSION MANAGER │ │
│ │ Load/create session from │ │
│ │ ~/.openclaw-mini/state/sessions/mini/{id}.json │ │
│ └───────────────────────┬───────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ PI SDK (Agent Session) │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ System Prompt (dynamically built) │ │ │
│ │ │ • Runtime info (OS, shell, model, timezone) │ │ │
│ │ │ • Available tools list │ │ │
│ │ │ • Project context files │ │ │
│ │ │ • Safety constraints │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ Tool Registry │ │ │
│ │ │ Built-in: read, write, edit, bash │ │ │
│ │ │ Custom: web_search, web_fetch │ │ │
│ │ └──────────────────────┬──────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────┴──────────┐ │ │
│ │ ▼ ▼ │ │
│ │ ┌──────────────────┐ ┌──────────────────────┐ │ │
│ │ │ LLM API Call │ │ Tool Execution Loop │ │ │
│ │ │ (Anthropic, │◄►│ model requests tool │ │ │
│ │ │ OpenAI, etc.) │ │ → execute → return │ │ │
│ │ └──────────────────┘ └──────────────────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ OUTPUT EXTRACTION │ │
│ │ • Extract assistant text from messages │ │
│ │ • List tool calls: [tools: read, edit, bash] │ │
│ │ • Display timing: (2.3s) │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
深入解析:入口
一切始于 src/entry.ts 。这个文件是神经中枢——它将配置、认证、REPL 和智能体循环连接在一起。
配置
智能体将其状态存储在一个定义良好的目录结构下:
const OPENCLAW_MINI_HOME = path.join(os.homedir(), ".openclaw-mini");
const AGENT_DIR = path.join(OPENCLAW_MINI_HOME, "agents", AGENT_ID, "agent");
const SESSION_DIR = path.join(OPENCLAW_MINI_HOME, "state", "sessions", "mini");
模型和提供者可以通过环境变量进行配置,具有合理的默认值:
const DEFAULT_PROVIDER = process.env.OPENCLAW_MINI_PROVIDER ?? "anthropic";
const DEFAULT_MODEL = process.env.OPENCLAW_MINI_MODEL ?? "claude-sonnet-4-20250514";
认证
认证系统是分层的。它首先检查提供者的 API 密钥的环境变量,然后回退到主 OpenClaw 平台也使用的共享认证配置文件:
function ensureApiKeyInEnv(provider: string): boolean {
const envKeys = ENV_KEY_MAP[provider] ?? [`${provider.toUpperCase()}_API_KEY`];
// Check environment variables first
for (const envKey of envKeys) {
if (process.env[envKey]) return true;
} // Fall back to shared auth profiles
const apiKey = loadApiKeyFromProfiles(provider);
if (apiKey && envKeys[0]) {
process.env[envKeys[0]] = apiKey;
return true;
} return false;
}
这意味着如果你已经配置了完整的 OpenClaw 应用程序,openclaw-mini 会自动获取你的凭证。
REPL 循环
应用程序的核心是一个 while(true) .readline 循环。启动时,它会打印一个干净的状态横幅:
┌ openclaw-mini
│ model: anthropic/claude-sonnet-4-20250514
│ workspace: /Users/you/my-project
│ session: mini-1708123456789
│ context: CONTEXT.md, CLAUDE.md
│ tools: read, bash, edit, write, web_search, web_fetch
└ /new /think /model /quit
每次迭代要么处理一个斜杠命令,要么运行智能体:
while (true) {
const input = await rl.question("> ");
const trimmed = input.trim();
// Handle slash commands: /quit, /new, /model, /think, /status
if (trimmed === "/quit" || trimmed === "/exit") break;
if (trimmed === "/new") { /* reset session */ continue; }
// ... other commands // Run the agent
const sessionManager = SessionManager.open(sessionFile);
const { session } = await createAgentSession({
cwd: workspaceDir,
model,
customTools,
sessionManager,
// ...
}); applySystemPromptToSession(session, currentSystemPrompt);
await session.prompt(trimmed); // Display results
const toolCalls = extractToolCalls(session.messages);
const text = session.getLastAssistantText();
console.log(text);
console.log(`[tools: ${toolCalls.join(", ")}]`);
console.log(`(${elapsed}s)`);
}
深入解析:系统提示词
系统提示符定义了 openclaw-mini 的性格和能力。每次提交提示符时,它都会动态构建(以便反映当前的思考水平、时间和加载的上下文)。
结构
buildSystemPrompt() 函数组装这些部分:
- 身份:“你是一个在 openclaw-mini 内部运行的个人编程助手。”
- 工具:列出所有可用工具及其描述
- 调用风格:避免不必要的叙述——直接调用工具
- 安全:不自我保护,不追求权力,优先考虑人工监督
- 工作区:当前工作目录
- 日期和时间:用户所在时区的当前时间
- llms.txt 发现:指导检查新域名上的
/llms.txt(AI 交互指南的新兴标准) - 项目上下文:任何已加载的上下文文件的内容
- 运行时:主机、操作系统、架构、Node 版本、Shell、模型、提供者、思考级别
上下文文件加载
这是其中一个非常实用的功能。智能体会自动从你的工作区读取项目指令文件:
const CONTEXT_FILE_NAMES = [
"CONTEXT.md",
"INSTRUCTIONS.md",
"INSTRUCTIONS.txt",
"SOUL.md",
"CLAUDE.md",
".openclaw-mini/CONTEXT.md",
".github/copilot-instructions.md",
];
如果你的项目根目录中有 CLAUDE.md 文件,其中包含类似“始终使用 Bun 而不是 npm”或“遵循仓库的错误处理模式”的指令,这些指令将成为智能体提示的一部分。它与 OpenClaw 的 CONTEXT.md 约定和 GitHub Copilot 的 .github/copilot-instructions.md 都兼容。
SOUL.md 文件会得到特殊处理——如果存在,智能体会被告知“体现其角色和语气”,从而实现个性化定制。
深入解析:自定义工具
PI SDK 提供了用于文件操作( read , write , edit )和 Shell 访问( bash )的内置工具。openclaw-mini 在此基础上增加了两个自定义工具:web_fetch 和 web_search。
web_fetch:URL 内容提取
该工具获取一个 URL 并提取干净、可读的内容。它就像一个专为 LLM 消费设计的专注型网络爬虫。
工作原理:
function htmlToMarkdown(html: string, url: string) {
const { document } = parseHTML(html);
const reader = new Readability(document);
const article = reader.parse();
return { text: article.content, title: article.title };
}
@mozilla/readability + linkedom 的组合可以在无需无头浏览器的情况下实现高质量的文本提取。它会移除导航、广告和冗余内容,只返回文章主体内容。
网络搜索:双重提供者网络搜索
搜索工具支持两种后端,并自动选择提供者:
- Brave Search(默认)— 传统搜索结果,包含标题、URL 和描述
- 困惑度(备用)— 基于人工智能的搜索,提供综合答案和引用
提供者选择基于哪些 API 密钥可用:
function resolveProvider(): SearchProvider {
if (process.env.PERPLEXITY_API_KEY || process.env.OPENROUTER_API_KEY) {
if (!process.env.BRAVE_API_KEY) return "perplexity";
}
return "brave";
}
Brave Search 支持高级参数,如 country (特定区域的结果)和 freshness (按时间过滤:过去一天、一周、一个月、一年或自定义日期范围)。
两个提供者都会缓存结果 5 分钟,以避免会话期间重复的 API 调用。
智能体循环:从提示到响应
当你输入消息并按下 Enter 键时会发生以下情况:
1. REPL captures input
│
2. SessionManager loads/creates session from disk
│
3. createAgentSession() initializes:
• PI SDK agent with model config
• Built-in tools (read, write, edit, bash)
• Custom tools (web_search, web_fetch)
• Auth credentials
│
4. System prompt is rebuilt and injected
(overrides SDK default with enriched version)
│
5. session.prompt(userInput) starts the agent loop:
┌──────────────────────────────────────┐
│ LLM receives: system prompt + │
│ conversation history + user message │
│ │ │
│ ▼ │
│ LLM decides: respond OR use tools │
│ │ │
│ ┌────┴────┐ │
│ ▼ ▼ │
│ Response Tool Call │
│ (done) (execute → loop back) │
└──────────────────────────────────────┘
│
6. Extract results:
• Last assistant text message
• List of all tool calls made
│
7. Display to user + timing info
│
8. Session saved to disk automatically
关键在于 PI SDK 处理内部循环(步骤 5)。模型可以按顺序进行多个工具调用——读取文件、运行命令、编辑代码——然后再生成最终的文本响应。openclaw-mini 只需要设置会话、传递提示并显示结果。
系统提示词覆盖
一个有趣的实现细节:PI SDK 在内部构建自己的默认系统提示。openclaw-mini 使用自定义的丰富版本覆盖它:
function applySystemPromptToSession(session: any, systemPrompt: string) {
session.agent.setSystemPrompt(systemPrompt);
// Prevent SDK from rebuilding its default prompt
const mutable = session as unknown as {
_baseSystemPrompt?: string;
_rebuildSystemPrompt?: (toolNames: string[]) => string;
};
mutable._baseSystemPrompt = systemPrompt;
mutable._rebuildSystemPrompt = () => systemPrompt;
}
这确保了智能体始终使用包含上下文文件、运行时信息和完整工具描述的丰富提示,而不是 SDK 的通用默认值。
多提供者 LLM 支持
openclaw-mini 的一个优势在于,切换 AI 后端只需修改一行环境变量。在底层,它将每个提供者映射到正确的 API 协议:
function resolveApiType(provider: string): string {
const apiMap: Record<string, string> = {
anthropic: "anthropic", // Native Anthropic Messages API
openai: "openai-responses", // OpenAI Responses API
google: "google", // Google Gemini API
ollama: "ollama", // Local Ollama
groq: "openai", // OpenAI-compatible
xai: "openai", // OpenAI-compatible
mistral: "openai", // OpenAI-compatible
openrouter: "openai", // OpenAI-compatible
cerebras: "openai", // OpenAI-compatible
};
return apiMap[provider] ?? "openai";
}
许多提供者(Groq、X.AI、Mistral、OpenRouter、Cerebras)使用与 OpenAI 兼容的 API 格式,因此它们都映射到 "openai" 。这意味着添加一个新的 OpenAI 兼容提供者只需在这张映射中添加一行。
要切换提供者:
# Use Anthropic Claude (default)
ANTHROPIC_API_KEY=sk-ant-... openclaw-mini
# Use OpenAI GPT-4
OPENCLAW_MINI_PROVIDER=openai OPENCLAW_MODEL=gpt-4o OPENAI_API_KEY=sk-... openclaw-mini# Use local Ollama
OPENCLAW_MINI_PROVIDER=ollama OPENCLAW_MODEL=llama3 openclaw-mini# Use Groq for speed
OPENCLAW_MINI_PROVIDER=groq OPENCLAW_MODEL=llama-3.1-70b GROQ_API_KEY=... openclaw-mini
关键设计决策
为什么有~1000 行代码?
openclaw-mini 刻意避免重新实现 PI SDK 已经提供的内容。SDK 处理:
- 智能体循环(提示→工具调用→响应循环)
- 内置工具执行(文件 I/O,Shell 命令)
- 消息历史管理
- 模型 API 通信
- 流式传输
openclaw-mini 仅添加 SDK 未提供的功能:
- 一个终端 REPL 界面
- 网络研究工具(搜索+获取)
- 带上下文文件的动态系统提示
- 多提供者身份解析
无通道开销
完整的 OpenClaw 平台通过“通道”进行路由——Discord、Slack、Web UI 等。每个通道都会增加序列化、消息格式化和特定协议的逻辑。openclaw-mini 绕过了所有这些。它直接与 PI SDK 的 createAgentSession() 通信,这意味着:
- 从通道初始化到零启动延迟
- 无需消息格式转换
- 从模型直接流式传输到您的终端
上下文文件兼容性
支持 CLAUDE.md 、 INSTRUCTIONS.md 、 SOUL.md 、 .github/copilot-instructions.md 和 CONTEXT.md 的选择是故意的。如果您已经有了 Claude Code、GitHub Copilot 或完整 OpenClaw 平台的项目说明,openclaw-mini 会自动读取它们。无需额外配置。
无处不在的缓存
两种网络工具都实现了 5 分钟的内存缓存。在编程会话期间,你经常搜索相同的内容或重新获取相同的文档页面。缓存避免了冗余的 API 调用,并显著提高了重复请求的速度。
技术栈
自行运行
# Clone and install
git clone <repo-url>
cd openclaw-mini
pnpm install
# Set your API key
export ANTHROPIC_API_KEY=sk-ant-...# Run in development mode
pnpm dev# Or build and run
pnpm build
pnpm start
可选的环境变量以启用附加功能:
# Web search (pick one)
export BRAVE_API_KEY=... # For Brave Search
export PERPLEXITY_API_KEY=... # For Perplexity
export OPENROUTER_API_KEY=... # For Perplexity via OpenRouter
# Switch AI provider
export OPENCLAW_MINI_PROVIDER=openai
export OPENCLAW_MINI_MODEL=gpt-4o
export OPENAI_API_KEY=sk-...
总结
openclaw-mini 证明了强大的 AI 编码智能体不需要复杂。通过借助 PI SDK 进行重负载处理,并添加一层 REPL、认证、系统提示和 Web 工具,你只需大约 1,000 行 TypeScript 代码(分布在 4 个文件中)就能得到一个功能完备的终端助手。
它拥有与完整 OpenClaw 平台相同的智能,只是被提炼到了本质。没有 UI,没有通道,没有部署。