[转][译] 从零开始构建 OpenClaw — 第一部分(智能体核心)

12 阅读10分钟

[转][译] 从零开始构建 OpenClaw — 第一部分(智能体核心)

[转][译] 从零开始构建 OpenClaw — 第二部分(技能插件系统)

[转][译] 从零开始构建 OpenClaw — 第三部分(元技能)

[转][译] 从零开始构建 OpenClaw — 第四部分(工具循环检测)

[转][译] 从零开始构建 OpenClaw — 第五部分(对话压缩)

原文:Building Openclaw from Scratch — Part 1 (The Agent Core)

在这里,我们将构建一个精简版的 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 commandcontinue 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-20250514workspace: /Users/you/my-project
    │ session: mini-1708123456789context: CONTEXT.md, CLAUDE.mdtools: 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() 函数组装这些部分:

  1. 身份:“你是一个在 openclaw-mini 内部运行的个人编程助手。”
  2. 工具:列出所有可用工具及其描述
  3. 调用风格:避免不必要的叙述——直接调用工具
  4. 安全:不自我保护,不追求权力,优先考虑人工监督
  5. 工作区:当前工作目录
  6. 日期和时间:用户所在时区的当前时间
  7. llms.txt 发现:指导检查新域名上的 /llms.txt (AI 交互指南的新兴标准)
  8. 项目上下文:任何已加载的上下文文件的内容
  9. 运行时:主机、操作系统、架构、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,没有通道,没有部署。