怎么读这份源码
AGENTS.md 分层、设计文档与生成清单、无注释区、导入边界、实验开关、TS 设定与几条阅读捷径。
先读 AGENTS.md,不是 README
这个仓库把架构说明写在 AGENTS.md 里——给 AI 编码助手看的指令文件,因为天天被使用,往往是最新的架构文档。根目录的 CLAUDE.md 只有一行 AGENTS.md,指回同一份文件。
分层放置:
AGENTS.md 仓库级:项目地图、硬约束、工作流
apps/kimi-code/AGENTS.md CLI/TUI 的入口链与模块职责
apps/kimi-inspect/AGENTS.md
packages/klient/AGENTS.md 门面 / 契约 / 传输三层规则
packages/minidb/AGENTS.md
packages/pi-tui/AGENTS.md 与上游 pi-mono 的本地差异清单
packages/agent-core-v2/src/human/llm/AGENTS.md 目录级
docs/AGENTS.md规则明确写着往哪写:
Hard rules that affect almost every task: update the root
AGENTS.md. Rules that only affect a specific directory: update the nearest sub-directoryAGENTS.md.
但仓库同时声明代码才是唯一真相:
Treat code, not documentation, as the source of truth.
这句话要当真。v0.43.0 的根 AGENTS.md 说 agent-core-v2 有四级 LifecycleScope,调用方经 IWorkspaceLifecycleService.handlerFor 组合会话生命周期;代码里的枚举只有三级,这个服务在引擎里也找不到,只剩 SDK 的注释还提到它。文档可以当索引,结论要回到代码。
第二读:设计文档与生成的清单
v2 引擎没有模块 README,取而代之的是 packages/agent-core-v2/docs/:
zh/llm.md(及英文版)——human/llm请求库的设计指南,九条设计原则写得很透;src/human/llm/AGENTS.md要求改这个目录前先读它。wire-manifest.d.ts、state-manifest.d.ts、config-manifest.toml——由包内scripts/gen-*-manifest.mts生成,分别列出 wire 记录、App / Workspace / Session / Agent 各层状态与全部配置段。想一眼看全引擎的「数据面」,先翻这三份。
无注释区
agent-core-v2、kap-server、transcript 是 comment-free zones:不许有任何注释,连导出符号的 JSDoc 也不行,只保留必要的 lint 抑制指令。scripts/check-no-comments.mjs 扫这三个包的 src/、test/、scripts/,作为 pnpm lint 的一部分执行。
所以读引擎没有注释可依靠,只能靠类型、命名与测试;命名也因此普遍很长、很具体,比如 llmRequesterMediaStrippedTurnsKey。反倒是 node-sdk 的 sdk-rpc-client-v2.ts 注释极多,逐方法写明与 v1 行为的对齐和差异,是理解换代的好材料。
目录约定
apps/ 可运行的应用(CLI/TUI、VS Code 插件、可视化调试器、检查器)
packages/ 库
plugins/official 官方插件(kimi-datasource、kimi-webbridge)
docs/ 用户文档(中英双语)
scripts/ 构建与检查脚本
.agents/skills/ 仓库自带的 agent skills(write-tui、tdd、gen-changesets…)
.changeset/ 变更集(发版用)packages/agent-core-v2/src/ 内部:
_base/ DI 容器、事件、生命周期、贡献点等底座
human/ 纯内核:agent / turn / tool 状态机、单次 LLM 请求库
llm-adapter/ 引擎侧的 LLM 兼容边界(模型、provider、协议路由)
app/ App 级服务:配置、认证、插件、会话索引、flag……
workspace/ 工作区:目录、git、信任、MCP 配置……
session/ Session 级:元数据、子代理、会话级工具策略……
agent/ Agent 级:loop、上下文、压缩、权限、工具执行、内置工具
features/ 以 Feature 接入的功能:goal、plan、skill、swarm、cron……
tool/ 工具契约与资源访问模型
wire/ wire 记录、日志与版本迁移
persistence/ 存储接口与后端(node-fs / minidb / memory)
os/ 宿主文件系统与进程导入边界
packages/agent-core-v2/scripts/check-import-boundaries.mjs(pnpm --filter @moonshot-ai/agent-core-v2 lint:imports)把分层写成了可执行的规则:
human/不许 import 内核以外的任何东西——它是纯 LLM / agent 内核,不认识llm-adapter与 v2 的各个领域;- v2 代码里只有
llm-adapter/、agent/loop/machine/、session/agentLifecycle/三处能 importhuman的实现,其余只能用一小组「词汇」模块(消息、用量、能力等类型); - 协议基座内部的 format / lower / patterns 只许基座自己和测试 import;
- 不许再 import kosong。
知道这三个适配层,就知道内核与外壳在哪里接缝。
实验开关
未公开的功能一律挂在开关后面,env 驱动、默认关闭:
| 环境变量 | 作用 |
|---|---|
KIMI_CODE_EXPERIMENTAL_<NAME> | 打开单个开关 |
KIMI_CODE_EXPERIMENTAL_FLAG | 打开全部 |
优先级是:单个 env > 配置里的 [experimental] > 总开关 env > 条目的 default;发布某功能就是把 default 翻成 true。v2 没有中央注册表,各领域在 import 时自己调 registerFlagDefinition(app/flag/flagRegistry.ts),用 IFlagService.enabled(id) 判断。例如 features/tower/flag.ts(有删减):
export const towerFlag: FlagDefinitionInput = {
id: TOWER_FLAG_ID,
title: 'Tower mode',
env: TOWER_FLAG_ENV,
default: false,
surface: 'both',
isExposed: (flags) => isTowerFeatureAssembled(flags),
};想知道默认配置下哪些路径根本不会执行,rg registerFlagDefinition 扫一遍即可。
TypeScript 设定
- 根
tsconfig.json开了strict、noUncheckedIndexedAccess、noImplicitOverride、noPropertyAccessFromIndexSignature、verbatimModuleSyntax与experimentalDecorators。最后一个给 DI 用:服务在构造函数参数上用@IAgentLoopService private readonly loop这样的装饰器声明依赖。 - 没有开
exactOptionalPropertyTypes。AGENTS.md 明确可选属性不必再写| undefined(写user?: User即可);传值直接给{ user },不用条件展开。 - 路径别名:
agent-core-v2的package.json里#/*指./src/*.ts、#human/*指./src/human/*.ts;src/human/还有自己的package.json,其中的#/*只指向 human 内部——内核在包里又划了一道包界。 exports用./*暴露深路径,所以常见@moonshot-ai/agent-core-v2/agent/loop/turnOps这样的子路径导入。- 除包的
index.ts外,其余index.ts一律export * from './module'。
几条阅读捷径
想弄清一个功能怎么实现,按这个顺序找:
docs/zh/或docs/en/找该功能的用户文档,拿到准确名词。rg搜那个名词(仓库工作流明确要求用rg)。- 落到
packages/agent-core-v2/src/<层>/<领域>/:先看接口文件(如agent/loop/loop.ts定义IAgentLoopService),再看*Service.ts实现,最后看文件末尾的registerScopedService(...)——它告诉你服务挂在哪一级 Scope、何时激活。
想弄清一次调用的完整链路,从 klient 契约切入:packages/klient/src/contract/ 按 global / session / agent 列出每个线上方法的 zod 输入输出,src/core/facade/ 把它们映射到引擎的服务名与方法(如 agentPromptService.submit)——这就是「前端能让引擎做什么」的清单。反方向(审批、提问)看 SDK 的 src/v2/session-wiring.ts。
想知道某处行为的边界,看测试。v2 的 test/ 与 src/ 同构,比如 test/agent/loop/ 下的 loop.test.ts、turnOps.test.ts、machineTools.test.ts;klient 另有一套对每种传输原样重跑的一致性测试(test/helpers/conformance.ts)。
本专栏的引用约定
- 路径一律相对仓库根:
packages/agent-core-v2/src/agent/loop/loopService.ts。 - 引用行号时以基准 tag
@moonshot-ai/[email protected](commitffa94fa)为准。这个仓库变化很快——从 v0.29.1 到 v0.43.0 只隔七周,引擎就换了代——行号与结构都可能漂移,读时请以当前 HEAD 为准。 - 代码片段会做删减(省略无关分支、错误处理),保留结构;需要精确细节请回原文件。
下一篇:一条消息的生命周期——把所有层串起来走一遍。