这是 @moonshot-ai/agent-core 的深度技术教程。我们将从架构全景出发,逐步深入 Agent 引擎的每一个核心模块——从 Loop 循环、Tool 系统、Plan 规划,到 DI 容器、事件溯源、Hook 机制。每个章节配有架构图和可运行的代码示例。

📦 包名: @moonshot-ai/agent-core📐 架构: TypeScript Monorepo🔄 模式: Event Sourcing + DI📖 共 5 章

第一章:核心概念与架构总览

1.1 什么是 Agent-Core?

@moonshot-ai/agent-core 是 Kimi Code 的统一 Agent 引擎。它不是一个简单的 LLM 封装——它是完整的 Agent 运行时,包含会话管理、工具系统、权限控制、任务规划、上下文压缩、事件溯源、后台任务等全部核心能力。无论是 CLI/TUI 应用(apps/kimi-code)还是 Web UI(apps/kimi-web),它们的 Agent 能力都来自于这个包。

▲ Agent-Core 在整个 Monorepo 中的位置:消费层(CLI/Web)→ SDK → 引擎 → 底层抽象(Kosong/Kaos)

1.2 三大核心抽象

理解 Agent-Core,首先要掌握三个最核心的类:

🏗️ Session

会话编排器。管理多个 Agent 的生命周期、技能注册表、MCP 连接、Hook 引擎、会话元数据持久化。一个 Session 包含一个主 Agent 和若干子 Agent。

🤖 Agent

Agent 编排器。组合了所有功能领域:上下文记忆、工具管理、权限控制、Plan 模式、压缩、后台任务、事件记录。每个 Agent 对应一个独立的对话上下文。

🔄 Loop

无状态的核心循环。协调 LLM 调用和工具执行:发送消息 → 解析响应 → 执行工具 → 将结果反馈给模型 → 重复。是 Agent 引擎的"心跳"。

1.3 核心设计模式

模式 描述 所在位置
依赖注入 (DI) 受 VSCode 启发的轻量 DI 容器,通过 createDecorator + registerSingleton 管理服务 src/di/
事件溯源 所有状态变更触发 AgentRecord 事件追加到 wire.jsonl,重放恢复完整状态 src/agent/records/
策略模式 权限系统使用 12+ 策略类,动态决定工具的批准/拒绝/询问 src/agent/permission/policies/
钩子模式 16 种事件类型,允许外部脚本在关键生命周期点插入自定义逻辑 src/session/hooks/
工厂 + 组合 Agent 不通过继承,而是组合 15+ 功能领域对象 src/agent/index.ts

1.4 关键类型速览

核心类型定义types.ts

// Agent 类型
export type AgentType = 'main' | 'sub' | 'independent';

// 工具来源
export type ToolSource = 'builtin' | 'user' | 'mcp';

// Loop 停止原因
export type LoopStepStopReason =
  'end_turn' | 'max_tokens' | 'tool_use' |
  'filtered' | 'paused' | 'unknown';

// 可执行工具接口
export interface ExecutableTool<Input = unknown> extends Tool {
  resolveExecution(input: Input): ToolExecution | Promise<ToolExecution>;
}

💡 理解要点Agent-Core 的最大特点是组合优于继承。Agent 类不是通过多层继承构建的,而是将 ContextMemory、ToolManager、PermissionManager 等 15+ 个独立模块组合在一起。这使得每个模块可以独立演进和测试。

第二章:Agent 生命周期与会话管理

2.1 Session 的创建与配置

Session 是 Agent 引擎的入口点。它管理 Agent 池、共享资源和全局配置。创建 Session 时,你需要提供 Kaos(I/O 抽象)、RPC 通道和丰富的配置选项:

Session 配置接口src/session/index.ts

export interface SessionOptions {
  readonly kaos: Kaos;                    // 文件 + 进程 I/O 抽象
  readonly config?: KimiConfig;           // 全局配置
  readonly homedir: string;              // Session 持久化目录
  readonly rpc: SDKSessionRPC;           // 到宿主(CLI/Web)的 RPC 通道
  readonly providerManager?: ProviderManager;  // LLM Provider 注册表
  readonly hooks?: readonly HookDef[];       // 钩子定义
  readonly permissionRules?: readonly PermissionRule[];
  readonly skills?: SessionSkillConfig;    // 技能配置
  readonly mcpConfig?: SessionMcpConfig;   // MCP 服务器配置
  readonly additionalDirs?: readonly string[];
}

