
1. 为什么我要在 Node.js 里自己搭一个 Agent 运行时NanoClaw 是一个用 TypeScript 写的轻量级 AI Agent 运行环境核心卖点是把 Agent 关进容器里跑代码量只有四千行出头单 Node.js 进程没有微服务也没有消息队列。它适合谁适合那些想自己掌控 Agent 执行边界、又不想啃几十万行框架源码的开发者。我最初关注它是因为手上有个定时抓数据、整理成日报的小需求用现成平台总觉得数据流向不透明用重型框架又觉得杀鸡用牛刀。Node.js 生态里做 Agent 的方案不少但大多数要么把工具调用、记忆、渠道抽象做成一大坨依赖要么安全模型停留在应用层白名单。NanoClaw 的思路不一样它把「Agent 能碰到什么」交给操作系统级别的容器隔离来回答。Agent 进程只能看到你显式挂载进去的目录执行 Bash 也翻不出沙箱。这个边界感是我决定动手试它的直接原因。这篇文章我会按真实落地路径走一遍先讲清楚它的工程结构长什么样再给出可复制的项目初始化配置然后是容器隔离参数怎么设最后跑一次本地验证并把模型调用通道通过 TaoToken 统一接进来。全程命令和配置都能直接抄踩过的坑我也会标出来。你不需要先成为容器专家只要机器上有 Node.js 和 Docker 就能跟着做。需要先说明一点NanoClaw 主张「代码即配置」很多定制是改源码而不是写配置文件。所以下面的步骤里配置文件的部分我会给全源码改动的部分我会指出改哪个文件、改哪几行方便你对照。2. NanoClaw 工程结构与 TaoToken 接入前置准备先把项目骨架看清楚后面配置才不会迷路。NanoClaw 的源码大约 12 个 TypeScript 文件单进程启动入口通常是一个主文件负责拉起 Agent 循环其余文件按职责拆成工具调用、会话管理、容器编排、渠道适配几块。它没有微服务没有消息队列也没有复杂的抽象层所以你读代码的路径是线性的从入口进去顺着 import 就能把整条链路走完。容器隔离层是它和普通 Node 脚本的分界线。Agent 产生的每一次工具执行理论上都发生在挂载好的沙箱目录里而不是你的宿主机根目录。Linux 上用 DockermacOS 上可以用 Apple Container 或 Docker。挂载是显式的你没挂进去的路径Agent 看不见。在接模型之前先把模型调用通道定下来。我这边统一用 TaoToken 做 Key 和 API 通道好处是后面不管换哪个模型Base URL 和鉴权方式不用来回改。你需要准备三样东西Base URL、API Key、Model ID。Base URL 用https://taotoken.net/apiAPI Key 到控制台创建Model ID 按你实际要调的模型填。这三件套在后面的配置里会反复出现建议先记在便签上。创建 Key 的入口在控制台文档在接入文档页两处地址分别是控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite如果你只是想先验证模型通不通可以先用模型对话页发一条消息试试模型对话https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite长期跑编码类或 Agent 类任务再考虑 Coding PlanCoding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite这里有个前置检查别跳过确认 Node.js 版本满足项目要求确认 Docker 能正常docker run hello-world。容器跑不起来后面所有隔离配置都是空谈。我建议先把这两条命令跑通再往下走能省掉一半的排障时间。3. 可复制的项目初始化与容器隔离配置这一节是全文最需要你动手的部分。我按「拉代码 → 装依赖 → 写配置 → 设隔离参数」的顺序给每一步都给完整命令或完整片段。先初始化项目并安装依赖。假设你把项目放在~/work/nanoclawmkdir -p ~/work/nanoclaw cd ~/work/nanoclaw git clone 你的 NanoClaw 仓库地址 . npm install依赖装完后先别急着启动。NanoClaw 的模型调用需要指向 TaoToken 的 API 通道我把它写进一个.env文件路径放在项目根目录和源码同级# ~/work/nanoclaw/.env TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-你的Key TAOTOKEN_MODEL_ID你的模型ID注意 Base URL 结尾不要多加/v1之类的后缀按文档给的写。Key 不要提交到 git把.env加进.gitignore。接下来是容器隔离参数。NanoClaw 的沙箱挂载是显式的我建议单独建一个工作目录只把这个目录挂进容器宿主机其他路径一律不挂。下面是一份可复制的容器启动配置我以 JSON 形式给出方便你对照字段{ container: { image: node:20-slim, workdir: /sandbox, mounts: [ { source: /home/你的用户名/work/nanoclaw/sandbox, target: /sandbox, mode: rw } ], env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: sk-你的Key, TAOTOKEN_MODEL_ID: 你的模型ID }, network: bridge, readOnlyRoot: true, capDrop: [ALL], memoryLimit: 512m, cpuLimit: 1.0 } }几个字段值得解释。mounts里 source 是你宿主机的沙箱目录target 是容器内路径mode 用rw让 Agent 能读写但范围仅限这个目录。readOnlyRoot设 true容器根文件系统只读Agent 想往系统目录写东西会失败这是隔离的关键一层。capDrop丢掉所有 Linux capabilities减少提权面。memoryLimit和cpuLimit防止 Agent 跑飞把宿主机拖垮。如果你在 macOS 上用 Apple Container字段名会有差异但语义一致显式挂载、只读根、限制资源。把上面这份配置落到项目里对应的容器编排文件路径按你项目实际结构来通常是源码里负责拉起容器的那一个文件。配置写完先做一次语法自检node --check src/index.ts 2/dev/null || npx tsc --noEmittsc --noEmit能过说明类型层面没有明显问题。这一步别省TypeScript 项目里配置字段拼错往往要到运行时才炸。4. 本地验证请求与成功结果确认配置就位后跑一次最小验证。目标很简单让 Agent 在沙箱里执行一个命令并确认它只能看到挂载目录。先启动服务cd ~/work/nanoclaw npm run start如果项目没有start脚本直接跑入口npx ts-node src/index.ts启动后给 Agent 发一条测试指令让它列出当前工作目录内容请执行 ls -la并告诉我当前工作目录是什么预期结果是它返回/sandbox下的文件列表而不是你宿主机的家目录。这一步能同时验证两件事模型调用通道通了容器隔离生效了。再补一条边界测试让它尝试访问宿主机路径请读取 /etc/passwd 的内容在正确配置下这个请求应该失败或者返回容器内/etc/passwd而不是宿主机的。如果它读到了宿主机的敏感文件说明挂载或只读根配置没生效回去检查mounts和readOnlyRoot。模型调用是否走通可以看服务日志里有没有正常的响应返回。如果日志里出现请求发出但迟迟没有响应先确认.env里的 Base URL 和 Key 是否正确加载。我习惯在启动时打印一行配置摘要不打印 Key 本身确认环境变量读进来了。验证通过后你可以把这条测试指令固化成一个定时任务让 Agent 每天早上跑一次输出到沙箱目录里的日志文件。这就是 NanoClaw 定时任务能力的实际用法配置方式和普通 cron 类似只是执行体在容器里。5. 本篇常见报错排查对照这一节按真实会撞到的报错来写每条给现象、原因、处理。401 Unauthorized。现象是模型请求被拒。原因通常是 Key 没加载或写错。检查.env是否在项目根目录、变量名是否和源码里读取的键名一致。如果你用的是TAOTOKEN_API_KEY源码里读的也必须是这个键。另外确认 Key 没有多余空格复制时容易带上换行。local proxy failed / connection refused。现象是请求发不出去。原因多半是 Base URL 写错或者容器网络模式不对。确认TAOTOKEN_BASE_URL是https://taotoken.net/api容器network用bridge能出网。如果你在容器里访问宿主机上的服务那才需要特殊网络配置但调 TaoToken 是走公网bridge 就够。reading choices 相关报错。现象是解析响应时字段对不上。这通常是 Model ID 填错或者请求体格式和接口不匹配。确认TAOTOKEN_MODEL_ID是你账号下可用的模型别填一个不存在的名字。响应结构对不上时先用模型对话页发一条同样的请求对比返回结构。OAuth 相关报错。如果你在配置里混用了 OAuth 流程和 API Key 鉴权会出现鉴权方式冲突。NanoClaw 接 TaoToken 走的是 API Key不需要 OAuth。把配置里多余的 OAuth 字段去掉只保留 Base URL、Key、Model ID 三件套。容器启动失败 / mount 报错。现象是服务起不来日志提示挂载路径不存在。原因是 source 路径写错或目录没建。先手动mkdir -p建好沙箱目录再确认路径拼写。macOS 上路径大小写敏感别写错。权限被拒 / read-only file system。现象是 Agent 写文件失败。这是readOnlyRoot生效的正常表现说明隔离在工作。如果它需要写文件写到挂载的/sandbox目录里那个目录是可写的。排障时如果拿不准先去接入文档核对参数格式接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteKey 相关的问题去控制台看用量和状态控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite6. 把 NanoClaw 用起来的下一步跑通最小验证之后我建议你先别急着加功能而是把沙箱目录的结构定下来。我的做法是在sandbox下分三个子目录inbox放输入数据work放 Agent 的中间产物out放最终结果。这样即使 Agent 行为异常污染范围也可控清理时直接删work就行。模型通道这边如果你后面要换模型只改.env里的TAOTOKEN_MODEL_IDBase URL 和 Key 不用动。这是统一通道最实际的价值。需要新建 Key 或管理多个项目的 Key去 API Keys 页面API Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite如果你打算把 NanoClaw 接到编码类任务上比如让它读仓库、改文件、跑测试那 Coding Plan 会更合适额度和调用方式按长期编码场景设计Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite最后提醒一个容易忽略的点NanoClaw 的「代码即配置」意味着你 fork 之后升级上游代码会比较麻烦。我的习惯是把自定义逻辑尽量收敛到少数几个文件并在文件头注释里写清楚改了什么这样下次合并上游时冲突范围小。容器隔离参数和模型通道配置尽量走环境变量不要硬编码进源码换机器时只改.env就能跑起来。