ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Claude Code 源码泄露后:12 层 Harness 究竟在赌什么——从 Bash AST 到 Agent 权限的 TypeScript 拆解

2026/10/4 20:03:07 拓冰建站 浏览量
Claude Code 源码泄露后:12 层 Harness 究竟在赌什么——从 Bash AST 到 Agent 权限的 TypeScript 拆解 1. 从 Bash AST 到 Agent 权限12 层 Harness 到底在防什么Claude Code 的 12 层 Harness本质上是一套围绕「语言模型输出不可信」这个前提搭建的执行保障体系。它要解决的问题不是模型能不能写出正确代码而是模型写出的东西在真实终端里执行时会不会把项目搞崩、把密钥泄露、把 CI 流水线炸掉。适合谁看如果你正在做 Agent 运行时、工具调用框架或者单纯想把 Claude Code 接到自己的工程流程里这套分层思路值得逐层拆。我最初也以为这类工具的核心竞争力在模型侧直到把 npm 包里 sourcemap 还原出的 TypeScript 逐段读完才发现真正下功夫的地方在「执行层」。生成从来不是瓶颈执行可靠性才是。12 层 Harness 里前三层管基础对话稳定性四到六层管工具调用的安全解析七到九层管长期信任与上下文压缩十到十二层管自主行动与多 Agent 协调。大多数竞品停在第六层就收工了因为再往上每一层的维护成本都指数级上升。这篇文章聚焦其中最能体现工程判断的两块Bash AST 解析器和 Agent 权限边界。前者把「这条命令安不安全」从正则猜测变成可审计的语法树决策后者决定了 Agent 在无人值守时能走多远。我会给出可复制的 Harness 分层配置片段以及本地验证 Bash AST 拦截效果的测试命令让你在自己的环境里跑一遍亲眼看到拦截发生在哪一层。先明确一个概念Harness 不是模型的一部分它是包裹在模型外面的运行时。模型每次返回 tool_callHarness 负责解析、分类、拦截、执行、回传结果。12 层不是随便分的每一层对应一种生产环境里真实出现过的失败模式。理解这个对应关系比记住层数重要得多。2. TaoToken 前置把 Claude Code 的模型出口接稳在拆 Harness 之前得先让 Claude Code 能稳定拿到模型响应。Harness 的很多层——重试、流式、错误兜底——只有在模型出口稳定的前提下才有意义。如果你用官方直连网络抖动会让第三层的错误兜底频繁触发干扰你对 Harness 行为的判断。我实测下来把模型出口换成兼容 Anthropic 协议的网关能让重试层的行为更可预测方便观察。TaoToken 提供的就是这样一个出口。它的 API 地址是 https://taotoken.net/api兼容 Anthropic 的 messages 接口格式Claude Code 这类工具可以直接把 Base URL 指过去。官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 文档和 Key 管理都在控制台里。你需要准备三样东西缺一不可Base URL、API Key、Model ID。这三件套在后面的配置片段里会反复出现尤其是 Claude Code、Cline、Codex 这类工具配置项名字不同但本质一样。拿 Key 的路径进控制台找到 API Keys 页面新建一个 Key。建议按项目分 Key方便后面排查是哪个环境出的问题。模型对话入口可以用来先验证 Key 是否可用不用一上来就配 Claude Code。文档页有各工具的接入示例遇到字段对不上时优先查文档。这里要提醒一句Harness 的权限层和模型出口是两回事。模型出口决定「能不能拿到响应」Harness 决定「拿到响应后敢不敢执行」。很多人把 401 当成权限问题其实是 Key 或 Base URL 配错了这两类错误要分开排查。3. 可复制配置Harness 分层与 Claude Code 接入片段这一节给两份东西一份是 Harness 的分层配置思路用 JSON 表达每层的开关和阈值一份是 Claude Code 接入 TaoToken 的实际配置。两份都可以直接复制改。先看 Harness 分层配置。这不是 Claude Code 官方格式而是我按 12 层逻辑抽象出来的可读结构方便你在自己的 Agent 框架里对照实现{ harness: { layer1_streaming: { enabled: true, chunkTimeoutMs: 30000 }, layer2_retry: { enabled: true, maxRetries: 3, backoff: exponential }, layer3_fallback: { enabled: true, onError: yield_and_continue }, layer4_context: { enabled: true, maxTokens: 180000 }, layer5_toolRegistry: { enabled: true, allowlist: [Bash, Read, Edit, Write] }, layer6_bashAST: { enabled: true, parser: typescript-bash-ast, onParseFail: deny, inspect: [executable, flags, pipes, redirects] }, layer7_sandbox: { enabled: true, mode: workspace-only }, layer8_permission: { enabled: true, classify: allow|deny|ask, dynamicClassifier: claude-side }, layer9_compact: { enabled: true, tiers: [auto, snip, context] }, layer10_memory: { enabled: true, scope: cross-session }, layer11_autonomy: { enabled: false, daemon: KAIROS-like }, layer12_coordinator: { enabled: false, scratchpad: ./.agent-scratch } } }关键在 layer6 和 layer8。layer6 的onParseFail: deny是安全默认值——解析不出来就拒绝而不是放行。layer8 的dynamicClassifier指向模型侧分类意味着权限判断不是纯静态规则而是结合上下文动态决定 allow/deny/ask。再看 Claude Code 接入 TaoToken 的配置。Claude Code 读取环境变量或 settings 文件把 Base URL 和 Key 指过去{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的Key, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }如果你用 Cline 或 Codex字段名会变但三件套不变。Cline 的 MCP 配置里Base URL 填 https://taotoken.net/apiKey 填控制台生成的Model ID 按文档里的可用列表选。Codex 的 auth.json 里对应base_url、api_key、model三个字段。三件套缺一个就会报 401 或 model not found。配置完先别急着跑复杂任务。用一条最简单的命令验证出口通不通再去看 Harness 的拦截行为。顺序反了你会把网络问题和权限问题混在一起排查。4. 验证请求本地跑一遍 Bash AST 拦截配置好之后最直接的验证方式是构造几条命令看 Harness 的 layer6 和 layer8 分别怎么反应。下面这套测试命令可以在本地跑观察拦截发生在解析阶段还是权限分类阶段。先验证模型出口。用 curl 直接打 messages 接口curl -s https://taotoken.net/api/v1/messages \ -H x-api-key: sk-你的Key \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: claude-sonnet-4-20250514, max_tokens: 64, messages: [{role: user, content: reply with ok}] }返回里有content数组且 stop_reason 正常说明出口通了。如果返回 401检查 Key如果返回 model 相关错误检查 Model ID。出口通了之后测 Bash AST 拦截。构造三类命令安全命令、需要 ask 的命令、必须 deny 的命令。在 Claude Code 里让模型执行观察 Harness 的反应# 安全只读应 allow ls -la ./src # 需要确认写操作应 ask rm -rf ./dist # 必须拒绝解析出危险重定向应 deny cat /etc/passwd ./leak.txtBash AST 解析器会把每条命令拆成 executable、flags、pipes、redirects 四部分。ls -la解析出 executablels无重定向allow。rm -rf ./dist解析出 executablermflags 含 -rf触发 ask。cat /etc/passwd ./leak.txt解析出重定向目标在 workspace 外deny。你可以在自己的 Harness 实现里加一行日志打印解析结果const ast parseBashAST(command); console.log(JSON.stringify({ executable: ast.executable, flags: ast.flags, redirects: ast.redirects, decision: classifyPermission(ast) }, null, 2));跑一遍这三条命令你会看到 decision 字段分别是 allow、ask、deny。这就是从「猜」到「懂」的差别正则只能匹配关键词AST 能理解结构。rm -rf出现在字符串里和出现在可执行位置风险完全不同AST 分得清。验证通过后把 layer6 的onParseFail保持 denylayer8 的 dynamicClassifier 打开。这两条是 Harness 安全性的底线别为了省事关掉。5. 常见报错排查401、local proxy failed、reading choices、OAuth配 Harness 和模型出口时几类报错反复出现。逐个说清楚原因和对策。401 Unauthorized。九成是 Key 或 Base URL 的问题。先确认ANTHROPIC_BASE_URL是 https://taotoken.net/api注意结尾不要多加/v1Claude Code 会自己拼路径。再确认 Key 没有多余空格控制台里重新复制一次。如果 Key 是对的还报 401检查是不是用了别的环境的 Key。local proxy failed。这个报错通常出现在你本地起了代理层但代理没起来或端口冲突。Harness 的 layer2 重试会连续触发日志里刷一片。先确认本地代理进程在跑端口没被占。如果你没主动起代理检查环境变量里有没有残留的 proxy 配置清掉再试。reading choices 相关报错。这类错误一般出现在响应体解析阶段模型返回的 JSON 结构和你预期的不一致。常见原因是 Model ID 写错网关返回了错误结构Harness 的 layer3 兜底没接住。核对 Model ID 是否在文档的可用列表里别用猜测的名字。OAuth 报错。Claude Code 某些版本会走 OAuth 流程如果你用 API Key 接入需要在配置里显式关闭 OAuth 或指定 auth 方式。检查 settings 里有没有冲突的 auth 字段只保留 API Key 一种方式。混用两种认证会互相覆盖。排查顺序建议先 curl 验证出口再验证 Key再看 Harness 日志。把模型出口问题和权限问题分开能省一半时间。Harness 的 layer3 错误兜底会把底层错误包装一层看日志时往下翻找原始错误码。6. 把 Harness 接进你的工程流程拆完 12 层最实际的收获不是记住层数而是知道每一层对应哪种失败模式以及哪些层可以先用最小实现顶上。如果你现在就要把 Claude Code 接进项目建议的顺序是先用 TaoToken 把模型出口配稳拿到 API Key 和 Model ID再打开 layer6 的 Bash AST 拦截onParseFail设 deny然后开 layer8 的动态权限分类allow/deny/ask 三态跑通最后再考虑 layer9 的上下文压缩和 layer10 的跨会话记忆。layer11 和 layer12 的自主能力等前三块稳定了再碰。Bash AST 那块如果你不想自己实现 2679 行解析器可以先从 executable redirects 两个字段做起覆盖大部分危险场景。权限分类先用静态规则等日志攒够了再上动态分类。Harness 的价值在于可审计每一步决策都能追到具体哪一层、哪条规则这比一次性堆满 12 层更重要。模型出口这边API Keys 在控制台管理接入文档有各工具的字段对照。验证模型是否可用走模型对话入口长期跑编码任务和 Agent 工作流可以看 Coding Plan。把出口和 Harness 分开维护出问题时定位会快很多。