2.2 Agent 的生命周期

Agent 的生命周期由 Session 管理,主要经历以下阶段:

2.3 ContextMemory:对话历史管理

ContextMemory 是 Agent 的"记忆"。它存储完整的对话历史(消息数组)、追踪 Token 使用量、并负责在 LLM 调用前将历史投影为 Model Context Protocol 格式。

上下文消息类型src/agent/context/types.ts

type ContextMessage = Message & {
  origin?: PromptOrigin;         // 消息来源
  isError?: boolean;
  toolCallDisplays?: Record<string, ToolInputDisplay>;
  note?: string;                 // 仅给模型看的工具说明
};

// PromptOrigin 是一个 discriminated union:
type PromptOrigin =
  | UserPromptOrigin         // 用户直接输入
  | SkillActivationOrigin    // 技能激活
  | InjectionOrigin          // 系统注入(待办列表、工具差异等)
  | CompactionSummaryOrigin  // 上下文压缩摘要
  | BackgroundTaskOrigin     // 后台任务结果
  | CronJobOrigin            // 定时任务触发
  | HookResultOrigin         // 钩子执行结果
  | ...

2.4 上下文压缩(Compaction)

当对话历史过长时,Agent 需要压缩上下文以避免超出模型的上下文窗口。Agent-Core 提供了两种压缩策略

📦 Micro Compaction

轻量级、基于计数器的修剪。当消息数量超过阈值时,自动丢弃最旧的非关键消息。速度快,不需要额外的 LLM 调用。

🧠 Full Compaction

LLM 驱动的完整压缩。调用模型对历史对话进行总结摘要,用摘要替换原始消息。质量高但需要额外的 Token 消耗。

压缩触发条件config/schema.ts

// KimiConfig 中的 LoopControl
interface LoopControl {
  reservedContextSize: number;      // 保留的上下文大小 (tokens)
  compactionTriggerRatio: number;  // 触发压缩的使用率阈值 (如 0.8)
  maxSteps: number;               // 每个 turn 的最大步骤数
  maxRetries: number;             // 每个步骤的最大重试次数
}

📋 第二章小结

Session 是整个引擎的容器,Agent 是具体执行单元。理解它们的生命周期——从创建、配置、运行到关闭——是使用 Agent-Core 的基础。ContextMemory 管理对话历史,Compaction 策略确保在长对话中保持性能。

第三章:Tool 系统与扩展机制

3.1 工具系统的三层架构

Agent-Core 的工具系统分为三个层次:

3.2 内置工具全景

类别 工具 用途
文件操作 Read 读取文件内容(支持图片、PDF)
Write / Edit 写入 / 精确替换文件内容
Glob / Grep 文件名匹配 / 内容正则搜索
Shell Bash 执行终端命令(Git Bash / PowerShell)
Web WebSearch 网页搜索
WebFetch 获取 URL 内容并提取
协作 Agent 创建子 Agent 执行任务
AgentSwarm Swarm 模式下的多 Agent 协作
AskUser 向用户提问
规划 EnterPlanMode 进入计划模式
ExitPlanMode 退出计划模式
后台 TaskList 列出活动后台任务
TaskOutput 获取后台任务输出
TaskStop 停止运行中的后台任务

3.3 ExecutableTool 接口详解

这是工具系统的核心契约。每个工具都实现 ExecutableTool 接口:

ExecutableTool 完整接口src/loop/types.ts

// 可执行工具:继承 Kosong 的 Tool,增加执行解析
export interface ExecutableTool<Input = unknown> extends Tool {
  resolveExecution(input: Input): ToolExecution | Promise<ToolExecution>;
}

// 执行结果为 RunnableToolExecution 或 ErrorResult
type ToolExecution = RunnableToolExecution | ExecutableToolErrorResult;

