---
created: 2026-03-29
updated: 2026-04-06
type: project
status: COMPLETED (2026-03-30)
parent: "[[Smart Support]]"
phase: 1
timeline: 第 1-3 周
tags:
  - phase-1
  - fastapi
  - websocket
  - langgraph
  - agent-orchestration
  - postgresql
  - react
  - yaml-registry
  - interrupt
  - hitl
  - docker
  - mock-agent
  - token-tracking
  - prompt-caching
  - session-ttl
---

# Phase 1：核心框架

## 目标

搭建 Smart Support 的核心闭环：客户发消息 → AI Agent 处理 → 流式回复。这个阶段结束时，应该有一个完整可运行的聊天应用，能通过 mock 工具回答问题，并在写操作时触发人工确认。

## 阶段产出

- 可运行的全栈应用（`docker compose up` 一键启动）
- 聊天界面能发消息、收到流式回复
- 2-3 个演示 Agent 通过 mock 工具执行操作
- 写操作自动触发确认提示

## 集成检查点

第 3 周末验证：
1. `docker compose up` → PostgreSQL + FastAPI 正常启动
2. 打开 `http://localhost:8000` → 聊天界面加载
3. 发送「查询订单 1042 的状态」→ 收到流式回复
4. 发送「取消订单 1042」→ 收到确认提示 → 批准 → 确认取消
5. `pytest --cov` → 80%+ 覆盖率

---

## 任务清单

### 1. 基础设施搭建

- [ ] 初始化 Python 项目（`pyproject.toml`，依赖：fastapi, uvicorn, langgraph, langchain-anthropic, langgraph-checkpoint-postgres, langchain-mcp-adapters）
- [ ] 创建 `docker-compose.yml`（PostgreSQL 16 + 应用容器）
- [ ] 配置环境变量（`.env.example`）：`LLM_PROVIDER`, `LLM_MODEL`, `ANTHROPIC_API_KEY`, `DATABASE_URL`
- [ ] 创建项目目录结构：

```
backend/
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── graph.py
│   ├── registry.py
│   ├── callbacks.py
│   └── agents/
│       ├── __init__.py
│       ├── order_lookup.py
│       ├── faq.py
│       └── fallback.py
├── agents.yaml
└── tests/
    ├── __init__.py
    ├── test_graph.py
    ├── test_registry.py
    ├── test_websocket.py
    └── conftest.py
```

### 2. PostgresSaver 检查点配置

- [ ] 在 `main.py` 启动时初始化 PostgresSaver（调用 `.setup()` 创建表结构）
- [ ] 配置连接池（asyncpg）
- [ ] 验证检查点持久化：重启应用后，之前的对话上下文仍可恢复
- [ ] DB 连接错误处理：graph 调用外层 try/except，捕获 DB 异常时返回「抱歉，系统暂时无法保存对话，请稍后重试」

### 3. YAML Agent 注册表

- [ ] 定义 `agents.yaml` 配置格式：

```yaml
agents:
  - name: order_lookup
    description: 查询订单状态、物流跟踪信息
    permission: read
    personality:
      tone: professional
      greeting: "您好，我来帮您查询订单信息。"
    tools:
      - get_order_status
      - get_tracking_info

  - name: faq
    description: 回答常见问题（退货政策、运费、营业时间等）
    permission: read
    personality:
      tone: friendly
      greeting: "有什么可以帮您的？"
    tools: []

  - name: fallback
    description: 通用兜底 Agent，处理无法路由的请求
    permission: read
    personality:
      tone: helpful
    tools: []
```

- [ ] 实现 `registry.py`：加载 YAML，验证必填字段（name, description, permission），缺失字段报明确错误（含文件名和字段名）
- [ ] 无效 YAML 语法 → 启动时抛出错误，包含行号
- [ ] Agent personality 配置解析（tone, greeting, escalation_message）

### 4. LangGraph Supervisor 配置

- [ ] 使用 `langgraph-supervisor` 创建 supervisor graph
- [ ] 从 agent 注册表动态注册 agents（注册表驱动，非硬编码）
- [ ] 每个 agent 配置对应的 mock 工具（`@tool` 装饰器）
- [ ] Mock 工具实现：
  - `get_order_status(order_id: str)` → 返回模拟订单数据（状态、日期、金额）
  - `get_tracking_info(order_id: str)` → 返回模拟物流数据
  - `cancel_order(order_id: str)` → 返回取消确认（触发 interrupt）
- [ ] Fallback agent：当 supervisor 路由失败或 agent 返回「无法处理」时，fallback agent 接管，尝试所有可用工具
- [ ] Supervisor 使用 `ChatAnthropic`（Claude Sonnet 4.6），通过 `LLM_PROVIDER` + `LLM_MODEL` 环境变量可切换

### 5. interrupt() 人工确认流程

- [ ] 在 agent 调用写操作工具前触发 `interrupt()`
- [ ] 判断逻辑：agent YAML 中 `permission: write` 的 agent，其所有工具调用都触发确认
- [ ] 确认提示格式：「即将执行：取消订单 #1042。确认执行？[是/否]」
- [ ] 用户回复「是」→ `Command(resume="approved")` → 执行操作
- [ ] 用户回复「否」→ `Command(resume="rejected")` → 返回「操作已取消」
- [ ] 确认状态通过 PostgresSaver checkpoint 持久化

