# agent-core-v2：唯一的引擎

> v1 退场、v2 接管的时间线，三层作用域与工作区实例，Service/Fiber 单元层与 Feature 接缝，以及 human 内核的边界。

- 作者：David（道雾轩）
- 专栏：Kimi Code 源码解读（https://daiw.org/manual/kimi-code.md）
- 最后更新：2026-09-19
- 原文：https://daiw.org/manual/kimi-code/agent-core-v2
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

`packages/agent-core-v2`（约 13.6 万行）的包描述没变：

> The unified agent engine for Kimi (**v2 — DI Scope architecture**)

变的是地位。v0.29.1 时本文讲的是「正在进行的 v2 重构」：v1 `agent-core` 仍是 CLI 主路径，v2 只在服务端落地。到 v0.43.0，`packages/agent-core` 目录已经不存在，代码里也搜不到回退开关 `KIMI_CODE_LEGACY_FLAG`——v2 是唯一的引擎，kap-server、acp-server、klient、node-sdk、migration-legacy、remote-control 都建在它上面。

## v1 退场的时间线

CHANGELOG 里能找到的节点：

| 版本 | 变化 |
| --- | --- |
| 0.24.0 | `kimi server run` / `kimi web` 默认跑 v2，v1 服务端包删除（#1617） |
| 0.25.0 | 服务端 v1 wire schema 挪进引擎各域与服务端包，共享 schema 包退出 v2 服务端栈（#1755） |
| 0.33.0 | TUI、`kimi -p`、`kimi acp`、`kimi export`、`kimi provider` 默认跑 v2，`KIMI_CODE_LEGACY_FLAG=1` 可回退（#2627） |
| 0.40.0 | `kimi acp` 不再理会 `KIMI_CODE_LEGACY_FLAG`（#3434） |