export interface RunnableToolExecution {
  readonly approvalRule: string;       // 权限匹配规则,如 "Read(/etc/**)"
  readonly display?: ToolInputDisplay;   // UI 渲染信息
  readonly accesses?: ToolAccesses;      // 声明的文件系统访问
  readonly execute: (ctx: ExecutableToolContext) => Promise<ExecutableToolResult>;
}

// 执行上下文
export interface ExecutableToolContext {
  readonly turnId: string;
  readonly toolCallId: string;
  readonly signal: AbortSignal;        // 取消信号
  readonly onUpdate?: (update: ToolUpdate) => void;  // 进度更新回调
}

3.4 权限系统:12+ 策略的决策链

每个工具执行前都会经过权限管道的检查。权限管理器使用策略模式,按优先级依次评估多个策略:

🔑 权限规则格式每条规则包含 decision(allow/deny/ask)、scope(turn-override/session-runtime/project/user)和 pattern(如 "Bash(rm *)""Read(/etc/**)")。规则可持久化到配置文件并在 Session 启动时加载。

📋 第三章小结

工具系统采用"定义 → 执行 → 调度"三层架构。ExecutableTool 接口通过 resolveExecution 将声明式的工具定义转换为可执行的 RunnableToolExecution,权限策略链在调度层保障安全。内置工具覆盖文件、Shell、Web、协作和规划等场景。

第四章:Plan 系统与任务规划

4.1 Plan Mode 的设计理念

Plan Mode 是 Agent-Core 的核心特性之一。它允许 Agent 在执行之前先规划——将复杂任务分解为可审查的步骤序列,获得用户批准后再执行。这显著提高了任务的可靠性和可控性。

4.2 PlanMode 类的实现

PlanMode 类管理计划的完整生命周期:创建、进入、取消、退出、恢复。每一次状态变更都通过 AgentRecords 持久化为事件。

PlanMode 核心 APIsrc/agent/plan/index.ts

export class PlanMode {
  protected _isActive = false;
  protected _planId: null | string = null;

  // 进入计划模式
  async enter(id?, createFile?): Promise<void> {
    this._isActive = true;
    this._planId = id;
    this.agent.records.logRecord({ type: 'plan_mode.enter', id });
    if (createFile) await this.writeEmptyPlanFile(planFilePath);
  }

  // 退出计划模式
  exit(id?): void {
    this.agent.records.logRecord({ type: 'plan_mode.exit', id });
    this._isActive = false;
  }

  // 恢复(从事件重放)
  restoreEnter({ id }): void {
    this._isActive = true;
    this._planId = id;
  }
}

4.3 Swarm Mode:多 Agent 协作

当单个 Agent 无法高效处理复杂任务时,Swarm Mode 允许创建多个子 Agent并行协作。每个子 Agent 拥有独立的上下文和执行环境:

Agent 协作的三种类型src/agent/index.ts

export type AgentType = 'main' | 'sub' | 'independent';

// main:    会话的主 Agent,由 Session.createMain() 创建
// sub:     Swarm 模式下的子 Agent,受主 Agent 调度
// independent: 独立的 Agent,不受 Session 生命周期管理

💡 Plan Mode vs Swarm ModePlan Mode 解决的是"先想再做"问题——任务规划与审查。Swarm Mode 解决的是"分而治之"的问题——将大任务拆分为子 Agent 并行执行。两者可以结合使用:先在 Plan Mode 下制定并行策略,再由 Swarm Mode 分发执行。

第五章:高级主题与最佳实践

5.1 依赖注入(DI)容器

Agent-Core 的服务层使用受 VSCode 启发的轻量 DI 容器。通过 createDecorator 定义服务标识符,registerSingleton 注册实现,ServicesAccessor.get() 获取实例:

DI 容器使用示例src/di/instantiation.ts + src/services/

// 1. 定义服务接口
export const IFileStore = createDecorator<IFileStore>('fileStore');
export interface IFileStore {
  save(key: string, data: Buffer): Promise<string>;
  get(key: string): Promise<Buffer | undefined>;
}

// 2. 实现服务
export class FileStore implements IFileStore {
  async save(key, data) { ... }
  async get(key) { ... }
}

// 3. 注册为单例
registerSingleton(IFileStore, FileStore);

// 4. 在类中通过装饰器注入
export class McpConnectionManager {
  constructor(
    private readonly kaos: Kaos,
    @IFileStore private readonly fileStore: IFileStore,
  ) {}
}

