为什么自建 Agent 内核,
而不是复用 Claude Code
FFAI 的内核和 Claude Code 高度同构——TAOR 循环、压缩阈值、重试语义逐常量对齐。既然长得像,为什么不直接用原装的?本页给出完整答案:五条决定性原因、三条次要原因、一张反事实翻盘条件表,以及「复用 Claude Code」的正确姿势。事实源在仓库 docs/modules/agent/references/why-own-kernel-not-claude-code.md(决策 D75)。
00先承认前提:内核确实是「临摹品」
不回避:FFAI 的主循环、auto-compact 阈值公式(window − 20000 − 13000)、重试语言(指数退避 ±25% jitter / 后台请求遇过载直接放弃 / 连续 3 次过载换模型)、记忆注入截断(200 行 / 25KB)、<tool_use_error> 反馈闭环、两轴协作模式,全部是对 Claude Code 的有意识临摹——设计文档逐处标了出处。
所以问题不是「我们能不能写出这个内核」(能,且已在生产运行),而是「既然长得像,为什么不用原装的」。答案的骨架一句话:
像的部分只占系统的 ~15%(主循环本体几千行);不像的部分才是系统的本体——多租户、多厂商、多端、可审计——而那些部分,Claude Code 在形态上给不了。
01五条决定性原因
任何一条单独成立,都足以否决「换内核」。五条同时成立。
工具层强制可经 MCP 达成,但「回合层」治理无法外包
先承认反驳成立的那一半(2026-07-07 修正):如果 MCP 的身份问题解决(per-user OAuth / OBO),org 隔离 + DataScope 完全可以在我们自己的 MCP server 里强制——强制点从来在我们后端代码里,MCP 只是换了传输层,门还是我们的门。我们的架构本就把 MCP 列为工具首选轨(G6 允许 CC/Cursor 调我们的业务工具)。
但搬得走的只有工具层。这些「回合层」治理长在循环里,CC 内核下要么消失、要么退化成面向机主(而非多组织 admin)的旋钮:① 上下文注入策略——个人/org 记忆注入、共享上下文隐私护栏(I-31)的第一层是 prompt 层不注入,MCP server 看不到 prompt;② 工具可见性按会话模式过滤(planMode / permissionMode / org 白名单,I-8/I-18);③ mid-turn 配额复查与软限降档路由;④ turn 级审计完整性——MCP 只审得到「工具被调了」,模型看到了什么、为何调它、本轮成本都在 CC 进程里,只有出入境记录、没有行程,HMAC 链口径就断了。
另外「身份解决」本身有新增成本:per-user token 的获取/刷新/撤销、confused deputy、每工具一跳 HTTP——可解,但都是换内核要额外付的复杂度。
模型锁定 vs 多厂商 + 数据驻留合规
Agent SDK 只跑 Anthropic 模型(API / Bedrock / Vertex)。而 FFAI 代码里有硬性出网合规门 FFAI_LLM_EGRESS_COMPLIANCE_CLEARED、region-aware 路由 CN→qwen——数据驻留是合规约束,不是偏好。ModelRouter(三层 scope 规则 + 轻 turn 降档 + 决策审计落库)还是架构目标 G10 声明的核心差异化。
换 CC 内核 = 5 家 provider、中立 IR、整个路由层作废。社区有把 CC 指向兼容端点的 shim,但那是非官方 hack,prompt cache / beta 特性随版本碎,不能当企业依赖。
多租户治理必须焊死在循环结构里,不能靠插入点
FFAI 的所有工具调用必经 ToolRegistry.invoke 单一收口(不变量 I-21 零绕过):IAM 授权、destructive 确认、幂等去重、出口脱敏(开关 import 时冻结,prompt injection 关不掉)、超限落盘、三档异常分类;外加 HMAC-SHA256 审计哈希链、org/user 双 scope 配额。
Claude Code 给的是 hooks(PreToolUse/PostToolUse 插入点)。插入点是「可以加检查」,收口是「不可能绕过检查」——多租户无人值守场景只有后者成立。CC 的安全模型是「问机主」(权限弹窗 UI 上万行),我们没有机主可问。
进程与部署模型不兼容
CC/SDK 每会话一个子进程(CLI 内核)。FFAI 是 NestJS 多副本常驻服务:几百员工会话跑在事件循环里、跨副本取消走 Redis 广播、SSE 流同进程直出、Teams webhook 后台跑 turn。
换成「每会话 spawn 一个 Node 子进程」意味着进程编排、资源记账、取消传播、SSE 桥接全部重做一层——为了换内核而给自己发明一个新的编排问题。
异步多端交互形态:ask_user 是第一类终态
CC 的交互模型是终端同步会话:AskUserQuestion 阻塞弹窗、循环原地等。FFAI 的 surface 是 Web / Teams / cron——ask_user 和 permission_required 是结束 turn 的第一类终态(事件推给前端 / Teams 卡片,用户回答开启新 turn),cron 跑在无人值守语义下。
这个差异渗透到主循环终止条件的设计里,不是外壳能适配掉的。
02三条次要但真实的原因
闭源 + 不可控演进
CC 闭源、版本节奏由 Anthropic 定;内核级依赖意味着它每次 breaking change 都是我们的 P0。自建内核 + 上游对标,把「被动跟随」变成「主动择优吸收」。
AI 时代自建成本已塌缩
内核核心(主循环 3,483 + 压缩 220 + 协议层 2,232 行)合计不到 6 千行;压缩层 220 行 vs CC 的 4,626 行(21×)证明「临摹最终答案」的成本极低。「自建工程量大」这个传统反对理由,在本项目实测数据里不成立。
许可与商业边界
把闭源终端产品嵌成多用户服务端内核处于授权条款灰色地带;Agent SDK 虽是官方嵌入形态,但授权前提仍是 Anthropic 模型(回到 R2)。
03反事实检验:什么条件下应该用 CC / Agent SDK
诚实列出翻盘条件,防止本文变成永久教条。任一行状态翻转时,应重开评估,而不是引用本文否决。
| 条件 | 若成立 | 现状(2026-07) |
|---|---|---|
| 单租户 / 单用户形态(内部工具 → 个人工具) | SDK 合理 | ❌ 不成立:多组织是 G2 根设定 |
| 只用 Anthropic 模型且无数据驻留约束 | R2 消失 | ❌ 不成立:qwen 合规门写在代码里 |
| 业务能力全部 MCP 化 + 身份 OBO 打通 | R1 的工具层消失(回合层治理仍在,见 R1) | ⚠️ 部分可行但未做:service 轨仍是默认,MCP 轨本就保留 |
| Agent SDK 开放多 provider + 服务端多租户运行时 | 重新评估 | ❌ 无此路线图信号 |
04「复用 Claude Code」的正确姿势
不换内核 ≠ 不用 CC。我们实际在做(和将要做)的三件事:
① 设计临摹
内核每个机制先看 CC 怎么做(阈值 / 重试 / memdir / 两轴 / tool_use_error),有标准答案就抄答案,不重新试错。事实源 references/claude-code-reference.md。
② 上游对标周期化
#1932 模式:CC / Codex / OpenClaw 发版 → 跑 delta 对标 → 逐项吸收。stall watchdog、bounded reader、拒收远端图片 URL 都是这么来的。
③ 沙箱内嵌当编程 worker
E28 per-user 持久容器 + E31 dev runtime 就绪后,编程类重任务由容器内的 CC/Codex CLI 承担(它们为此而生),FFAI 内核负责编排/身份/审计/投递——CC 变成 cli: 轨里的一个超级工具,而不是内核。既要 CC 的编码深度,又不交出平台控制权。
漂移防御(D75):任何「换内核 / 接 CC 引擎」的提案,先过 §03 反事实表;「沙箱内嵌 worker」是增量能力,不改变内核归属,勿混为「换内核」。
05FAQ:「Claude 不是有企业版吗?」
最容易混淆的一层追问。答案:Claude 的企业形态企业化的是「员工用 Claude」这件事;FFAI 要企业化的是「模型操作我们的业务系统」这件事——两个「企业」不在同一个位置。
Claude 的企业形态是两样东西:① Claude Enterprise(claude.ai 企业席位:SSO/SAML、席位与域管理、审计日志、数据不用于训练);② Claude Code 企业管理(managed settings 策略下发、用量/费用管控、Bedrock/Vertex 合规接入)。它们是采购合规层——让 IT 部门敢把 Claude 发给全员。但逐维对照我们的需求,会发现它答的不是同一道题:
| 维度 | Claude 企业版给的 | FFAI 需要的 |
|---|---|---|
| 多租户 | 「你们公司」在 Anthropic 云上的席位空间——隔离的是员工与 Claude 的对话 | 我们业务系统内部的多组织结构:查一张采购单要过 org 隔离 + DataScope 行级过滤。Claude 不知道我们的 org/部门/角色是什么,也永远不该知道 |
| 权限 | 席位级:谁能用、能用多少额度 | 业务动作级:这个员工的 agent 能不能改这张审批单,由我们的权限码决定——即 R1,MCP connector 级凭据表达不了 RBAC+DataScope+事务语义 |
| 审计 | 平台使用审计(谁登录、谁开了会话、admin 操作),落在 Anthropic 的审计域 | 业务操作审计:「谁在何时通过 agent 调了什么工具改了什么单据」,HMAC 链防篡改,落在我们的合规域——审计员查的是我们的账 |
| 模型/驻留 | 只有 Claude;驻留 = Anthropic 云或 Bedrock/Vertex region | CN 场景要 qwen、出网合规门、按任务路由(R2)——企业版再企业,也不会替你接通义千问 |
| 产品形态 | 入口是 claude.ai / 终端 CC,体验由 Anthropic 定义 | agent 是工作台首页、嵌 Teams、跑 cron、Canvas 长在我们前端——体验由我们定义 |
一句话收拢:企业版解决「公司安全地用 Claude」(信任边界在 Anthropic 平台);FFAI 解决「模型安全地操作我们的系统」(信任边界在我们平台)。两者互补不对立——员工通用问答可用 Claude Enterprise 席位,FFAI 内部照样经 API 调 Claude 模型(走我们的路由和审计),沙箱内嵌 worker 还能复用其管控能力。被否决的只是「把 CC 当 FFAI 的内核」,不是「在企业里用 Claude」。
FAQ-2:「工具可见性 MCP 能动态过滤、上下文注入 spawn 时能拼进去啊?」
2026-07-07 的连环追问,逐条认账之后,论证收敛到它的最终形态。
都对:MCP tools/list 是 per-session 动态的(还有 list_changed 通知 + readOnly/destructive 注解);内核由我们 spawn,system prompt / CLAUDE.md / append-system-prompt 都是我们拼的,per-turn 动态注入可走 UserPromptSubmit hook 注 additionalContext——连「共享上下文不注入」都成立。照此推演,任何「X 做不到」的具体清单都会被逐条失守,因为 CC 的旋钮面每个版本都在扩大。所以正确的论证不是阵地战,而是看什么撑到最后:
① 模型路由 / mid-turn 降档(R2)
CC 的循环只跟 Anthropic 说话。「软限触发换便宜模型」「CN 任务路由 qwen」在别人的循环里不存在对应概念。唯一的死刑条款。
② 循环本体的行为
ask_user/permission_required 终态、14 种 StreamEvent SSE 协议、跨副本取消、cron skipHistory、failover 候选链——这些不是「注入什么」,是「循环怎么走」。
③ 审计第一方性
hooks + transcript 摄取只能从 CC 的日志格式二手重建;HMAC 链从「记录产生即入链」退化为「摄取时补链」。
最终论证形态——不是「做不到」,是「负收益」:每一条「能做到」都需要一块胶水(OBO token 生命周期 / MCP server 化 / hooks 桥 / settings 下发 / transcript 摄取 / 每会话子进程编排)。胶水加总,规模大概率 ≥ 被替换的循环本体(约 3,500 行);换来的是黑盒依赖、每次 CC 发版的胶水脆性、以及无解的模型锁定。用 CC 当内核 = 把产品循环行为的上界设为「CC 恰好暴露的旋钮」,每个新需求先问一遍 Anthropic 有没有旋钮。判定应基于此,而非任何一条会随版本失效的「做不到」清单。
06FAQ-3:「Agent 长在业务系统上,会不会高耦合?」
2026-07-07 追问。判定:是好方式——代码耦合实际很低(插件反转),真正的耦合在进程/部署层,那才是要管理的部分。行动项登记于 decisions.md D76。
端口-适配器,低耦合
agent 内核零业务 import;业务模块经 @AgentTool 薄契约(元数据 + zod + AgentContext 6 字段)自注册、bootstrap 反向发现;独立 *.agent-tools.ts 出口 + CI 卡口防边界侵蚀。
深耦合是故意的
agent→平台(IAM/DataScope/org 模型)的耦合就是 R1 护城河;解开它产品退化为「通用 chatbot + connector」。业界同型:Agentforce / Joule / M365 Copilot 全是嵌入式。
唯一实的风险
长 SSE 和 100 轮循环本身 I/O-bound 无害;真实争用面是三个:事件循环同步 CPU 尖刺(大 JSON/脱敏/base64/HMAC)、堆与 GC 停顿(blob/图片/fetch 缓冲)、共享 Prisma 池(每迭代 3-5 笔写)。
治理姿势(D76):单 turn 已充分有界(四层大小上界 + MAX_ITER=100 + 硬超时 + 重执行全外放容器),裸露面 = 并发无上限 + 不可观测。行动排序:① per-user/org 并发 turn cap(Redis 计数 + 429,几十行)→ ② event loop lag / heap / pool wait 三指标接 OTel + 告警 → ③ 进程拆分是有触发条件的演进项(agent 致业务 P99 劣化超阈值 / 部署节奏被阻塞才拆;断面已备好:内核零业务 import + 事件流跨模块写 + service→MCP 出口预留)。在 ①② 数据缺席时提前拆微服务 = 盲飞。
前置心智模型:本机 vs 服务器 · 两种并发容量 · SSE 的账怎么算
本机 vs 服务器 = N=1 vs N=many
CC 无并发设计不是省略而是不需要——资源用户自带(成本外置,一万个 CC 用户 = 一万台用户的电脑出力)。服务器把负载集中到自己机器上,公平性 / 隔离 / 容量规划才成为一等公民。
两种并发容量,只有一种关联核数
CPU 并行 = 核数(Node 单线程 → pm2 每核一进程),对应循环里的同步尖刺;I/O 并发 = 内存 + fd + 事件循环健康,与核数基本无关——一个核挂几万条空闲连接是事件循环模型的本职。agent 负载是混合体:95%+ 墙钟在 await,穿插吃核的尖刺。
Little's law:L = λ × W
SSE 把 W 从毫秒放大到分钟 → 同样用户量,并发连接数放大百千倍——「长连接更耗并发资源」的数学本质。但 socket 本身便宜;贵的是连接背后活跃 turn 的 MB 级堆、连接钉住副本的运维税(drain / 滚动部署 / 断线续传 / 防代理砍连接)、被长期占用的 DB 池与上游流配额。
收束:agent 服务容量规划的单位不是「连接数」也不是「核数」,是「并发活跃 turn 数」——一个活跃 turn ≈ 一条 SSE + 一条上游流 + MB 级堆 + 每轮几笔 DB 写 + 间歇尖刺。核数决定尖刺消化能力,内存决定可挂 turn 数,DB 池决定可同时落库数。D76 行动项 ① cap 的对象正是活跃 turn。
资源瓶颈排序(「所以内存更重要?」的准确版本):① 逻辑资源先撞——DB 连接池、上游厂商并发/速率配额都是几十量级,在物理资源告急前先排队;② 内存是第一个硬耗尽的物理资源,且最大单项不是 Node 堆而是沙箱容器(2g × 暖池 32 ≈ 64g,I-34「持久≠运行」与 I-33 cgroup fail-safe 正为此而立);③ CPU 几乎不构成容量上限(尖刺影响 p99 不影响容量),且内存压力会转化为 CPU 症状(GC 变频变长),heap 与 event loop lag 要一起看。采购扩容优先级:加内存 > 加核;调优优先级:先把逻辑资源可观测化。
07依据与终态声明
- 最佳实践依据:企业内嵌 agent 的头部实现(Microsoft 365 Copilot、Salesforce Agentforce、GitHub Copilot 企业版)无一例外自持 orchestration 层、把厂商模型作为可替换后端——「循环自己拿、模型可路由」是企业 ToB 的行业事实标准。Claude Agent SDK 的官方定位是开发者构建 agent 应用的工具链,不是多租户平台内核;CC 自身的单机、单租户、权限弹窗信任模型也从设计上印证它不面向本场景。
- 终态符合性:自建内核 + 设计临摹 + 上游对标是终态方案而非过渡——它是 R1–R5 五条硬约束的唯一解,不存在「以后条件成熟再换回 CC」的隐含计划。唯一的开放项是 §03 的反事实条件与 §04③ 的沙箱内嵌 worker(后者是增量能力)。