`packages/agent-core` 本身在哪个版本删除，CHANGELOG 没有记。按 [monorepo 全景](https://daiw.org/manual/kimi-code/monorepo-map)的口径，v0.29.1 时 v1 约 6.6 万行、v2 已约 9.8 万行。

路线很典型：**新架构先在服务端落地，再切 CLI 默认值并保留回退开关，最后撤掉开关、删掉旧代码**。每一步都可观察、可回退。

## 三层作用域，外加工作区实例

作用域枚举从 `_base/di/scope.ts` 挪到了 `app/scopes.ts`，改成字符串值，并向 DI 内核声明拓扑：

```ts
export enum LifecycleScope {
  App = 'app',
  Session = 'session',
  Agent = 'agent',
}

export const SCOPE_TOPOLOGY: readonly LifecycleScope[] = [
  LifecycleScope.App,
  LifecycleScope.Session,
  LifecycleScope.Agent,
];

setScopeTopology(SCOPE_TOPOLOGY);
```

`_base/di` 只把作用域当字符串（`ScopeKind = string`），`Scope.createChild()` 按声明的拓扑拒绝「子级不高于父级」的建法。服务用 `registerScopedService(scope, id, ctor, activation, domain)` 注册，直接调用的有 App 级 75 处、Session 级 18 处、Agent 级 45 处；`ScopeActivation` 决定作用域一建就实例化还是首次解析时再建，重复注册直接报错，有意替换要用 `overrideScopedService`。

DI 作用域就这三层。工作区那一层在代码里不是作用域，而是 `WorkspaceInstance`（`workspace/workspaceInstance/`）：App 级的 `IWorkspaceInstanceManager` 为每个工作区创建一个实例，它有 `materializing` / `active` / `closing` / `disposed` 四态，持有运行时注册表、单元宿主与 `Program`，后者按工作区装配 `WorkspaceFsService`、`WorkspaceGitService`、`WorkspaceTrustService` 等服务。

以恢复会话为例：App 级 `ISessionManager` 的 `controllerForSession()` 先查 `ISessionIndex` 拿到会话所属工作区，经 `IWorkspaceInstanceManager.getOrCreate()` 物化工作区实例，交给它的 `SessionLifecycleService`，后者用 `createScopedChildHandle(…, LifecycleScope.Session, …)` 建出 Session 作用域；Agent 作用域同理由 `agentLifecycleService.ts` 建出。

需要提醒一句：根 `AGENTS.md` 的项目地图写的是四层 `LifecycleScope`（App / Workspace / Session / Agent），还说调用方组合 `ISessionIndex` → `IWorkspaceLifecycleService.handlerFor` → handler、没有 App 级会话门面。这与 v0.43.0 的代码不符：全仓没有 `LifecycleScope.Workspace`，`IWorkspaceLifecycleService` 只出现在 node-sdk 与 kimi-inspect 的注释里，`ISessionManager` 仍注册在 App 级——文档走在了代码前面，读源码时以代码为准。

## 单元层：Service、Fiber 与贡献点

根 `AGENTS.md` 称之为 L3 单元层。`_base/di/service.ts` 的 `Service` 是抽象基类，同时实现 `Fiber` 接口：一个服务单元可以在运行时 `provide()` 子单元（类、函数或对象形式的 recipe，可声明 `inject` 与 `Config`），单元有 `Pending` / `Activating` / `Active` / `Unloading` / `Failed` 五态。

`collection<T>(name)` 定义**集合贡献点**：多方贡献、统一消费。`ScopeUnits(kind)` 就是其中之一，贡献进来的单元会在对应作用域创建时由 `watchScopeUnits()` 物化。单元的增删改由 `cascadeEngine.ts` 沿依赖图级联（`provide` / `unprovide` / `update`），并记下每次级联拆了谁、重建了谁；循环依赖仍抛 `CyclicDependencyError`。App 级 `IFeatureManager` 暴露 `provideUnit` / `unprovideUnit` / `updateUnit`，单元因此能在运行时热插拔。`src/debug/` 的 ledger、graph、cascade 调试服务，就是 kimi-inspect 里 DI 视图的数据源。

## Feature 接缝

`features/` 是功能挂进引擎的统一入口。`Feature` 继承 `Service`，提供一组声明式的 `contribute*()`：`contributeService`、`contributeAgentService`、`contributeTool`、`contributeCommand`、`contributeConfig`、`contributeSessionModel`、`contributeAgentModel` 等。最短的例子是 `features/btw/btwFeature.ts`：

```ts
export class BtwFeature extends Feature {
  static override readonly name = 'btw';

  constructor() {
    super();
    this.contributeService(LifecycleScope.Session, ISessionBtwService, SessionBtwService);
  }
}

registerFeature(BtwFeature);
```

`contributeService` 内部就是往 `ScopeUnits(scope)` 贡献一个单元。`registerFeature()` 只做登记，App 级的 `FeatureAssemblyService` 启动时把登记过的 recipe 逐个交给 `IFeatureManager.provideUnit()`。目前登记了 17 个：btw、cron、dateChange、debugEvents、externalHooks、fileHistory、goal、notify、plan、reminder、sessionInit、skill、swarm、todo、tokenCounting、tower、usage。

## human 内核与导入边界

`src/human/` 是另一块值得注意的区域。`packages/agent-core-v2/scripts/check-import-boundaries.mjs`（`lint:imports`）这样定位它：

> human is the pure LLM/agent kernel: it never imports llm-adapter or v2 domains

反过来，只有 `llm-adapter`、`agent/loop/machine`、`session/agentLifecycle` 三处能 import human 的实现，其余代码只能用少数「词汇」模块（`llm/message`、`llm/usage` 等）。同一个脚本还宣告「the kosong kernel is deleted」。所以 v2 的 `package.json` 既不声明 `@moonshot-ai/kosong`，也不声明 `@moonshot-ai/kaos`：模型请求层是 `src/human/llm` 与 `src/llm-adapter`，执行与文件 / 进程访问走自己的 `src/os/`（`IHostProcessService` 等，见 [kaos](https://daiw.org/manual/kimi-code/kaos)）。

另外，agent-core-v2、kap-server、transcript 是零注释区（`scripts/check-no-comments.mjs` 随 `pnpm lint` 检查），v0.29.1 时本文引用的文件头注释都已删除。

## 这次接管解决了什么

| v1 的问题 | v2 的解法 |
| --- | --- |
| 服务全是单例，会话 / agent 级状态靠手工传递 | 作用域树，容器管生命周期 |
| 功能散落在引擎各处 | Feature 接缝，`contribute*()` 声明式挂载 |
| `PermissionManager` 一个类多职责 | `permissionGate` / `permissionMode` / `permissionPolicy` / `permissionRules` 四个域 |
| 会话活动状态在多处折算 | `ISessionActivityView` 单一真相 |
| 两代引擎长期并存 | 服务端先行、CLI 跟进、回退开关兜底、最后删除 |

代价也真实：规模是 v0.29.1 时 v1 的两倍多，概念层次（作用域、工作区实例、单元、贡献点、Feature、human 边界）也更多。好在关键边界都有脚本检查，而不是靠口头约定。

下一篇：[kaos 执行环境抽象](https://daiw.org/manual/kimi-code/kaos)。
