# RFC-001：简化处方生命周期 API

- 状态：Draft / 供讨论
- 日期：2026-07-13
- 范围：EvoCow 公共 `/v1` 接口
- 实现状态：当前 Demo 尚未迁移到本 RFC

## 1. 背景

旧版接口要求调用方理解 `refs`、结构化 observation、sensor feature、多个 report type 和纠错引用。它把 EvoCow 内部的数据建模压力暴露给了外部 Agent，也使一次简单的“现场描述—追问—建议—反馈”需要组装大量字段。

这份 RFC 把公开契约收缩到一个处方生命周期：调用方提交自然语言观察，EvoCow 返回自然语言内容；信息不足时继续追加观察；结束后提交一次完整报告。

## 2. 已确定的原则

1. `observation` 是字符串，不是结构化对象；创建和追加观察时可以同时附带当前可获得的原始 `hardware_data`。
2. 公开请求里没有 `refs`。处方 ID 是本次生命周期的唯一关联键。
3. 响应的业务内容统一为 `content: string`。
4. report 顶层严格只有三块：`human_feedback`、`conversation`、`hardware_data`。
5. EvoCow 不接管牛只、设备、病例、会话等调用方实体的生命周期。
6. LLM 通过 AI SDK 接入 Anthropic 或 OpenRouter，不使用 Bedrock。

## 3. 公开接口

| 方法   | 路径                            | 作用                          |
| ------ | ------------------------------- | ----------------------------- |
| `POST` | `/v1/prescriptions`             | 用第一条 observation 创建处方 |
| `PUT`  | `/v1/prescriptions/{id}`        | 在同一处方中追加 observation  |
| `GET`  | `/v1/prescriptions/{id}`        | 读取最新处方状态              |
| `PUT`  | `/v1/prescriptions/{id}/report` | 提交唯一的最终报告            |

所有接口使用 Bearer API Key。所有写接口要求 `Idempotency-Key`。

## 4. Schema

### 4.1 PrescriptionInput

```json
{
  "observation": "这头牛今天不吃草，精神很差。",
  "hardware_data": {
    "source": "ear-sensor-live",
    "samples": [{ "time": "2026-07-13T08:00:00+08:00", "temperature_c": 39.8 }]
  }
}
```

正文只接受两个顶层字段：

- `observation`：必填的自然语言字符串。
- `hardware_data`：可选的 JSON object 或 array，表示当前这一步可获得的硬件快照或时序片段。首版不强制设备 Schema。

每次 PUT 只提交新的观察和新获得的硬件片段，历史由服务端按处方 ID 累积。请求里的硬件数据是当前决策可见的增量证据；最终 report 中的硬件数据是生命周期结束后的完整数据。

### 4.2 Prescription

```json
{
  "id": "rx_01JEVOCOW001",
  "status": "needs_more_information",
  "content": "请测量体温，并观察呼吸是否费力、能否正常站立。"
}
```

`status` 只有三种，每种都返回完整的 `id + status + content`：

- `needs_more_information`：`content` 是下一条需要收集的问题。
- `ready`：`content` 是当前建议。
- `urgent_escalation`：`content` 是立即升级给人工或兽医的提示。

建议已就绪示例：

```json
{
  "id": "rx_01JEVOCOW001",
  "status": "ready",
  "content": "建议尽快联系驻场兽医检查。等待期间隔离观察并持续记录体温。"
}
```

紧急升级示例：

```json
{
  "id": "rx_01JEVOCOW002",
  "status": "urgent_escalation",
  "content": "发现无法站立并伴随呼吸费力，请立即联系兽医进行现场急诊处理。"
}
```

同一个处方可以经历多次 `needs_more_information`，最终进入 `ready` 或 `urgent_escalation`。终态后是否允许追加 observation，首版建议返回 `409 prescription_closed`。

### 4.3 Report

```json
{
  "human_feedback": "兽医检查后按方案处理，24 小时后体温下降，采食开始恢复。",
  "conversation": [
    { "role": "user", "content": "这头牛今天不吃草，精神很差。" },
    { "role": "assistant", "content": "请测量体温。" }
  ],
  "hardware_data": {
    "source": "ear-sensor-export",
    "samples": [{ "time": "2026-07-13T08:00:00+08:00", "temperature_c": 40.2 }]
  }
}
```

- `human_feedback`：非空字符串。
- `conversation`：全量原始 JSON object 或 array。EvoCow 首版不要求统一消息 Schema。
- `hardware_data`：原始 JSON 或 `null`。暂无统一 Schema；没有硬件数据时必须明确传 `null`。

同一处方只接受一份最终 report。相同幂等键和相同正文的重放返回同一回执；报告已存在后用新幂等键提交，返回 `409 report_already_submitted`。首版不开放公开纠错接口，纠错流程待单独设计。

## 5. 后端边界

首版保持一个 API 部署单元，公共 `/v1/*` 和内部 `/admin/*` 共用服务层与数据库，但分别鉴权。建议内部模块边界如下：

```text
HTTP/API
  -> Prescription application service
      -> LLM adapter (AI SDK: Anthropic/OpenRouter)
      -> Safety policy / fail-closed fallback
      -> Prescription + observation repository
  -> Report application service
      -> Report repository
      -> Hardware payload storage adapter
  -> Admin read models
```

LLM 输出必须被收敛成固定的 `status + content`。模型调用超时、解析失败或安全判断不确定时，系统应 fail closed，返回 `urgent_escalation` 或可安全展示的人工升级内容，不能返回半截结构。

## 6. 硬件时序数据：待决策

硬件数据的设备协议、采样频率、单次体积、查询方式和保留周期尚未确定，因此本 RFC 只固定它在处方输入和最终 report 中的语义位置，不固定内部时序 Schema。

- 处方输入中的 `hardware_data`：当前可用的增量证据，参与本次判断。
- 最终 report 中的 `hardware_data`：结束后收集到的完整数据，用于复盘、审计和后续评估。

建议验证两阶段方案：

1. MVP：原始 payload 压缩后进入对象存储；PostgreSQL 保存 report ID、对象 URI、内容哈希、字节数和服务端接收时间。为内联 JSON 设置明确的单次大小上限。
2. 当产品确认需要按指标和时间窗查询时：异步把白名单指标投影进 TimescaleDB 或 PostgreSQL 时序表。原始 payload 继续作为审计事实保留。

合并 RFC 前需要回答：

- 内联 JSON 的最大字节数是多少？
- 大 payload 是否改用预签名上传？
- 数据保留多久，是否允许调用方主动删除？
- 是否需要按设备、指标和时间窗查询？
- conversation 与 hardware_data 是否包含需要额外加密或脱敏的信息？

## 7. 非目标

- 本 RFC 不定义牛只、病例、设备或会话主数据接口。
- 本 RFC 不定义硬件厂商的统一采样 Schema。
- 本 RFC 不定义 Skill 自动发布、在线自我修改或模型训练管道。
- 本 RFC 不定义 Admin API 的最终契约；Admin 先作为内部读模型独立演进。
- 本 RFC 不宣称当前 Demo 已兼容这些接口。

## 8. 实施顺序

1. 评审并冻结本 RFC 的 4 个接口和 3 个 report 顶层字段。
2. 修改 Zod contracts、数据库 schema 和公共路由。
3. 为 4 个公开接口补齐真实数据库 + 真实 LLM 集成测试。
4. 调整 Admin 投影，不影响公开契约。
5. 决定硬件存储 ADR 后再实现大 payload 上传。