整个服务层定义了 20+ 服务接口,覆盖文件系统、会话、消息、工具、MCP、技能、任务、终端等所有核心领域。每个服务都可以被替换(如测试时用 Mock 实现),实现了高度的可测试性。

5.2 事件溯源(Event Sourcing)

Agent-Core 使用事件溯源模式来持久化 Agent 状态。每一个状态变更——从用户输入、工具执行到 Plan 模式切换——都作为一个 AgentRecord 事件追加到 wire.jsonl 文件中。恢复时通过重放所有事件来重建完整状态。

AgentRecord 事件类型(部分)src/agent/records/types.ts

export interface AgentRecordEvents {
  metadata: { protocol_version: string; created_at: number };

  // 对话控制
  'turn.prompt':  { input: ContentPart[]; origin: PromptOrigin };
  'turn.cancel':  { turnId?: number };

  // 配置 & 权限
  'config.update': AgentConfigUpdateData;
  'permission.set_mode': { mode: PermissionMode };

  // Plan & Swarm 状态
  'plan_mode.enter': { id: string };
  'plan_mode.exit':  { id?: string };
  'swarm_mode.enter': { trigger: SwarmModeTrigger };

  // 上下���操作
  'context.append_message': { message: ContextMessage };
  'context.apply_compaction': CompactionResult;

  // 可观测事件(不参与状态恢复)
  'llm.request': LlmRequestRecord;
  'llm.tools_snapshot': LlmRequestToolSchema[];
}

5.3 Hook 系统

Hook 系统允许在 16 种生命周期事件中插入自定义逻辑。钩子以 Shell 命令的形式定义,支持阻塞和非阻塞两种模式:

事件类型 触发时机 模式
SessionStart / SessionEnd 会话开始/结束 非阻塞通知
UserPromptSubmit 用户提交 Prompt 可阻塞,允许修改输入
PreToolUse / PostToolUse 工具执行前/后 可阻塞,可阻止或修改结果
PermissionRequest / PermissionResult 权限请求/结果 非阻塞通知
PreCompact / PostCompact 上下文压缩前/后 可阻塞
SubagentStart / SubagentStop 子 Agent 启动/停止 非阻塞通知
Stop / StopFailure Agent 停止/停止失败 非阻塞通知
Notification 通用通知 非阻塞通知

5.4 配置系统全景

KimiConfig 是全局配置的单一真相来源,支持逐层解析:环境变量 > 配置文件 > 默认值。核心配置由 Zod Schema 严格验证:

配置分层解析src/config/resolve.ts

// 配置解析层次:
//   1. 环境变量覆盖 (KIMI_* 前缀)
//   2. config.toml 文件
//   3. 内置默认值

const KimiConfigSchema = z.object({
  providers: z.record(ProviderConfig),    // LLM Provider 配置
  defaultProvider: z.string(),
  defaultModel: z.string(),
  models: z.record(ModelAlias),        // 模型别名映射
  permission: PermissionConfig,          // 权限规则
  hooks: HookDef[],                      // 钩子定义
  loopControl: LoopControl,              // 循环参数
  background: BackgroundConfig,          // 后台任务限制
  mcp: McpConfig,                       // MCP 超时配置
  experimental: z.record(z.boolean()),   // 实验性功能
});

5.5 最佳实践总结

🏆 生产级最佳实践

  1. 使用事件溯源做审计:wire.jsonl 记录了 Agent 的每一个决策,可用于调试和合规审计
  2. 利用 DI 做可测试设计:将外部依赖(文件系统、LLM Provider、网络)抽象为服务接口,用 Mock 实现进行单元测试
  3. 善用 Hook 做企业集成:PreToolUse/PostToolUse 钩子可对接企业内部审计系统、日志平台
  4. 配置分层管理:敏感信息用环境变量,团队共享配置用 config.toml,默认值保持最小化
  5. 权限最小化原则:默认 DenyAll,逐步添加 Allow 规则,避免 Yolo 模式在生产环境使用
  6. 关注 Compaction 策略:长对话场景务必配置 compactionTriggerRatio,避免上下文溢出

更多推荐