# Agent API Endpoints 本文档以当前后端实现为准,描述 `/api/v1/agent` 的 HTTP 接口契约。 Base URL: `/api/v1/agent` --- ## 端点清单 | 方法 | 路径 | 说明 | |---|---|---| | POST | `/runs` | 创建一次 agent run(异步入队) | | GET | `/runs/{thread_id}/events` | 订阅 SSE 事件流 | | GET | `/history` | 获取历史快照(按天分页) | | POST | `/attachments` | 上传用户图片附件 | | GET | `/attachments/signed-url` | 获取附件临时签名链接 | | POST | `/transcribe` | WAV 音频转写 | --- ## 1) POST `/runs` 发起一次运行请求,后端会先持久化用户消息,再将命令放入异步队列。 ### Request - Body: `RunAgentInput` - 详细结构见 `docs/protocols/agent/run-agent-input.md` ### Response `202 Accepted` ```ts { taskId: string; threadId: string; runId: string; created: boolean; // 是否新建了会话 } ``` ### 错误码 - `401` 未认证 - `422` 请求结构校验失败 - `429` 超过 run 请求速率限制 --- ## 2) GET `/runs/{thread_id}/events` 订阅指定 thread 的实时事件流。 ### Path | 参数 | 类型 | 说明 | |---|---|---| | `thread_id` | string | 会话 ID | ### Query | 参数 | 类型 | 默认 | 说明 | |---|---|---|---| | `idle_limit` | integer | `300` | 最大空闲轮询次数(1-3600) | ### Headers | Header | 必填 | 说明 | |---|---|---| | `Accept: text/event-stream` | 否 | 建议显式设置 | | `Last-Event-ID` | 否 | 从指定游标断点续流 | ### Response - `200 OK` - `Content-Type: text/event-stream` - 事件类型与字段见 `docs/protocols/agent/sse-events.md` - 空闲时会发送 keep-alive 注释行 `: keep-alive` ### 错误码 - `401` 未认证 - `403` 非会话所有者 - `422` `Last-Event-ID` 非法 - `429` 超过 SSE 连接数限制 --- ## 3) GET `/history` 返回历史快照(`HistorySnapshotResponse`),不是 SSE 包装事件。 ### Query | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | `threadId` | string | 否 | 指定会话,不传则取当前用户最近会话 | | `before` | `YYYY-MM-DD` | 否 | 返回该日期之前最近一天的快照 | ### Response ```ts { scope: "history_day"; threadId: string | null; day: string | null; // YYYY-MM-DD hasMore: boolean; messages: Array<{ id: string; seq: number; role: "user" | "assistant"; content: string; attachments?: Array<{ // user 附件签名链接列表 mimeType: string; url: string; }>; ui_schema?: object | null; // assistant 的编译后 UI timestamp: string; // ISO-8601 }>; } ``` tool 消息在存储层用于运行时上下文续接,不在 `/history` 对外返回。续接时以 `metadata.tool_agent_output` 作为主信源(`content` 为轻量摘要)。 ### 说明 - 若用户没有任何会话:返回 - `threadId = null` - `day = null` - `hasMore = false` - `messages = []` --- ## 4) POST `/attachments` 上传图片附件,返回可直接用于 `RunAgentInput.messages[].content[].url` 的签名链接。 ### Request - `multipart/form-data` | 字段 | 类型 | 说明 | |---|---|---| | `threadId` | string | 会话 ID | | `file` | file | 附件文件 | ### Response ```ts { attachment: { bucket: string; path: string; mimeType: string; url: string; }; } ``` ### 错误码 - `401` 未认证 - `403` 非会话所有者 - `413` 附件超过大小限制 - `422` 文件类型不支持/空文件等 - `503` 存储服务不可用 --- ## 5) GET `/attachments/signed-url` 对已有存储对象重新签名。 ### Query | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | `bucket` | string | 是 | 存储桶 | | `path` | string | 是 | 对象路径 | ### Response ```ts { bucket: string; path: string; url: string; } ``` --- ## 6) POST `/transcribe` WAV 音频转写。 ### Request - `multipart/form-data` | 字段 | 类型 | 说明 | |---|---|---| | `audio` | file | WAV 文件 | ### Response ```ts { transcript: string; } ``` ### 限制 - 内容类型:`audio/wav` / `audio/x-wav` / `audio/wave` - 文件大小:最大 10MB - 速率限制:20 次/分钟/用户 --- ## 通用错误 当前实现的错误主体为 FastAPI `detail` 字段: ```json { "detail": "..." } ```