- 前端: 添加 SSE 流式支持、stateSnapshot 事件、路由导航工具 - 前端: 实现工具调用审批流程,支持 pending 状态展示 - 后端: Agent 状态管理与会话持久化相关重构 - 文档: 新增 agent-agui-full-alignance 设计文档 - 测试: 补充相关单元测试和集成测试
15 KiB
Runtime API Routes
本文档记录所有 HTTP API 端点。修改路由时必须同步更新此文档。
格式说明
- Request/Response 使用 JSON 格式
- 错误响应使用 RFC 7807
application/problem+json - 所有端点前缀:
/api/v1
Auth
POST /auth/verifications
创建验证码(注册发起)。
Request:
{
"username": "string (3-30 chars)",
"email": "string (email)",
"password": "string (min 6 chars)",
"redirect_to": "string? (optional)",
"invite_code": "string? (8 chars, 排除易混淆字符 0/1/I/L/O)"
}
Response: 202 Accepted
{
"email": "user@example.com"
}
邀请码说明:
- 可选字段,不填则注册不受影响
- 格式:8 位字母数字组合,排除易混淆字符 (0, 1, I, L, O)
- 注册时传入有效邀请码会建立邀请关系并增加邀请码使用次数
- 无效邀请码(不存在/已禁用/已过期/已达上限)不会阻断注册成功
Errors:
- 422: 请求参数无效
- 429: 请求过于频繁
POST /auth/resend
重发验证码(统一端点,支持注册/找回密码)。
Request:
{
"type": "signup | recovery (default: signup)",
"email": "string (email)",
"redirect_to": "string? (仅 recovery 可选)"
}
Response: 204 No Content
Errors:
- 422: 请求参数无效
- 429: 请求过于频繁
POST /auth/verify
验证码校验(统一端点,按 type 区分场景)。
Request (signup):
{
"type": "signup",
"email": "string (email)",
"token": "string (6 digits)"
}
Response (signup): 200 OK
{
"access_token": "string",
"refresh_token": "string",
"expires_in": 3600,
"token_type": "bearer",
"user": {
"id": "string",
"email": "string"
}
}
Request (recovery):
{
"type": "recovery",
"email": "string (email)",
"token": "string (6 digits)",
"new_password": "string (min 6 chars)"
}
Response (recovery): 204 No Content
Errors:
- 401: 验证码无效或已过期
- 422: 请求参数无效
- 429: 请求过于频繁
POST /auth/sessions
登录(创建会话)。
Request:
{
"email": "string (email)",
"password": "string (min 6 chars)"
}
Response: 200 OK
{
"access_token": "string",
"refresh_token": "string",
"expires_in": 3600,
"token_type": "bearer",
"user": {
"id": "string",
"email": "string"
}
}
Errors:
- 401: 邮箱或密码错误
- 422: 请求参数无效
- 429: 请求过于频繁
POST /auth/sessions/refresh
刷新 Token。
Request:
{
"refresh_token": "string"
}
Response: 200 OK
{
"access_token": "string",
"refresh_token": "string",
"expires_in": 3600,
"token_type": "bearer",
"user": {
"id": "string",
"email": "string"
}
}
Errors:
- 401: 无效的 refresh token
- 422: 请求参数无效
- 429: 请求过于频繁
DELETE /auth/sessions
登出(删除会话)。
Request:
{
"refresh_token": "string"
}
Response: 204 No Content
Errors:
- 422: 请求参数无效
- 429: 请求过于频繁
GET /auth/users
按邮箱查询用户(需要认证)。
Query Parameters:
email: string (required)
Response: 200 OK
{
"id": "string",
"email": "string",
"created_at": "string (ISO 8601)",
"email_confirmed_at": "string? (ISO 8601)"
}
Errors:
- 403: 无权限访问
- 404: 用户不存在
- 422: 请求参数无效
Schedule Items
POST /schedule-items
创建日历事项(需要认证)。
Request:
{
"title": "string (1-255 chars, required)",
"description": "string? (max 2000 chars)",
"start_at": "string (ISO 8601 datetime, required)",
"end_at": "string? (ISO 8601 datetime)",
"timezone": "string? (default: UTC)",
"metadata": {
"color": "#FF6B6B",
"location": "会议室A",
"notes": "记得带身份证",
"attachments": [],
"version": 1
}
}
Response: 201 Created
{
"id": "uuid",
"title": "string",
"description": "string?",
"start_at": "string",
"end_at": "string?",
"timezone": "string",
"metadata": {},
"status": "active",
"source_type": "manual",
"created_at": "string",
"updated_at": "string"
}
Errors:
- 400: end_at 早于 start_at
- 401: 未认证
- 503: 服务不可用
GET /schedule-items
按时间范围查询日历事项列表(需要认证)。
Query Parameters:
start_at: ISO 8601 date/datetime(查询范围起始)end_at: ISO 8601 date/datetime(查询范围结束)
Response: 200 OK
[
{
"id": "uuid",
"title": "string",
"start_at": "string",
"end_at": "string?",
"timezone": "string",
"status": "active"
}
]
Errors:
- 400: end_at 早于 start_at
- 401: 未认证
GET /schedule-items/{id}
获取单个日历事项详情(需要认证)。
Response: 200 OK
Errors:
- 401: 未认证
- 404: 事项不存在
PATCH /schedule-items/{id}
更新日历事项(需要认证)。
Request: 支持 title/description/start_at/end_at/timezone/metadata/status 部分更新
Response: 200 OK
Errors:
- 401: 未认证
- 404: 事项不存在
DELETE /schedule-items/{id}
删除日历事项(软删除,需要认证)。
Response: 204 No Content
Errors:
- 401: 未认证
- 404: 事项不存在
POST /schedule-items/{id}/share
分享日历事项给他人(需要认证)。
通过邮箱邀请其他用户,被邀请人将收到待办消息邀请。
Request:
{
"email": "string (required, email of user to share with)",
"permission_view": "boolean (default: true)",
"permission_edit": "boolean (default: false)",
"permission_invite": "boolean (default: false)"
}
Permission 位说明:
| 权限 | 值 | 说明 |
|---|---|---|
| view | 1 | 查看事项详情 |
| invite | 2 | 邀请其他人订阅此事项 |
| edit | 4 | 修改事项内容、管理订阅 |
可组合使用,如 view+edit = 5,view+invite+edit = 7。
Response: 200 OK
{
"message": "Invitation sent to user@example.com"
}
Errors:
- 401: 未认证
- 403: 非日历所有者无权分享
- 404: 日历事项不存在或用户不存在
Inbox Messages
GET /inbox/messages
获取当前用户的待办消息列表(需要认证)。
Query Parameters:
status: string (optional) - 过滤状态:pending/accepted/rejected/dismissed
Response: 200 OK
[
{
"id": "uuid",
"recipient_id": "uuid",
"sender_id": "uuid?",
"message_type": "calendar",
"schedule_item_id": "uuid?",
"content": "string?",
"is_read": false,
"status": "pending",
"created_at": "2024-01-01T00:00:00Z"
}
]
Errors:
- 401: 未认证
POST /inbox/messages/{id}/accept
接受邀请(需要认证)。
接受日历邀请时,会为当前用户创建订阅关系。
Request:
{
"permission_view": "boolean (default: true)",
"permission_edit": "boolean (default: false)",
"permission_invite": "boolean (default: false)"
}
Response: 204 No Content
Errors:
- 401: 未认证
- 404: 消息不存在
- 400: 消息不是待处理状态或不是日历类型邀请
POST /inbox/messages/{id}/dismiss
忽略邀请(需要认证)。
Response: 204 No Content
Errors:
- 401: 未认证
- 404: 消息不存在
- 400: 消息不是待处理状态
Users
GET /users/me
获取当前用户信息(需要认证)。
Response: 200 OK
{
"id": "string",
"username": "string",
"avatar_url": "string?",
"bio": "string?"
}
Errors:
- 401: 未认证
PATCH /users/me
更新当前用户信息(需要认证)。
Request:
{
"username": "string? (3-30 chars)",
"avatar_url": "string? (URL)",
"bio": "string? (max 200 chars)"
}
Response: 200 OK
{
"id": "string",
"username": "string",
"avatar_url": "string?",
"bio": "string?"
}
Errors:
- 401: 未认证
- 422: 请求参数无效
POST /users/search
搜索用户(需要认证)。
支持两种查询模式:
- 用户名查询:模糊匹配,返回最多 20 个结果
- 邮箱查询:精确匹配,返回 0 或 1 个结果
查询类型自动识别:包含 @ 符号视为邮箱查询。
Request:
{
"query": "string (1-100 chars)"
}
Response: 200 OK
[
{
"id": "string",
"username": "string",
"avatar_url": "string?",
"bio": "string?"
}
]
Errors:
- 401: 未认证
- 503: Auth 服务不可用(仅邮箱查询)
- 422: 请求参数无效
Friends
POST /friends/requests
发送好友请求(需要认证)。
Request:
{
"target_user_id": "string (uuid)",
"content": "string? (max 500 chars)"
}
Response: 201 Created
{
"id": "uuid",
"from_user_id": "uuid",
"to_user_id": "uuid",
"content": "string?",
"status": "pending",
"created_at": "string (ISO 8601)",
"updated_at": "string (ISO 8601)"
}
Errors:
- 400: 不能添加自己为好友
- 401: 未认证
- 404: 目标用户不存在
- 409: 已是好友或请求已存在
- 422: 请求参数无效
GET /friends/requests/inbox
获取收到的好友请求(需要认证)。
Response: 200 OK
[
{
"id": "uuid",
"from_user_id": "uuid",
"to_user_id": "uuid",
"content": "string?",
"status": "pending",
"created_at": "string (ISO 8601)",
"updated_at": "string (ISO 8601)"
}
]
Errors:
- 401: 未认证
GET /friends/requests/outgoing
获取发出的好友请求(需要认证)。
Response: 200 OK
[
{
"id": "uuid",
"from_user_id": "uuid",
"to_user_id": "uuid",
"content": "string?",
"status": "pending",
"created_at": "string (ISO 8601)",
"updated_at": "string (ISO 8601)"
}
]
Errors:
- 401: 未认证
POST /friends/requests/{id}/accept
接受好友请求(需要认证)。
Response: 200 OK
{
"id": "uuid",
"from_user_id": "uuid",
"to_user_id": "uuid",
"content": "string?",
"status": "accepted",
"created_at": "string (ISO 8601)",
"updated_at": "string (ISO 8601)"
}
Errors:
- 401: 未认证
- 404: 请求不存在
- 409: 请求已被处理
POST /friends/requests/{id}/decline
拒绝好友请求(需要认证)。
Response: 200 OK
{
"id": "uuid",
"from_user_id": "uuid",
"to_user_id": "uuid",
"content": "string?",
"status": "declined",
"created_at": "string (ISO 8601)",
"updated_at": "string (ISO 8601)"
}
Errors:
- 401: 未认证
- 404: 请求不存在
- 409: 请求已被处理
DELETE /friends/requests/{id}
取消发出的好友请求(需要认证)。
Response: 204 No Content
Errors:
- 401: 未认证
- 404: 请求不存在
GET /friends
获取好友列表(需要认证)。
Response: 200 OK
[
{
"id": "uuid",
"friend_id": "uuid",
"username": "string",
"avatar_url": "string?",
"bio": "string?",
"created_at": "string (ISO 8601)"
}
]
Errors:
- 401: 未认证
DELETE /friends/{id}
删除好友(需要认证)。
Response: 204 No Content
Errors:
- 401: 未认证
- 404: 好友关系不存在
Agent Runtime
POST /agent/runs
创建一次 Agent 异步运行任务(需要认证)。
Request:
{
"threadId": "string (UUID, required)",
"runId": "string (required)",
"parentRunId": "string? (optional)",
"state": {},
"messages": [
{
"id": "string",
"role": "user",
"content": "string | InputContent[]"
}
],
"tools": [],
"context": [],
"forwardedProps": {}
}
Response: 202 Accepted
{
"taskId": "string",
"threadId": "string",
"runId": "string",
"created": false
}
Errors:
- 401: 未认证
- 403: 非会话 owner
- 422: 请求参数无效
POST /agent/runs/{thread_id}/resume
恢复一次等待工具结果的 Agent 运行(需要认证)。
Request:
{
"threadId": "string (must match path thread_id)",
"runId": "string",
"parentRunId": "string? (optional)",
"state": {},
"messages": [
{
"id": "string",
"role": "tool",
"toolCallId": "string",
"content": "string (JSON string, AG-UI ToolMessage content)"
}
],
"tools": [],
"context": [],
"forwardedProps": {}
}
Response: 202 Accepted
{
"taskId": "string",
"threadId": "string",
"runId": "string",
"created": false
}
Errors:
- 401: 未认证
- 403: 非会话 owner
- 422: 请求参数无效
GET /agent/runs/{thread_id}/events
订阅 Agent SSE 事件流(需要认证)。
Headers:
Last-Event-ID(optional): 断点续传游标,格式^\d+-\d+$
Response: 200 OK
Content-Type: text/event-stream
id: 2-0
event: RUN_STARTED
data: {"type":"RUN_STARTED","threadId":"...","runId":"..."}
Errors:
- 401: 未认证
- 403: 非会话 owner
GET /agent/runs/{thread_id}/history
按“天”读取指定会话的历史快照(需要认证)。
Query:
before(optional,YYYY-MM-DD): 读取该日期之前的最近一天
Response: 200 OK
{
"type": "STATE_SNAPSHOT",
"threadId": "string",
"snapshot": {
"scope": "history_day",
"threadId": "string",
"day": "2026-03-07",
"hasMore": true,
"messages": []
}
}
Errors:
- 401: 未认证
- 403: 非会话 owner
GET /agent/history
读取当前用户历史快照(需要认证)。当未传 threadId 时,默认返回最近活跃会话的按天快照。
Query:
threadId(optional): 指定会话before(optional,YYYY-MM-DD): 读取该日期之前的最近一天
Response: 200 OK
{
"type": "STATE_SNAPSHOT",
"threadId": "string?",
"snapshot": {
"scope": "history_day",
"threadId": "string?",
"day": "2026-03-07",
"hasMore": false,
"messages": []
}
}
Infra
GET /infra/health
检查基础设施健康状态。
Response: 200 OK
{
"status": "healthy" | "unhealthy",
"services": {
"redis": {
"status": "healthy" | "unhealthy",
"latency_ms": 0
}
}
}
GET /health
检查服务健康状态。
Response: 200 OK
{
"status": "ok"
}
Error Response Format (RFC 7807)
所有错误响应使用 application/problem+json 格式:
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "验证码无效或已过期",
"instance": "/api/v1/auth/verify"
}
前端应优先读取 detail 字段显示给用户。