## 模块 2：确保智能体工作目录持久化

```mermaid
---
title: 模块环境总览
---
flowchart LR
  USER["实验用户"] --> T1["终端1:<br/>Hermes沙箱"]
  USER --> T2["终端2:<br/>VM主机"]
  T1 --> TD_LAYOUT
  T2 --> TD_LAYOUT
  
  %% DIR及其连接：切换为自上而下的方向
  subgraph TD_LAYOUT["使用 TiDB Cloud CLI 和文件系统"]
    direction TB
    TI1["ti"]
    TI1 -->|管理| FS["TiDB Cloud 文件系统<br/>aws-${LAB:REGION_CODE}"]
    DIR["本地沙箱目录<br/>aws-${LAB:REGION_CODE}"]
    TI1 -->|FUSE挂载| FS
    FS -->|FUSE挂载| DIR
  end
```

在本模块中，你将配置并启动实验VM上预装的Hermes 智能体。通过`ti`命令，它将创建、挂载并验证一个TiDB Cloud 文件系统，该文件系统独立于VM、智能体会话或智能体沙箱生命周期持久存在，并设置为智能体的默认工作目录。

### 步骤 1：配置 Hermes 原生沙箱并启动 Hermes 会话

- 返回 **[终端 1](ssh://monitor1-ssh#1)**。
- 执行以下命令应用Hermes的预设配置。我们将在之后回顾配置细节。

```bash
# 应用预设配置
cp ~/config.yaml.solution ~/.hermes/config.yaml
```

- 检查相关配置。更多细节见下方说明。

```bash
# 检查相关设置
hermes config check
cat ~/.hermes/config.yaml | grep -A17 'terminal:'
```

```output
terminal:
  backend: docker
  cwd: .
  timeout: 720
  home_mode: auto
  docker_mount_cwd_to_workspace: false
  docker_forward_env:
    - "TI_FS_TOKEN"
    - "TI_REGION_CODE"
    - "DATABASE_URL"
  docker_run_as_host_user: false
  docker_extra_args:
    - "--privileged"
    - "--device=/dev/fuse"
    - "--cap-add=SYS_ADMIN"
    - "--security-opt=apparmor=unconfined"
    - "--tmpfs=/tmp:rw,nosuid,size=512m,exec"
  docker_persist_across_processes: false
```

- Hermes 配置说明：
  - `backend: docker`：将Docker用作工具后端，使命令在安全的短生命周期容器（沙箱）中执行，而不是直接在VM主机壳中。
  - `docker_forward_env`：将`TI_FS_TOKEN`、`TI_REGION_CODE`和`DATABASE_URL`等环境变量转发进沙箱容器。（注意：`DATABASE_URL`在下一模块使用）
  - `docker_extra_args`：FUSE挂载TiDB Cloud文件系统所需的Docker参数，包括`--privileged`, `--device=/dev/fuse`, `--cap-add=SYS_ADMIN`, `--security-opt=apparmor=unconfined` 以及可执行的`/tmp` tmpfs。
  - `docker_persist_across_processes: false`：不同Hermes进程间不持久Docker容器，确保每次新Hermes会话都是新的容器。

> [!NOTE]
> 如前一模块所述，只要环境中有`TI_FS_TOKEN`变量和文件系统的区域信息，TiDB Cloud CLI可无需额外配置直接挂载目标文件系统。

- 启动Hermes会话，进入Hermes提示符。启动可能需要30秒左右。

```bash
hermes chat
```

```output
 ⚕ deepseek.v3.2 │ ctx -- │ [░░░░░░░░░░] -- │ 18s │ ⏲ 0s 
──────────────────────────────────────────────────────────────────────────────────
❯ 
──────────────────────────────────────────────────────────────────────────────────
```

### 步骤 2：帮助 Hermes 智能体了解 TiDB Cloud CLI

- 保持在 **[终端 1](ssh://monitor1-ssh#1)** 开始与智能体交互。

- 让Hermes打印环境变量。确认环境变量中存在关键的`TI_`相关项。让智能体运行`env`，查看输出，确认`TI_FS_TOKEN`及`TI_REGION_CODE`都已经包含。你的主要目标是确认存在即可，无需在意智能体当下如何理解它们的用途。

```text
执行 env
```

```output
╭─ ⚕ Hermes ──────────────────────────────╮
我理解您想查看当前的环境变量。让我为您执行这个命令。
.
TI_FS_TOKEN=*** (已隐藏)
.
TI_REGION_CODE=aws-${LAB:REGION_CODE}
.
```

- 确认Hermes终端会话是否运行在沙箱容器环境中。

```text
你的终端是在短生命周期的沙箱容器中运行的吗？
```

```output
╭─ ⚕ Hermes ───────────────────────╮
看起来是这样的。让我检查更多系统信息来确认：
.
.
.
```

- 帮助智能体学习如何使用TiDB Cloud CLI命令行工具。观察其反馈，判断其是否理解统⼀存储层的价值。

> [!TIP]
> 这里我们特意不使用专用的TiDB Cloud Filesystem 智能体技能。

```text
访问 https://github.com/tidbcloud/ti-cli。请告诉我这个工具具备哪些功能？你能否利用这些功能来提升你的工作流程？
```

```output
╭─ ⚕ Hermes ────────────────────────╮
让我访问这个GitHub仓库来了解ti-cli的功能：
.
.
.
```

- 现在，Hermes 智能体已理解如何使用TiDB Cloud Filesystem，并认识到统一状态存储层的重要意义，正在考虑如何利用此能力优化自身工作流。

### 步骤 3：让智能体自主解决工作目录持久化

- 让你的智能体安装合适的技能。允许它有最长3分钟去完成安装，可以包括后续的验证步骤。观察其过程，耐心等待。如果 Hermes 问你要许可，请放行。

```text
添加这个Skill - https://github.com/pingcap/agent-rules/blob/main/skills/mount-tidb-cloud-fs/SKILL.md
```

```output
╭─ ⚕ Hermes ────────────╮
让我获取并查看这个技能的内容：
.
.
.
该技能已准备好使用，只要容器中设置了 TI_FS_TOKEN 和 TI_REGION_CODE 环境变量——我们已经具备！
```

- 复制以下指令让Hermes 智能体以 `/workspace` 作为自身持久化、默认的工作目录，并将所有输出文件保存在该目录下。仔细观察智能体的执行过程及其是否符合期望。

```text
FUSE mount TiDB Cloud FS 到 /workspace 目录，并将其作为你所有输出文件的存放位置。最后，给我一份报告。
```

```output
╭─ ⚕ Hermes ───────────────────────────────────────────────────────────────────────────────────────────╮
我来按照 mount-tidb-cloud-fs 技能的指导，将TiDB Cloud文件系统挂载到 /workspace 目录。首先让我检查当前情况并执行挂载。
.
.
.
此目录现在提供了一个持久的、跨会话的工作空间，对复杂多步任务尤其提升了工作流。
```

> [!NOTE]
> Hermes沙箱环境默认未预装`fusermount`和`ti-cli`工具（FUSE装载操作必需）。幸运的是，智能体可以自动检测并在需要时安装这些依赖。若想避免重建沙箱后重复安装，请考虑通过提交镜像预装这些工具。我们稍后会操作。

### 步骤 4：让智能体实际使用 TiDB Cloud 文件系统

- 让Hermes 智能体在 `/workspace` 下创建一个太阳系天体库的Python程序。当智能体开始写入Python文件即可继续下一步，无需等待任务完全结束。

```text
在 /workspace 目录下创建一个简单的 Python 程序，该程序能够返回太阳系内任意行星的卫星信息。
```

```output
╭─ ⚕ Hermes ────────────────────────────────────────────────────────────────────────────╮
我来在 /workspace 目录下创建一个能够返回太阳系行星卫星信息的Python程序。首先让我查看一些已知的卫星数据。
.
.
.
```

### 步骤 5：验证智能体是否使用 TiDB Cloud 文件系统

- 切换到 **[终端 2](ssh://monitor1-ssh#2)** 并新开一个终端2：

- 在VM主机上，运行如下命令，导入Hermes的环境变量（特别是`TI_FS_TOKEN`），并在Hermes沙箱的 `/workspace` 目录中搜索内容包含 **Solar** 的文件。你的输出可能与样例不同：

```bash
source ~/.hermes/.env
export TI_FS_TOKEN
ti fs search-file-content --pattern Solar
```

> [!IMPORTANT]
> 你可以直接用`ti`命令，`ti fs search-file-content` 支持语义搜索，会查找文件内容相关项而非仅文件名。

```output
{
  "path": "/",
  "results": [
    {
      "path": "/solar-system-moons/README.md",
      "name": "README.md"
    },
    {
      "path": "/solar-system-moons/test_moon_finder.py",
      "name": "test_moon_finder.py"
    }
  ]
}
```

### 步骤 6：创建新的沙箱镜像

- 在 **[终端 2](ssh://monitor1-ssh#2)**，创建一个名为 **`hermes-sandbox:v1`** 的新Docker镜像（预装TiDB Cloud CLI及其依赖），可避免每次重建沙箱都重复安装（如`ti-cli`、`fusermount`等）。

```bash
docker commit $(docker ps -l -q -f status=running | head -1) hermes-sandbox:v1
```

> [!NOTE]
> 此操作约需2分钟。本实验VM较小，请耐心等待。

```output
sha256:88212b02b034........a3030400f49b0538579
```

- 修改 Hermes 配置以在下次启动新会话时应用新镜像。

```bash
sed -i '/backend: docker/a\  docker_image: hermes-sandbox:v1' ~/.hermes/config.yaml
hermes config check
```

```output
.
.
.
    ○ TEAMS_PORT
    ○ TEAMS_HOST
    ○ TEAMS_ALLOWED_USERS
    ○ TEAMS_ALLOW_ALL_USERS
    ○ TEAMS_HOME_CHANNEL
    ○ TEAMS_HOME_CHANNEL_NAME
```

### 步骤 7：测试新沙箱是否继承 TiDB Cloud 文件系统

- 保持在 **[终端 2](ssh://monitor1-ssh#2)**，用以下命令确认当前沙箱容器正在运行。输出结果与你实际环境有关。

```bash
docker ps
```

```output
CONTAINER ID   IMAGE                                        COMMAND            CREATED          STATUS          PORTS     NAMES
19b7b29802b8   nikolaik/python-nodejs:python3.11-nodejs20   "sleep infinity"   21 minutes ago   Up 21 minutes             hermes-b401e193
```

- 回到 **[终端 1](ssh://monitor1-ssh#1)**，退出当前Hermes聊天会话。

```text
/quit
```

```output
Resume this session with:
  hermes --resume 20260817_000435_239c2f
.
.
.
```

> [!IMPORTANT]
> 退出Hermes会话会同时销毁相关的短生命周期沙箱容器。

- 切换到 **[终端 2](ssh://monitor1-ssh#2)**，通过如下命令确认沙箱容器已被移除：

```bash
docker ps
```

```output
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

- 回到 **[终端 1](ssh://monitor1-ssh#1)**。启动新会话，将自动创建全新的沙箱。

```bash
hermes chat
```

- 询问Hermes此时 **`/workspace`** 目录的状态。如果目录内容为空属于正常——新的沙箱尚未挂载TiDB Cloud文件系统。

```text
现在 /workspace 目录的状态是什么？
```

```output
╭─ ⚕ Hermes ───────────────────╮
我来检查一下 /workspace 目录的状态。
.
.
.
```

> [!IMPORTANT]
> 若智能体未能自动将TiDB Cloud文件系统挂载到`/workspace`，请用下述指令提醒它。

- 如果未自动挂载TiDB Cloud文件系统，使用下面的提示让智能体执行挂载，并确认**数据并未丢失**。（输出内容可能不同）

```text
将 TiDB Cloud 文件系统以 FUSE 挂载到该目录。挂载完成后，列出 /workspace 目录结构。
```

```output
╭─ ⚕ Hermes ──────────────────────────────────╮
我将首先加载相关的技能，然后挂载 TiDB Cloud 文件系统。
.
.
.
/workspace 目录结构：

/workspace/
├── README.md (3947字节) - 太阳系行星卫星信息系统文档
├── demo.py (2716字节) - Python演示程序
├── hello-world.txt (20字节) 
├── hermes-fs-mount-report.md (1423字节) - 挂载报告
├── hermes-projects/ - Hermes项目目录
│   └── test-session-20260819-061830/ - 测试会话目录
│       ├── config.json (126字节)
│       ├── hello.py (64字节)
│       └── session.log (112字节)
├── hermes-test.txt (74字节)
├── hermos-fs-mount-report.md (25字节)
├── moon_info_cli.py (1746字节) - 月球信息CLI工具
└── planetary_moons.py (14381字节) - 行星卫星主程序
```

- 退出Hermes聊天。

```text
/quit
```

> [!IMPORTANT]
> 目前为止，我们模拟了两个独立智能体会话间切换工作目录的场景。实际生产环境中，你可以构建一个始终自动挂载TiDB Cloud文件系统的docker镜像，供智能体沙箱使用。

请继续下一个模块。