### 6. FastAPI WebSocket 端点

- [ ] `ws://localhost:8000/ws` WebSocket 端点
- [ ] 连接时生成 `thread_id`（UUID），作为 PostgresSaver 的 thread 标识
- [ ] 接收消息 → 调用 supervisor graph（`ainvoke` / `astream_events()`）
- [ ] 流式输出：通过 `astream_events()` 获取 LLM token，逐个通过 WebSocket 发送
- [ ] 消息协议：

```json
// 客户端 → 服务器
{"type": "message", "content": "查询订单 1042"}

// 服务器 → 客户端（流式 token）
{"type": "token", "content": "您"}
{"type": "token", "content": "的"}
{"type": "token", "content": "订单"}

// 服务器 → 客户端（确认提示）
{"type": "interrupt", "action": "cancel_order", "params": {"order_id": "1042"}, "message": "即将取消订单 #1042，确认执行？"}

// 客户端 → 服务器（确认回复）
{"type": "resume", "decision": "approved"}

// 服务器 → 客户端（错误）
{"type": "error", "message": "系统暂时无法处理，请稍后重试"}
```

- [ ] 断线处理：WebSocket 关闭时清理资源，不影响其他连接
- [ ] 无效 JSON → 返回 error 消息，不断开连接

### 7. React 聊天 UI

- [ ] 基础聊天界面（消息列表 + 输入框 + 发送按钮）
- [ ] WebSocket 连接管理（连接、断线重连）
- [ ] 流式 token 渲染（逐字显示 AI 回复）
- [ ] 中断确认 UI：收到 `interrupt` 消息时，显示操作描述 + 「确认」/「取消」按钮
- [ ] 错误提示：收到 `error` 消息时，显示红色提示
- [ ] Agent 操作可视化：显示 agent 正在执行的工具调用（如「正在查询订单...」）

### 8. Token 用量统计

- [ ] 实现 `callbacks.py`：LangChain callback handler，记录每次 LLM 调用的 input/output tokens
- [ ] 数据写入 PostgreSQL（独立表或利用 checkpoint metadata）
- [ ] 每条记录包含：`thread_id`, `agent_name`, `input_tokens`, `output_tokens`, `model`, `timestamp`

### 9. 测试

- [ ] **Graph 测试：** supervisor 收到「查询订单」→ 路由到 order_lookup agent → 调用 get_order_status → 返回结果
- [ ] **Graph 测试：** supervisor 收到模糊请求 → 路由到 fallback agent
- [ ] **Graph 测试：** agent 调用写操作 → interrupt 触发 → resume approved → 操作执行
- [ ] **Graph 测试：** interrupt → resume rejected → 操作取消
- [ ] **注册表测试：** 有效 YAML → agents 正确加载
- [ ] **注册表测试：** 无效 YAML → 明确错误信息
- [ ] **注册表测试：** 缺失必填字段 → validation error
- [ ] **WebSocket 测试：** 发送消息 → 收到流式 token
- [ ] **WebSocket 测试：** 发送无效 JSON → 收到 error，连接不断
- [ ] **WebSocket 测试：** 断线 → 服务器清理资源
- [ ] **DB 测试：** 连接正常 → checkpoint 持久化成功
- [ ] **DB 测试：** 连接失败 → 用户收到友好错误
- [ ] **E2E 测试：** 完整聊天流程（发消息 → 收回复）
- [ ] **E2E 测试：** 完整确认流程（写操作 → 确认 → 执行）

## 技术要点

| 组件 | 技术选型 | 说明 |
|------|---------|------|
| Web 框架 | FastAPI | 原生 WebSocket + async 支持 |
| Agent 编排 | langgraph-supervisor v1.1 | 内置 supervisor + middleware |
| 状态持久化 | langgraph-checkpoint-postgres v3.0.5 | 需调用 `.setup()` 初始化 |
| LLM | ChatAnthropic (Claude Sonnet 4.6) | 通过 LangChain BaseChatModel 抽象 |
| 流式输出 | astream_events() | Messages 模式，逐 token 推送 |
| 前端 | React | WebSocket 连接 + 流式渲染 |
| 数据库 | PostgreSQL 16 | Docker Compose 部署 |
| 测试 | pytest + FastAPI TestClient | 80%+ 覆盖率 |

## 依赖项

```
langgraph>=1.1.0
langgraph-supervisor
langgraph-checkpoint-postgres>=3.0.5
langchain-anthropic
langchain-mcp-adapters
fastapi
uvicorn[standard]
asyncpg
pyyaml
pytest
httpx
```

## 风险与缓解

| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| LangGraph supervisor 路由不准 | Agent 收到错误类型的请求 | Fallback agent 兜底 + agent description 写清楚 |
| PostgresSaver 初始化失败 | 应用无法启动 | 启动时检查连接，失败报明确错误 |
| WebSocket 连接不稳定 | 用户体验差 | 前端自动重连 + 断线提示 |
| LLM API 超时 | 用户等待无响应 | 设置 timeout + 返回错误消息 |

## Related

- [[Smart Support]]
- [[Smart Support/Phase 2 - 多 Agent + 安全]]
