專屬AI Agent:基于OpenClaw龍蝦智能體完整實戰(zhàn)指南(TaoToken統(tǒng)一Key接入篇))
1. 為什么我要自己擼一個 OpenClaw 龍蝦智能體市面上大部分 AI 對話工具本質(zhì)還是“你問一句它答一句”。關(guān)掉窗口它就把你忘了想讓它幫你整理個文件、查個天氣、跑個定時任務(wù)它只會禮貌地告訴你“我做不到”。我想要的不是這種問答機器人而是一個能自己感知、自己規(guī)劃、自己動手、還能記住事的本地智能體。OpenClaw圈里叫龍蝦智能體就是沖著這個目標(biāo)去的開源框架它把“理解—規(guī)劃—執(zhí)行—記憶—迭代”這一整套閉環(huán)塞進了一個可以本地跑的 Node.js 項目里。這篇實戰(zhàn)指南面向的是想從零手寫一個專屬 AI Agent 的開發(fā)者尤其是習(xí)慣 Node.js、想用 SQLite 做本地記憶、又不想被各種模型 Key 管理折騰的人。我會帶你搭出 OpenClaw 的最小可運行骨架目錄結(jié)構(gòu)、SQLite 建表、Agent 主循環(huán)代碼最后把模型 endpoint 和 Key 統(tǒng)一改到 TaoToken 通道上發(fā)一條測試消息驗證閉環(huán)真的跑通了。全程可復(fù)制踩坑點我會標(biāo)出來。核心檢索詞先擺在這OpenClaw 是一個本地自主智能體框架AI Agent 是它的產(chǎn)物Node.js 是運行底座SQLite 是記憶底座。適合誰適合想擁有一個“越用越懂你”的本地數(shù)字助手、又愿意動手寫點代碼的人。下面直接開干。2. 前置準(zhǔn)備TaoToken 統(tǒng)一 Key 與 OpenClaw 環(huán)境在寫代碼之前先把兩件事搞定模型通道和環(huán)境依賴。模型這塊我用 TaoToken 做統(tǒng)一入口好處是一個 Key 能覆蓋多種模型不用在 OpenClaw 里到處改 provider 配置。官網(wǎng)在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 注意這個 API 地址后面不加任何參數(shù)。先去控制臺建一個 Key路徑是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 在 API Keys 頁面生成頁面在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。拿到形如sk-xxxx的字符串先存好后面配置里要用。想先確認(rèn)模型通不通可以直接在模型對話頁 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 發(fā)一句話試試能回就說明 Key 沒問題。環(huán)境依賴三樣Node.js 18 以上我用 18.20 實測穩(wěn)定、Git、SQLite3macOS 和多數(shù) Linux 自帶Windows 建議裝個 sqlite3 命令行方便調(diào)試。檢查命令node -v npm -v sqlite3 --version三個都出版本號就 OK。接著建項目目錄我習(xí)慣叫openclaw-lobstermkdir openclaw-lobster cd openclaw-lobster npm init -y npm install better-sqlite3 node-fetch3這里我選better-sqlite3而不是原生 sqlite3因為它是同步 API寫 Agent 主循環(huán)時邏輯更直白不用被回調(diào)繞暈。node-fetch3用來發(fā)模型請求。裝完目錄里會有node_modules和package.json在package.json里加一行type: module這樣后面能用 import 語法。目錄結(jié)構(gòu)我規(guī)劃成這樣先建好空文件夾openclaw-lobster/ ├── src/ │ ├── agent.js # Agent 主循環(huán) │ ├── memory.js # SQLite 記憶層 │ ├── llm.js # 模型調(diào)用封裝 │ └── tools.js # 技能注冊 ├── data/ │ └── lobster.db # SQLite 數(shù)據(jù)庫文件 ├── config.json # 模型與網(wǎng)關(guān)配置 └── package.jsonmkdir -p src data到這一步TaoToken 的 Key 和環(huán)境都齊了。接下來進入真正的代碼環(huán)節(jié)先把記憶底座 SQLite 建起來因為 Agent 的“記性”全靠它。3. 可復(fù)制配置SQLite 建表與 config.json 接入 TaoTokenAgent 的記憶分三塊原始對話、任務(wù)日志、配置信息。我用一張messages表存對話一張tasks表存任務(wù)執(zhí)行記錄再加一張kv表存運行時狀態(tài)。建表語句直接寫進src/memory.js的初始化函數(shù)里這樣每次啟動自動建表不用手動跑 SQL。// src/memory.js import Database from better-sqlite3; const db new Database(./data/lobster.db); db.pragma(journal_mode WAL); export function initDB() { db.exec( CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, role TEXT NOT NULL, content TEXT NOT NULL, created_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, status TEXT NOT NULL, result TEXT, created_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS kv ( key TEXT PRIMARY KEY, value TEXT NOT NULL ); ); } export function saveMessage(role, content) { const stmt db.prepare( INSERT INTO messages (role, content, created_at) VALUES (?, ?, ?) ); return stmt.run(role, content, Date.now()); } export function recentMessages(limit 20) { const stmt db.prepare( SELECT role, content FROM messages ORDER BY id DESC LIMIT ? ); return stmt.all(limit).reverse(); } export function saveTask(name, status, result ) { const stmt db.prepare( INSERT INTO tasks (name, status, result, created_at) VALUES (?, ?, ?, ?) ); return stmt.run(name, status, result, Date.now()); }journal_mode WAL這行別省Agent 頻繁讀寫時它能明顯減少鎖等待。recentMessages里我做了reverse()因為 SQL 是倒序取最近 N 條返回給模型時要按時間正序排。然后是config.json這是接入 TaoToken 的關(guān)鍵。Base URL、Key、Model ID 三件套都在這里{ model: { provider: openai-compatible, baseUrl: https://taotoken.net/api, apiKey: sk-你的TaoToken密鑰, modelId: gpt-4o-mini, maxTokens: 1024 }, agent: { name: 小鉗, heartbeatInterval: 1800000, memoryLimit: 20 } }注意baseUrl寫https://taotoken.net/api不要帶斜杠結(jié)尾也不要在后面拼/v1之類的路徑具體路徑由llm.js里的請求拼接決定。modelId可以換成你在模型對話頁看到的任意可用模型名。Key 建議用環(huán)境變量覆蓋避免明文進 Git// src/llm.js 里讀取時 const apiKey process.env.TAOTOKEN_API_KEY || config.model.apiKey;啟動前export TAOTOKEN_API_KEYsk-xxxx即可。這樣配置和代碼分離換 Key 不用改文件。配置就緒下面寫 Agent 主循環(huán)。4. 驗證請求Agent 主循環(huán)跑通首個對話閉環(huán)主循環(huán)是 OpenClaw 的心臟邏輯是加載歷史記憶 → 拼上下文 → 調(diào)模型 → 解析回復(fù) → 回寫記憶。先寫src/llm.js封裝請求// src/llm.js import fetch from node-fetch; import fs from fs; const config JSON.parse(fs.readFileSync(./config.json, utf-8)); const apiKey process.env.TAOTOKEN_API_KEY || config.model.apiKey; export async function chat(messages) { const res await fetch(${config.model.baseUrl}/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${apiKey} }, body: JSON.stringify({ model: config.model.modelId, messages, max_tokens: config.model.maxTokens }) }); if (!res.ok) { const errText await res.text(); throw new Error(LLM request failed: ${res.status} ${errText}); } const data await res.json(); return data.choices[0].message.content; }這里res.ok判斷很關(guān)鍵401 和 404 都會在這里被攔下來并打印原始錯誤方便排障。接著寫src/agent.js// src/agent.js import { initDB, saveMessage, recentMessages } from ./memory.js; import { chat } from ./llm.js; initDB(); const SYSTEM_PROMPT 你是本地智能體「小鉗」回答簡潔精準(zhǔn)優(yōu)先給出可執(zhí)行結(jié)果。 涉及文件刪除、覆蓋等高危操作必須先向用戶確認(rèn)。; export async function runAgent(userInput) { saveMessage(user, userInput); const history recentMessages(20); const messages [ { role: system, content: SYSTEM_PROMPT }, ...history ]; const reply await chat(messages); saveMessage(assistant, reply); return reply; } // 命令行直接測試 const input process.argv.slice(2).join( ) || 你好做個自我介紹; runAgent(input) .then((r) console.log(\n[小鉗] r)) .catch((e) console.error(\n[錯誤] e.message));跑起來驗證node src/agent.js 你好你現(xiàn)在能記住我說的話嗎如果配置正確終端會打印小鉗的回復(fù)。再跑一次帶上下文的node src/agent.js 我上一句問了你什么第二次能答出第一次的內(nèi)容說明 SQLite 記憶閉環(huán)生效了。這一步是整個實戰(zhàn)的驗收點模型請求走的是 TaoToken 的https://taotoken.net/apiKey 是統(tǒng)一 Key返回正常就代表接入成功。如果第一次就報錯別慌下一節(jié)專門排。5. 本篇常見錯排查401、local proxy failed 與 reading choices排障這塊我按真實遇到的報錯來每個都給定位思路。401 Unauthorized。最常見報錯長這樣LLM request failed: 401 {error:{message:Invalid API key}}。原因通常是 Key 沒讀到或?qū)戝e了。先確認(rèn)echo $TAOTOKEN_API_KEY有值再檢查config.json里的apiKey是不是還留著占位符。還有一種情況是 Key 前后帶了空格或換行復(fù)制時容易帶上用trim()處理一下。如果 Key 確認(rèn)沒問題還是 401去 API Keys 頁面看這個 Key 是不是被禁用或額度用盡。local proxy failed / ECONNREFUSED。這個報錯說明請求根本沒發(fā)出去卡在本地網(wǎng)絡(luò)層。檢查baseUrl是不是寫成了https://taotoken.net/api/多了斜杠或者誤加了端口。另外確認(rèn)機器能正常訪問外網(wǎng)curl https://taotoken.net/api看有沒有響應(yīng)。如果公司網(wǎng)絡(luò)有出口限制換網(wǎng)絡(luò)環(huán)境再試。注意這里不要引入任何本地代理配置直連即可。Cannot read properties of undefined (reading choices)。這個報錯說明data.choices是 undefined通常是響應(yīng)結(jié)構(gòu)和你預(yù)期的不一樣。可能是modelId寫錯了服務(wù)端返回了一個錯誤對象而不是正常 completion。打印完整data看看const data await res.json(); console.log(JSON.stringify(data, null, 2));如果看到{error: ...}那就是模型名或參數(shù)問題。還有一種可能是baseUrl拼出來的路徑不對比如重復(fù)拼了/v1實際請求打到了不存在的路由。確認(rèn)baseUrl是https://taotoken.net/api代碼里拼/v1/chat/completions。OAuth / token 過期類報錯。如果你用的是某些需要 OAuth 的客戶端配置報錯會提示 token invalid。OpenClaw 這套走的是標(biāo)準(zhǔn) Bearer Key不涉及 OAuth 流程。如果看到 OAuth 字樣多半是配置文件里混入了別的客戶端殘留字段把config.json精簡成上面那三件套即可。SQLite 報 database is locked。并發(fā)寫的時候會出現(xiàn)加WAL模式基本能解決。如果還鎖檢查是不是有另一個進程占著lobster.db關(guān)掉再跑。排障的核心思路就一條先看 HTTP 狀態(tài)碼再看響應(yīng)體原文最后看請求 URL 拼得對不對。把這三樣打印出來九成問題能自己定位。6. 繼續(xù)深入把 OpenClaw 接到 Coding Plan 與文檔跑通首個閉環(huán)只是起點。接下來你可以給 Agent 加技能比如在src/tools.js里注冊一個查天氣的工具讓模型通過 function calling 自主調(diào)用。技能多了之后模型調(diào)用量會上來這時候用 Coding Plan 會更劃算適合長期編碼和 Agent 場景入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。如果你更想先摸清接口細(xì)節(jié)再動手接入文檔在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有請求格式和參數(shù)說明。我自己的做法是本地開發(fā)階段用按量 Key 調(diào)試等 Agent 穩(wěn)定跑起來、每天調(diào)用量上去了再切到 Coding Plan。記憶層也可以繼續(xù)優(yōu)化比如把messages表里的遠期對話做摘要壓縮只把摘要喂給模型控制 token 消耗。這些都在你現(xiàn)有骨架上加不用推倒重來。最后留一個實用技巧給runAgent加個超時控制避免模型卡住時整個循環(huán)掛死。const controller new AbortController(); const timer setTimeout(() controller.abort(), 30000); // fetch 里帶上 signal: controller.signal30 秒沒響應(yīng)就中斷Agent 主循環(huán)能繼續(xù)處理下一條。這個細(xì)節(jié)在長時間運行的本地智能體里很值錢早加早省心。