---
tags: []
create time: 2026-04-29 15:30
---

# 第九章：Skill（Console）

## 概述

本章在上一章（RAG + Interrupt/Resume + Checkpoint）的基础上，引入 **Skill** 中间件。通过 Skill 机制，Agent 可以发现并加载一组可复用的"技能文档"（`SKILL.md`），并在需要时自动调用它们——让 Agent 获得结构化的领域知识，而不需要把所有知识写进系统提示词里。

> [!TIP] 核心目标
> 学会用 Skill 中间件把一个稳定的知识集合注入到 Agent 中，并理解 Skill 与 Tool 的区别、注册方式、以及验证方法。

---

## 前置条件

- 与第一章一致：需要配置一个可用的 ChatModel（OpenAI 或 Ark）
- 准备好 `eino-ext` PR 提供的 skills 资源：`eino-guide` / `eino-component` / `eino-compose` / `eino-agent`

> [!QUESTION] 为什么是这四个 skill？
>
> ChatWithEino 的定位是「帮用户学习 Eino 框架、并尝试用 AI 辅助写 Eino 代码」。这四个 skill 恰好覆盖了关键知识点：
>
> - **`eino-guide`** — 学习入口与导航（从哪里开始、怎么快速跑起来）
> - **`eino-component`** — Component 接口与各类实现参考（Model / Embedding / Retriever / Tool / Callback 等）
> - **`eino-compose`** — 编排与确定性工作流参考（Graph / Chain / Workflow 等）
> - **`eino-agent`** — ADK / Agent 相关参考（Agent / Runner / Middleware / Filesystem / Human-in-the-loop 等）

Skills 来源可以是：

- `eino-ext` 仓库本地路径（同步脚本会自动读取 `<src>/skills/...`）
- 你已安装 skills 的目录（目录下能看到上述四个子目录）

---

## 正文

### 从 Graph Tool 到 Skill：为什么需要"技能文档"

第八章我们解决了「复杂工作流如何做成一个可调用的 Tool」的问题。但当你构建一个面向框架学习/开发辅助的 Agent 时，还会遇到另一类挑战：

> **如何把一组稳定、可复用的知识与指令注入到 Agent 里，并让它在运行时按需加载？**

这就是 Skill 的切入点：

- **Tool** = "能做什么"（函数/接口级别的能力）
- **Skill** = "怎么做"（可复用的说明书/操作手册）

```mermaid
graph LR
    A["Agent"] --> B["Tool 层<br/>读文件 / 执行流程 / 调外部API"]
    A --> C["Skill 层<br/>知识文档 / 最佳实践 / 操作手册"]
    C --> D["eino-guide<br/>学习入口"]
    C --> E["eino-component<br/>组件参考"]
    C --> F["eino-compose<br/>编排参考"]
    C --> G["eino-agent<br/>ADK参考"]
```

简单说：**Skill 是一种可被模型发现的结构化知识包**。每个 Skill 以 `SKILL.md` 为核心描述文件，辅以 `reference/*.md` 参考资料。

### 运行步骤

在 `quickstart/chatwitheino` 目录下执行以下两步：

#### 1) 同步 eino-ext skills 到本地目录

为了让 `skill` 中间件可以"发现"这些 skills，需要把它们放到一个统一目录下，满足扫描约定：

```
EINO_EXT_SKILLS_DIR/<skillName>/SKILL.md
```

同步命令（推荐）：

```bash
go run ./scripts/sync_eino_ext_skills.go -src /path/to/eino-ext -dest ./skills/eino-ext -clean
```

> [!NOTE] `-src` 参数说明
>
> - 形式一：`eino-ext` 仓库根目录 → 脚本自动读取 `<src>/skills/...`
> - 形式二：你已安装 skills 的目录 → 要求目录下包含 `eino-guide/`、`eino-component/` 等子目录

#### 2) 启动 Chapter 9

```bash
EINO_EXT_SKILLS_DIR=/absolute/path/to/chatwitheino/skills/eino-ext go run ./cmd/ch09
```

