OpenClaw 是什么?从 Gateway 到 SQLite 拆解 AI Agent 运行链路

发布时间:2026/10/1 7:43:25
OpenClaw 是什么?从 Gateway 到 SQLite 拆解 AI Agent 运行链路
1. 从一次 Agent 请求说起OpenClaw 的 Gateway 到底在做什么如果你第一次接触 OpenClaw很容易被它“7×24 小时自主干活”的描述吸引但真正决定它能不能稳定跑起来的其实是背后那条从消息进入到状态落盘的完整链路。我把它拆成一句话Gateway 负责收单和路由Agent 负责思考和执行SQLite 负责把状态和记忆索引落盘。这三者缺一个Agent 就会变成“聊完就忘、重启就丢”的玩具。先说你最可能遇到的场景你在飞书里给 OpenClaw 发一句“帮我看下本地项目昨天的构建日志把报错原因整理出来”。这条消息不会直接进大模型而是先到 Gateway。Gateway 做三件事——鉴权、会话绑定、路由分发。鉴权确认这条消息来自已授权的 Channel会话绑定把这条消息挂到某个 Agent 实例的 session 上路由分发决定它该走哪个模型、加载哪份工作空间配置。为什么这一步重要因为 Agent 不是无状态函数。它要读SOUL.md、AGENTS.md、TOOLS.md还要从 SQLite 里召回历史记忆片段。如果 Gateway 没有正确绑定 sessionAgent 就会把上一次的任务上下文和这一次混在一起出现“答非所问”或者“重复执行”。我实测下来大部分“Agent 行为诡异”的问题根因都在 Gateway 的 session 映射上而不是模型本身。再往深一层看Gateway 还承担了请求排队与并发控制。OpenClaw 的心跳机制会定时唤醒 Agent如果你同时又在聊天窗口发指令两个请求可能同时到达。Gateway 需要决定是并行处理还是串行排队。默认配置下同一 session 的请求是串行的避免 Agent 在读写同一个文件时自己踩自己的坑。这个设计在本地调试时特别有用你可以放心地一边让心跳跑巡检一边手动发指令测试。理解 Gateway 的另一个角度是把它当成“反向代理 会话管理器”。它不负责智能只负责把正确的请求送到正确的 Agent再把 Agent 的输出送回正确的 Channel。这种职责分离让 OpenClaw 可以同时接入飞书、Telegram、本地终端等多个入口而 Agent 本身不需要关心消息从哪来。你后面配置 Gateway 时重点就是三块监听端口、Channel 适配器、session 存储位置。最后提醒一点Gateway 的日志是你排查问题的第一现场。当 Agent 没有响应、或者响应了但没落库先看 Gateway 日志里这条请求有没有成功路由、session ID 是什么、有没有报鉴权失败。很多人一上来就怀疑模型其实请求根本没走到模型那一步。把 Gateway 这一层看透后面的 SQLite 和 Agent 执行链路才有意义。2. TaoToken 前置准备给 Agent 接上稳定的模型出口OpenClaw 本身不生产模型能力它需要调用外部大模型 API。这里我用 TaoToken 作为模型出口来演示原因是它的接口格式兼容主流协议配置进 OpenClaw 的模型层比较直接。你需要先拿到两样东西API Key 和 Base URL。API 地址是https://taotoken.net/api注意这个地址不带任何查询参数直接作为 OpenAI 兼容协议的 base 使用。拿到 Key 之后不要急着往 OpenClaw 里塞。先在本地用 curl 验证一次确认 Key 有效、网络可达、模型 ID 正确。这一步能帮你排除掉后面 80% 的“Agent 不响应”问题。验证命令如下把$TAOTOKEN_KEY换成你自己的 Keycurl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_KEY \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-20250514, messages: [{role: user, content: 只回复 ok}], max_tokens: 16 }如果返回里能看到choices字段和内容说明模型出口通了。如果返回 401检查 Key 有没有复制完整、有没有多余空格如果返回 model not found说明模型 ID 写错了去控制台的模型列表里核对。这一步过了再进 OpenClaw 配置。接下来是 OpenClaw 侧的模型配置。OpenClaw 的模型层通常放在工作空间的配置目录里我用一个models.toml片段来演示路径按你实际安装位置调整[provider.taotoken] type openai-compatible base_url https://taotoken.net/api api_key_env TAOTOKEN_KEY default_model claude-sonnet-4-20250514 [provider.taotoken.models] fast claude-haiku-4-20250514 balanced claude-sonnet-4-20250514这里有个细节api_key_env指向环境变量而不是把 Key 明文写进配置文件。OpenClaw 在启动时会读取这个环境变量。你可以在启动脚本里export TAOTOKEN_KEY你的Key或者写进.env文件再 source。这样做的好处是配置文件可以安全地分享给同事不会泄露 Key。配置完成后OpenClaw 的 Agent 在需要调用模型时就会走provider.taotoken这个出口。你可以在 Gateway 日志里看到每次模型调用的耗时和 token 用量。如果发现调用失败先确认环境变量在当前 shell 里是否生效再确认 base_url 有没有多写或少写/v1。不同版本的 OpenClaw 对 base_url 拼接方式略有差异以你实际日志里打印出的完整请求 URL 为准。另外如果你打算长期跑 Agent 任务建议在 TaoToken 控制台里给这个 Key 设置用量上限或告警。Agent 的心跳和反思循环会持续消耗 token有个上限能避免意外账单。这不是 OpenClaw 的问题而是所有常驻 Agent 的共性提前设好边界比事后补救省心得多。3. 可复制配置Gateway 与 SQLite 的落地写法这一节给你两份可以直接抄的配置一份是 Gateway 的一份是 SQLite 的。先说 Gateway。OpenClaw 的 Gateway 配置通常是一个 JSON 文件放在工作空间的config/目录下。下面这个片段定义了监听端口、Channel 适配器和 session 存储{ gateway: { host: 127.0.0.1, port: 8787, auth: { mode: token, token_env: OPENCLAW_GATEWAY_TOKEN }, session: { store: sqlite, sqlite_path: ./data/sessions.db, ttl_hours: 72 }, channels: [ { type: feishu, enabled: true, app_id_env: FEISHU_APP_ID, app_secret_env: FEISHU_APP_SECRET }, { type: local_terminal, enabled: true } ] } }几个关键点host用127.0.0.1而不是0.0.0.0避免本地调试时被局域网其他设备访问auth.mode用 tokentoken 从环境变量读session.store设为sqlite并指定数据库路径。ttl_hours控制 session 过期时间超过 72 小时没活动的 session 会被清理避免数据库无限膨胀。然后是 SQLite 的表结构。OpenClaw 的 session 存储至少需要三张表会话表、消息表、记忆索引表。下面是我实际用的建表语句你可以直接在sqlite3里执行CREATE TABLE IF NOT EXISTS sessions ( id TEXT PRIMARY KEY, channel_type TEXT NOT NULL, channel_user_id TEXT NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, status TEXT DEFAULT active ); CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL, role TEXT NOT NULL, content TEXT NOT NULL, token_count INTEGER DEFAULT 0, created_at INTEGER NOT NULL, FOREIGN KEY (session_id) REFERENCES sessions(id) ); CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id, created_at); CREATE TABLE IF NOT EXISTS memory_index ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL, chunk_text TEXT NOT NULL, embedding BLOB, source_file TEXT, created_at INTEGER NOT NULL ); CREATE INDEX IF NOT EXISTS idx_memory_session ON memory_index(session_id, created_at);messages表存的是短期对话流水memory_index表存的是从MEMORY.md切分出来的记忆块和向量。注意embedding用 BLOB 存因为 SQLite 没有原生向量类型OpenClaw 会把向量序列化成二进制存进去。查询时用向量相似度函数配合 BM25 做双路召回。配置写完后启动 Gateway 前先确认数据库文件所在目录存在否则 SQLite 会报 unable to open database file。你可以手动mkdir -p ./data再启动。启动后访问http://127.0.0.1:8787/health如果返回{status:ok}说明 Gateway 起来了。这一步过了再往下做请求验证。4. 验证请求一次完整 Agent 任务的调用与落库现在我们把前面配好的东西串起来跑一次完整任务。目标很简单通过本地终端 Channel 发一条指令让 Agent 读取一个本地文件并总结然后确认消息和记忆都落进了 SQLite。第一步启动 OpenClaw 主进程和 Gateway。假设你的启动命令是openclaw start启动后观察日志里有没有gateway listening on 127.0.0.1:8787和sqlite session store ready。这两行出现说明 Gateway 和 SQLite 都初始化成功。第二步通过本地终端 Channel 发指令。OpenClaw 的本地终端适配器通常会提供一个 CLI 入口类似openclaw send --channel local --message 读取 ./README.md用三句话总结项目用途这条命令会把消息交给 GatewayGateway 鉴权后绑定 session路由给 Agent。Agent 加载工作空间配置调用模型模型返回总结Agent 把结果写回 Channel同时把这条消息和回复写入messages表。第三步验证落库。用 sqlite3 打开数据库sqlite3 ./data/sessions.db SELECT id, channel_type, status FROM sessions ORDER BY created_at DESC LIMIT 3;你应该能看到刚才那条会话channel_type是localstatus是active。再查消息sqlite3 ./data/sessions.db SELECT role, substr(content,1,60), token_count FROM messages ORDER BY created_at DESC LIMIT 5;如果能看到 user 和 assistant 两条记录说明消息落库成功。token_count如果为 0说明你的 OpenClaw 版本没有开启 token 统计不影响功能但建议开启以便控制成本。第四步验证记忆索引。如果这次对话触发了记忆提炼通常需要对话足够长或包含明确事实memory_index表里会出现新记录sqlite3 ./data/sessions.db SELECT session_id, substr(chunk_text,1,80), source_file FROM memory_index ORDER BY created_at DESC LIMIT 3;source_file应该指向MEMORY.md或对应的 session 日志文件。如果这里为空说明记忆提炼还没触发你可以多聊几轮再查。整个链路跑通后你会得到一个可复现的本地调试路径发指令 → 看 Gateway 日志 → 查 SQLite 表 → 确认 Agent 行为。这套流程我用了很多次每次改配置或换模型后都跑一遍能快速定位问题出在哪一层。比盲目看 Agent 输出靠谱得多。5. 常见报错排查401、local proxy failed 与 reading choices这一节列几个我实际踩过的报错以及对应的排查路径。第一个是401 Unauthorized。这个报错通常出现在模型调用层说明 TaoToken 的 Key 无效或没被正确读取。先确认环境变量在当前进程里可见echo $TAOTOKEN_KEY。如果为空说明启动 OpenClaw 的 shell 没有 source 到 Key。如果 Key 有值但还报 401检查配置文件里api_key_env拼写是否和实际环境变量名一致大小写敏感。第二个是local proxy failed。这个报错一般出现在 Gateway 尝试连接本地模型代理或转发请求时。常见原因是 Gateway 配置里的上游地址写错或者本地代理进程没启动。先看 Gateway 日志里打印的目标 URL确认端口和路径正确。如果你用的是 TaoToken 的 API 地址确认写的是https://taotoken.net/api而不是带/v1的变体具体以你配置文件里的拼接逻辑为准。另外检查本机防火墙有没有拦截出站请求。第三个是reading choices相关报错完整信息通常是error reading choices from response或choices field missing。这说明模型返回的 JSON 结构不符合预期。可能原因有三个模型 ID 写错导致返回了错误结构base_url 拼接后实际请求到了非兼容端点或者返回被中间层截断。排查方法是把 OpenClaw 发出的原始请求和收到的原始响应打到日志里对比标准 OpenAI 兼容格式。如果响应里没有choices字段先单独用 curl 测同一个模型 ID确认 API 本身正常。第四个是 OAuth 相关报错比如OAuth token expired或invalid_grant。如果你在 Channel 适配器里用了 OAuth 方式接入飞书或其他平台token 过期是正常现象。检查你的刷新逻辑有没有生效或者重新走一遍授权流程。OpenClaw 的 Channel 配置里通常有refresh_token字段确认它被正确保存和读取。最后一个高频问题是 Agent 不响应但 Gateway 日志正常。这种情况先查 session 状态确认 session 没有被标记为expired或blocked。再查 Agent 进程是否还在运行有时候 Agent 因为未捕获异常退出了Gateway 还在但没人处理请求。重启 Agent 进程通常能解决。如果重启后仍然不响应检查工作空间配置文件有没有语法错误比如 JSON 少了个逗号导致 Agent 启动时加载配置失败。6. 把链路用起来从调试到长期运行的几个建议跑通一次请求只是开始真正让 OpenClaw 稳定干活需要在几个地方做取舍。第一是 session 的 TTL 设置。默认 72 小时对大多数场景够用但如果你希望 Agent 记住更长时间的对话上下文可以调大代价是 SQLite 文件增长更快。我的做法是定期把旧 session 归档到单独数据库主库只保留最近一周的活跃 session。第二是记忆索引的更新频率。memory_index表不是越大越好向量检索的耗时和索引规模正相关。OpenClaw 通常会在MEMORY.md变更时增量更新索引但如果你手动编辑了MEMORY.md记得触发一次重建否则检索结果会和文件内容不一致。重建命令一般在 OpenClaw 的 CLI 里类似openclaw memory reindex。第三是 Gateway 的日志级别。调试阶段用 debug能看到每条请求的完整路由路径长期运行时切到 info避免日志文件把磁盘写满。日志轮转也要配好否则跑几周就会发现日志比数据库还大。第四是模型出口的稳定性。Agent 的心跳和反思循环会持续调用模型如果出口不稳定Agent 会频繁重试既慢又费 token。TaoToken 的接口在我实测中比较稳定但你仍然应该在配置里加上超时和重试上限避免单个请求卡死整个 Agent 循环。最后一点不要把 OpenClaw 当成“配好就不用管”的黑盒。它的行为高度依赖工作空间里的 Markdown 文件和 SQLite 里的记忆索引。定期打开MEMORY.md看看它记了什么打开 SQLite 看看 session 和消息有没有异常增长比出了问题再排查省事得多。这套链路的价值在于透明你能看到每一步发生了什么也能在每一步介入调整。把它当成一个需要持续维护的本地服务而不是一次性安装的软件用起来会顺手很多。