# 第一章：Agent 运行时概述 -- 从"单次调用"到"自动循环"

> 对应源文件：`packages/agent/src/`

## 回顾上一阶段

在第一阶段，我们学了 `packages/ai`。它解决的问题是：**如何向各种 LLM 发请求、收响应**。

但 `ai` 包只管"一来一回"。你调用 `stream(model, context)` 得到一个 `AssistantMessage`，如果 AI 想调用工具，`ai` 包不会帮你执行工具，也不会自动把工具结果喂回给 AI。你得自己写这个循环。

## Agent 包解决的问题

`agent` 包在 `ai` 之上构建了**完整的自动循环**：

> 用户说一句话 → AI 回复（可能包含工具调用）→ 自动执行工具 → 把结果喂回 AI → AI 继续回复 → 直到 AI 说"我说完了" → 结束

这个循环叫做 **tool-call loop（工具调用循环）**，是所有 AI Agent 的核心机制。

```
没有 agent 包时：

你的代码手动循环：
  1. stream(model, context)
  2. 如果 stopReason === "toolUse"
     → 手动找到工具
     → 手动验证参数
     → 手动执行工具
     → 手动把结果放回 messages
     → 回到 1
  3. 如果 stopReason === "stop"
     → 结束

有了 agent 包后：

  agent.prompt("帮我读取 main.ts")
  → 自动完成上面所有步骤
  → 通过事件通知你每一步发生了什么
```

## 这个包有多小

`agent` 包只有 **5 个文件**：

```
packages/agent/src/
├── types.ts          # 类型定义（366 行）
├── agent-loop.ts     # 核心循环逻辑（684 行）
├── agent.ts          # Agent 类封装（544 行）
├── proxy.ts          # 浏览器代理流式传输（368 行）
└── index.ts          # 导出（3 行）
```

总共不到 2000 行代码。但它的设计非常精巧，值得仔细理解。

## 两层架构

agent 包有两层 API：

| 层次 | 代码位置 | 说明 |
|------|----------|------|
| **底层** | `agent-loop.ts` | 纯函数，无状态。接收上下文和配置，运行循环，通过事件回调通知调用者 |
| **高层** | `agent.ts` (`Agent` 类) | 有状态的封装。管理消息历史、事件订阅、abort 控制、消息队列 |

底层像一个"引擎"，高层像一辆"汽车"。你可以直接用引擎（底层 API），但大多数时候用汽车（`Agent` 类）更方便。

## 核心设计理念

### 1. 消息双层转换

agent 包引入了 `AgentMessage` 类型，它是 LLM `Message` 的**超集**：

```
Message（LLM 能理解的消息）
  ├── UserMessage        // 用户消息
  ├── AssistantMessage   // AI 回复
  └── ToolResultMessage  // 工具结果

AgentMessage（应用层消息 = Message + 自定义类型）
  ├── UserMessage
  ├── AssistantMessage
  ├── ToolResultMessage
  └── 你的自定义消息类型    ← 新增！
      ├── 通知消息
      ├── UI 状态消息
      ├── 上下文压缩摘要
      └── ...
```

为什么需要这个？因为你的应用可能有 LLM 不认识的消息类型。比如 pi 有"bash 执行记录"、"分支摘要"等自定义消息。这些消息在 UI 中显示，但发给 LLM 前需要转换成它能理解的格式。

### 2. 不拥有 stream 函数

agent 包不直接 `import` 某个特定的 LLM 调用函数。你通过配置传入一个 `streamFn`，告诉它"用这个函数调用 LLM"。默认使用 `ai` 包的 `streamSimple`，但你可以替换为代理函数、mock 函数等。

### 3. 事件驱动

循环过程中的每一步都会发出事件。你的 UI 代码通过监听这些事件来更新界面，而不是轮询状态。

## 下一步

下一章我们会拆解核心类型系统 -- `AgentMessage`、`AgentTool`、`AgentEvent` 等。
