1
0
0
核心包架构深度解析
2026-08-14
2026-08-14

文章摘要
|
# 入门03:核心包架构深度解析
> 如果把 Harness 比作一个 Web 应用,`packages/core/` 就是它的"骨架"——Vue 的响应式系统 + React 的 reconciler + Vue Router 的路由管理,都在这一层。
---
## 1. 六大核心模块是啥?
```mermaid
graph TB
subgraph "核心层(相当于应用的骨架)"
AL[AgentLoop
引擎] AG[Agent
户口本] SE[Session
聊天记录本] SC[Scope
作用域链] TL[Tools
工具台] SP[SystemPrompt
提示组装器] end AL --> AG AL --> SE AL --> TL AL --> SP AG --> SC TL --> SC SE --> SC ``` | 模块 | 用前端话解释 | 相当于 | |------|-------------|--------| | **Agent** | 管理所有 Agent 的"户口本" | 类似 Vuex 里管理所有组件的状态清单 | | **AgentLoop** | Agent 的"引擎",驱动对话循环 | 类似 React 的 reconciler + 事件循环 | | **Session** | 不可修改的聊天记录本 | 类似 Git 的 commit log | | **Scope** | 作用域链,实现能力继承和隔离 | 类似 Vue 的 scoped slots + 组件树 | | **Tools** | 工具的"注册中心" | 类似 Vue 的全局组件注册 | | **SystemPrompt** | 拼装发给 AI 的提示词 | 类似模板引擎渲染 | --- ## 2. Agent 注册表(AgentRegistry)— Agent 的"户口本" > 就像 Vuex 的 store 管理所有组件状态,AgentRegistry 管理所有运行中的 Agent。 **代码位置**:`packages/core/agent/src/index.ts` 它负责三件事: 1. **创建** Agent——就像 `new Vue()` 创建应用实例 2. **查找** Agent——给个 ID 就能找到 3. **追踪** 谁调用了谁——通过 `AsyncLocalStorage` 追踪调用链 ```typescript class AgentRegistry extends Service { // 创建新 Agent async create(options: CreateAgentOptions): Promise
// 从硬盘恢复 Agent(重启后还能继续聊天)
async resume(options: ResumeAgentOptions): Promise
// 按 ID 查找
get(id: SessionId): AgentHandle | undefined
// 谁在调用我?(追踪调用链)
currentInitiator(): AgentHandle | undefined
}
```
**关键概念**:
- **AgentHandle**:Agent 的"遥控器",对外暴露的引用,不直接操作 Agent 内部
- **Initiator**:追踪谁发起了调用——就像 `console.trace()` 打印调用栈
---
## 3. Agent 循环引擎(AgentLoop)— 驱动 Agent 跑起来
> 就像 React 的 render 循环 + 事件循环合体。每次用户发消息,就触发一轮"思考-行动"循环。
**代码位置**:`packages/core/agent-loop/src/index.ts`
```typescript
class AgentLoop extends Service {
// 必须的依赖——就像 Vue 组件声明 props
static inject = ['agents', 'sessions', 'llm', 'tools', 'systemPrompt']
// 从配置创建 Agent
async createAgent(options: CreateAgentOptions): Promise
// 恢复 Agent
async resume(options: ResumeAgentOptions): Promise
}
```
**核心状态**:Agent 只有三种状态——
```
idle(空闲) → running(运行中) → idle(空闲)
↓
maintenance(维护中,配置热更新)
```
---
## 4. Session(事件溯源会话)— 不可修改的聊天记录本
> 就像 Git 一样,每次操作都 commit,不修改历史。AI 看到的对话内容,是从 commit 历史"算"出来的。
**代码位置**:`packages/core/session/src/index.ts`
```typescript
class Session {
// 头部信息(就像 Git commit 的元数据)
readonly header: {
sessionId: SessionId
cwd: string // 当前工作目录
createdAt: Date
forkLine: string // 分叉线
}
// 追加事件(类似 git add + git commit)
append(type: string, data: any, surfaceOpts?: SurfaceOpts): void
// 从事件日志"算"出 LLM 能看到的消息(类似 git log 查看历史)
deriveMessages(): Message[]
}
class SessionStore extends Service {
create(): Session // 创建新会话
fork(session: Session): Session // 分叉(类似 git branch)
}
```
### 事件类型(就像 Git 的 commit message 类型)
| 事件类型 | 对应什么 | 类似 Git 的 |
|---------|---------|------------|
| `user/message` | 用户说了一句话 | 一次 commit |
| `assistant/message` | AI 回了一句话 | 一次 commit |
| `tool/result` | 工具执行完了 | 一次 commit |
| `turn/start` | 一个回合开始 | 一个分支开始 |
| `turn/end` | 一个回合结束 | 分支合并 |
| `step/start` | 一个步骤开始 | 子任务 |
| `step/end` | 一个步骤结束 | 子任务完成 |
### Surface(表面)机制
> 就像数据库的 View(视图)——不是所有字段都暴露给用户,只暴露需要的。
不是所有事件都会传给 AI。只有标记了 `surface: true` 的事件才会"浮出"水面,进入 AI 的上下文。比如 `turn/start` 这种内部事件就不会传给 AI。
---
## 5. 作用域系统(Scope)— 像 React 组件树一样嵌套
> 就像 React 组件可以嵌套,子组件能看到父组件的 props 和 context。Agent 也可以嵌套,子 Agent 继承父 Agent 的能力。
**代码位置**:`packages/core/scope/src/index.ts`
```typescript
// 创建作用域(就像创建子组件)
function createScope(ctx: Context, key: ScopeKey): Context
// 分层注册表(子作用域能看到祖先注册的东西)
class ScopedLayers {
add(key: ScopeKey | undefined, value: T): void
remove(key: ScopeKey | undefined, value: T): void
values(key: ScopeKey): T[] // 获取当前作用域及祖先的所有值
}
```
### 作用域链长啥样?
```
全局(啥都有)
└── Agent A(能执行 bash、读写文件)
├── 子 Agent B(继承 bash 和读写文件,还能搜网页)
└── 子 Agent C(只能读文件,不能写)
```
**这不就是作用域链吗?** 就像 JS 的作用域——子作用域能访问父作用域的变量,但不能反过来。
---
## 6. 工具注册表(ToolRuntime)— 全局组件注册
> 就像 Vue 的 `app.component('my-component', {...})` 注册全局组件,ToolRuntime 注册"工具"让 AI 调用。
**代码位置**:`packages/core/tools/src/index.ts`
```typescript
class ToolRuntime extends Service {
define(name: string, definition: ToolDefinition): void // 注册工具
createExecution(toolName: string, args: any): ToolExecution // 执行工具
restrict(scope: ScopeKey, tools: string[]): void // 限制子 Agent 能用啥
guard(condition: (tool: string) => boolean): void // 设置守卫
}
```
### 工具执行管线
> 就像 Express 中间件——每个阶段都是 Waterfall,插件可以拦截和修改。
```
pre-execute(执行前修改参数) → guard(守卫检查) → execute(实际执行) → post-execute(处理结果) → result(返回)
```
每个阶段都是 Waterfall 事件,插件可以"插一脚":
```typescript
// 在工具执行前记录日志
ctx.waterfall('tools/pre-execute', (execution) => {
console.log(`将要执行: ${execution.name}`)
return execution
})
```
---
## 7. 系统提示组装(SystemPrompt)— 模板引擎
> 就像服务端渲染拼 HTML 模板——收集各部分内容,组装成完整的提示词发给 AI。
**代码位置**:`packages/core/system-prompt/src/index.ts`
```typescript
class SystemPrompt extends Service {
section(section: PromptSection): void // 注册提示节
context(context: ContextProvider): void // 注册动态上下文
tools(provider: ToolsProvider): void // 注册工具 Schema
variable(name: string, provider: VariableProvider): void // 注册模板变量
assemble(context: AssemblyContext): PromptAssembly // 组装
}
```
### 组装过程
```
收集所有 sections → 按顺序排好 → 收集 context → 收集 tools → 变量插值 {{variable}} → Waterfall 最终加工 → 发给 AI
```
---
## 8. 模块间怎么配合?
```mermaid
graph TB
AL[AgentLoop
引擎] --> AG[AgentRegistry
管理Agent] AL --> SE[SessionStore
记录会话] AL --> TL[ToolRuntime
执行工具] AL --> SP[SystemPrompt
组装提示] AL --> LLM[LlmRuntime
调用AI模型] AG --> SC[Scope
作用域链] TL --> SC ``` **各模块的职责划分很清晰**: - **AgentRegistry** 只管"有哪些 Agent",不管怎么运行 - **AgentLoop** 只管"怎么运行 Agent",通过 AgentRegistry 管理 - **SessionStore** 只管"记录事件",不管事件含义 - **ToolRuntime** 只管"工具有哪些、怎么执行",不管谁调用 - **SystemPrompt** 只管"怎么拼提示词",不管谁用 - **Scope** 是粘合剂,提供分层和隔离 **这就像前端框架的分层**:Vue 的响应式系统只管数据变更,模板编译器只管编译,渲染器只管渲染,各司其职。 --- ## 要点总结 - **AgentRegistry** = Agent 的"户口本",管创建、查找、恢复 - **AgentLoop** = 引擎,驱动"思考-行动"循环 - **Session** = 不可修改的聊天记录,像 Git 一样只追加 - **Scope** = 作用域链,组件树一样的嵌套继承 - **Tools** = 工具注册中心,像 Vue 注册全局组件 - **SystemPrompt** = 提示词组装器,像模板引擎 - 六个模块通过 Cordis 依赖注入连接,职责清晰互不干扰 ## 进阶阅读 - 核心源码:`packages/core/` 目录 - 官方文档:`docs/subsystems/core.md` - 名词速查:[附录-AI 概念名词速查手册](附录-AI概念名词速查手册.md) - 下一步:[04-Agent 循环与对话流程](04-Agent循环与对话流程.md)
引擎] AG[Agent
户口本] SE[Session
聊天记录本] SC[Scope
作用域链] TL[Tools
工具台] SP[SystemPrompt
提示组装器] end AL --> AG AL --> SE AL --> TL AL --> SP AG --> SC TL --> SC SE --> SC ``` | 模块 | 用前端话解释 | 相当于 | |------|-------------|--------| | **Agent** | 管理所有 Agent 的"户口本" | 类似 Vuex 里管理所有组件的状态清单 | | **AgentLoop** | Agent 的"引擎",驱动对话循环 | 类似 React 的 reconciler + 事件循环 | | **Session** | 不可修改的聊天记录本 | 类似 Git 的 commit log | | **Scope** | 作用域链,实现能力继承和隔离 | 类似 Vue 的 scoped slots + 组件树 | | **Tools** | 工具的"注册中心" | 类似 Vue 的全局组件注册 | | **SystemPrompt** | 拼装发给 AI 的提示词 | 类似模板引擎渲染 | --- ## 2. Agent 注册表(AgentRegistry)— Agent 的"户口本" > 就像 Vuex 的 store 管理所有组件状态,AgentRegistry 管理所有运行中的 Agent。 **代码位置**:`packages/core/agent/src/index.ts` 它负责三件事: 1. **创建** Agent——就像 `new Vue()` 创建应用实例 2. **查找** Agent——给个 ID 就能找到 3. **追踪** 谁调用了谁——通过 `AsyncLocalStorage` 追踪调用链 ```typescript class AgentRegistry extends Service { // 创建新 Agent async create(options: CreateAgentOptions): Promise
引擎] --> AG[AgentRegistry
管理Agent] AL --> SE[SessionStore
记录会话] AL --> TL[ToolRuntime
执行工具] AL --> SP[SystemPrompt
组装提示] AL --> LLM[LlmRuntime
调用AI模型] AG --> SC[Scope
作用域链] TL --> SC ``` **各模块的职责划分很清晰**: - **AgentRegistry** 只管"有哪些 Agent",不管怎么运行 - **AgentLoop** 只管"怎么运行 Agent",通过 AgentRegistry 管理 - **SessionStore** 只管"记录事件",不管事件含义 - **ToolRuntime** 只管"工具有哪些、怎么执行",不管谁调用 - **SystemPrompt** 只管"怎么拼提示词",不管谁用 - **Scope** 是粘合剂,提供分层和隔离 **这就像前端框架的分层**:Vue 的响应式系统只管数据变更,模板编译器只管编译,渲染器只管渲染,各司其职。 --- ## 要点总结 - **AgentRegistry** = Agent 的"户口本",管创建、查找、恢复 - **AgentLoop** = 引擎,驱动"思考-行动"循环 - **Session** = 不可修改的聊天记录,像 Git 一样只追加 - **Scope** = 作用域链,组件树一样的嵌套继承 - **Tools** = 工具注册中心,像 Vue 注册全局组件 - **SystemPrompt** = 提示词组装器,像模板引擎 - 六个模块通过 Cordis 依赖注入连接,职责清晰互不干扰 ## 进阶阅读 - 核心源码:`packages/core/` 目录 - 官方文档:`docs/subsystems/core.md` - 名词速查:[附录-AI 概念名词速查手册](附录-AI概念名词速查手册.md) - 下一步:[04-Agent 循环与对话流程](04-Agent循环与对话流程.md)