控制台输出示例：

```
Skills dir: /.../skills/eino-ext
Enter your message (empty line to exit):
```

### 在 DeepAgent 中启用 Skill

Skill 不会被自动加载 —— 你需要在 Agent 构建时显式注册 `skill` 中间件。核心三步：

| 步骤 | 操作 | 关键 API |
|------|------|----------|
| 1️⃣ | 创建文件系统 backend | `localbk.NewBackend(ctx, &localbk.Config{})` |
| 2️⃣ | 构建 Skill Backend | `skill.NewBackendFromFilesystem(ctx, cfg)` |
| 3️⃣ | 生成中间件并注入 DeepAgent | `skill.NewMiddleware(ctx, cfg)` |

```mermaid
sequenceDiagram
    participant User as 用户
    participant Agent as DeepAgent
    participant SkillMW as Skill 中间件
    participant Backend as Skill Backend
    participant FS as 本地文件系统

    User->>Agent: 发送消息
    Agent->>SkillMW: 处理请求
    SkillMW->>Backend: 按 skillName 查找 SKILL.md
    Backend->>FS: Glob / Read 文件
    FS-->>Backend: 返回 Markdown 内容
    Backend-->>SkillMW: 技能上下文
    SkillMW-->>Agent: 注入知识到 prompt
    Agent->>User: 返回回复
```

**关键代码片段（简化版，完整代码见 `cmd/ch09/main.go`）：**

```go
// Step 1: 本地 filesystem backend
backend, _ := localbk.NewBackend(ctx, &localbk.Config{})

// Step 2: 把 $EINO_EXT_SKILLS_DIR 变成 Skill Backend
skillBackend, _ := skill.NewBackendFromFilesystem(ctx, &skill.BackendFromFilesystemConfig{
    Backend: backend,
    BaseDir: skillsDir, // = os.Getenv("EINO_EXT_SKILLS_DIR")
})

// Step 3: 创建中间件并注册到 DeepAgent
skillMiddleware, _ := skill.NewMiddleware(ctx, &skill.Config{
    Backend: skillBackend,
})

agent, _ := deep.New(ctx, &deep.Config{
    ChatModel: cm,
    Backend:   backend,
    StreamingShell: backend,
    Handlers: []adk.ChatModelAgentMiddleware{
        skillMiddleware,
        // ... 其他中间件（approval / safeTool / retry 等）
    },
})
```

> [!WARNING] 容错设计
>
> 本 quickstart 保证了"没配置 skills 也能跑"：代码中对 `EINO_EXT_SKILLS_DIR` 做了存在性检查，目录不存在则跳过注册 `skillMiddleware`。此时仍可正常对话和使用 RAG 工具。

### Skill 工具的入参格式

Skill 被注册为 Tool 后，模型的调用入参是一个 JSON 对象：

```json
{"skill": "eino-guide"}
```

其中 `"skill"` 键对应要激活的技能名称。

### 快速验证

启动后输入一条明确要求模型调用 skill 工具的指令：

```
Use the skill tool with skill="eino-guide" and tell me what the entry point is for getting started.
```

你应该看到：

- `[tool call] ...` — 模型发起了 skill 工具调用
- `[tool result] Launching skill: eino-guide` — 技能被成功激活
- Tool result 中包含 `Base directory for this skill: .../eino-guide` — 确认文件读取正确

### 会话恢复

会话数据保存在 `SESSION_DIR`（默认 `./data/sessions`），支持通过 `--session` 参数恢复：

```bash
go run ./cmd/ch09 --session <session-id>
```

---

## 关联笔记

- [[Eino/quick_start/chapter_08_graph_tool]] — 上一章：Graph Tool，理解 Tool 作为"动作能力"的基础
- [[Eino/quick_start/chapter_05_middleware]] — Middleware 机制，所有中间件的通用注册方式
- [[Eino/quick_start/chapter_04_tool_and_filesystem]] — Tool 与 Filesystem，文件系统 backend 的来源
