# AI 事后话术：放 tool 返回值里，不放 description / 不靠 memory

**Date**: 2026-05-19
**Module**: internal-app-platform / MCP tool 设计通用
**Related**: PR #434 / [2026-05-18-claude-ignores-ffoa-apps-mcp-generates-generic-deploy.md](2026-05-18-claude-ignores-ffoa-apps-mcp-generates-generic-deploy.md)

## 症状

`deploy_prepare` MCP 工具成功返回后，Claude Code 对用户的回复是自由发挥的：

> 部署已触发，代码已推送到 album app。
> URL: https://itadmin-album.apps.ffworkspace.test.faradayfuturecn.com
> 平台 webhook 会自动接住并构建部署
> 如需查看日志，告诉我即可。

用户立刻访问 URL → 502 / 自签证书 / 旧版本（webhook 构建实际要 30s–5min）。
体感"部署没成功"，实际是"AI 没说清 push≠上线"。

## 三种"让 AI 每次都带某句话"的方案对比

| 方案 | 触达率 | 跨 session | 跨 AI（Claude/Codex）| 评价 |
|---|---|---|---|---|
| **AI 个人 memory** | 当前 session 100%，新 session 0% | ❌ | ❌ | 最差 — 换 session / 换 AI 即失效 |
| **Tool description** | AI 调用前读到一次，事后不一定记得 | ✅ | ✅ | 中 — description 是"如何调"，不是"调完该说啥" |
| **Tool 返回值字段（如 postDeployHint）** | 100%，AI 拿到结构化数据自然引用 | ✅ | ✅ | **最佳** — 数据驱动，不靠 AI 记忆 |

## 解法

在 `DeployPrepareOutput` 加 `postDeployHint: string` 字段，service 填入完整话术：

```ts
// dto/mcp.dto.ts
export interface DeployPrepareOutput {
  // ... 其他字段
  /** 给 Claude 的事后话术：push≠上线，提示用户 5min 后验证 url / 否则调 logs */
  postDeployHint: string;
}

// services/mcp-tools.service.ts
return {
  ok: true,
  data: {
    // ...
    postDeployHint: `代码已推到 Gitea。平台 webhook 接到 push 后会拉起构建并部署，通常 30 秒到 5 分钟完成。请告知用户：约 5 分钟后访问 ${url} 验证；如仍无法访问，可让用户提出"查看日志"，再用 logs 工具拉构建/运行日志。push 完成 ≠ 上线完成，不要立即声称部署成功。`,
  },
};
```

Claude 拿到这个字段后自然会把内容融入对用户的回复——不靠记忆、不靠 prompt 工程、不靠 skill 文档。

## 适用范围（不止 deploy_prepare）

任何"工具调完后 AI 应该向用户传递某条非结构化信息"的场景都适用：

- 长耗时异步操作（部署 / 构建 / 训练 / 报表生成）→ `pollHint` / `eta` / `postCallGuidance`
- 操作有副作用但延迟可见（cache invalidate / 权限变更 5min 生效）→ `propagationHint`
- 结果需要二次验证（迁移完成 / 配置下发）→ `verifyHint`
- 操作部分成功（批量任务 80% 完成）→ `partialResultGuidance`

**判别准则**：如果你发现自己想在 prompt / memory / skill 文档里写"AI 调完 X 工具后应该告诉用户 Y"——停下，加到 X 的返回值里。

## 反例（已修正）

2026-05-18 时同样症状下采用的应对是写 `.learnings/` 笔记 + 加 skill TODO（"封装 ffoa-apps-deploy slash command"）——下一个 session 的 Claude 不会自动读到，下次又重犯。

2026-05-19 第二次复现后，改成"数据驱动 + 字段固化"，断了 AI 自由发挥的口子。

## 元规则

跟 CLAUDE.md #12 "项目知识落项目文件，不落 AI memory" 同源——
**AI 行为指令也应落到数据结构 / 文档 / 代码里，不落到 prompt 工程**。
prompt 工程是没办法时的兜底，不是默认。
