# 2026-06-08 — Agent 401 停心跳 + 配置重载后重启（A-05）

## 摘要

边端 Agent 心跳收到中心 **401** 或 **discarded** 后永久退出循环；`/config/reload` 写入新 key 后自动重启心跳任务。策略提取为 `heartbeat_policy.py` 并加单测。

## 动机

错误 API key 时旧 Agent 每 60s 无限重试；401 停循环已在 `72d82d7` 落地，但缺单测、缺 key 修复后自动恢复、子机文件未统一 rollout。

## 涉及文件

- `web/agent/heartbeat_policy.py`（新）
- `web/agent/agent.py` — `AGENT_VERSION` 常量、config reload 重启心跳
- `web/agent/install.sh` — 同步下载 `heartbeat_policy.py`
- `server/application/server_batch_common.py` — `agent_files_curl_cmds` 升级双文件
- `server/api/servers.py` · `server_batch_service.py` — 升级拉取双文件
- `server/utils/agent_version.py` — 读 `AGENT_VERSION` 常量
- `tests/test_agent_heartbeat_stop.py`

## 迁移 / 重启

- 中心：`/agent/agent.py` 随 API 镜像更新
- **各子机**：须批量 **升级 Agent** 或重装，否则仍跑旧 `agent.py`（见 backlog #7）

## 行为

| 中心响应 | Agent |
|----------|--------|
| 401 Invalid API key | 停止心跳，打 error 日志 |
| 200 `status=discarded` | 停止心跳（错误 server_id 等） |
| 5xx / 网络错误 | 指数退避重试（不变） |
| `/config/reload` 新 key | 若心跳已停，重启协程 |

## 验证

```bash
pytest tests/test_agent_heartbeat_stop.py tests/test_agent_version.py -q
bash scripts/local_verify.sh
```
