Files
social-app/docs/protocols/agent/run-agent-input.md
T
2026-03-19 00:52:16 +08:00

525 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Agent Run Input Protocol
> **NOTE**: This document defines the RunAgentInput data structure for `POST /api/v1/agent/runs`.
## Version
- **Current**: `1.0`
- **Status**: Active
---
## Overview
`POST /api/v1/agent/runs` accepts `RunAgentInput` as request body to initiate an agent execution.
---
## RunAgentInput Schema
```typescript
interface RunAgentInput {
threadId: string; // 必须是有效 UUID
runId: string; // 最大 128 字符
parentRunId?: string;
state?: any;
messages: Message[]; // 最多 200 条
tools?: Tool[];
context?: Context[];
forwardedProps?: any;
}
```
### Required Fields
| Field | Type | Constraints |
|-------|------|-------------|
| `threadId` | string | 必须为有效 UUID |
| `runId` | string | 最大 128 字符 |
| `messages` | array | 最多 200 条,**必须恰好包含 1 条 user message** |
| `state` | any | - |
| `tools` | array | 可选 |
| `context` | array | 可选 |
| `forwardedProps` | any | - |
---
## Message Types
### UserMessage
```typescript
interface UserMessage {
id: string;
role: "user";
content: string | ContentBlock[];
name?: string;
encryptedValue?: string;
}
type ContentBlock = TextContentBlock | BinaryContentBlock;
interface TextContentBlock {
type: "text";
text: string;
}
interface BinaryContentBlock {
type: "binary";
mimeType: string; // 必须为 image/* 类型
id?: string;
url?: string; // 必须是有效的 signed URL
data?: string; // 不允许使用 data 字段
filename?: string;
}
```
### AssistantMessage
```typescript
interface AssistantMessage {
id: string;
role: "assistant";
content?: string | null;
name?: string | null;
toolCalls?: ToolCall[];
encryptedValue?: string | null;
}
interface ToolCall {
id: string;
type: "function";
function: {
name: string;
arguments: string;
};
encryptedValue?: string | null;
}
```
### SystemMessage
```typescript
interface SystemMessage {
id: string;
role: "system";
content: string;
name?: string | null;
encryptedValue?: string | null;
}
```
### ToolMessage
```typescript
interface ToolMessage {
id: string;
role: "tool";
content: string;
toolCallId: string;
error?: string | null;
encryptedValue?: string | null;
}
```
### Other Message Types
- **DeveloperMessage**: `role: "developer"`
- **ReasoningMessage**: `role: "reasoning"`
- **ActivityMessage**: `role: "activity"` (for progress updates)
---
## Tool Schema
```typescript
interface Tool {
name: string;
description: string;
parameters: object; // JSON Schema 格式
}
```
### Example
```json
{
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
```
### Frontend Tool Channel Semantics
- `RunAgentInput.tools` 用于前端工具通道(供前端/HITL 审批链路透传与回放)。
- 当前后端 AgentScope 执行阶段**不**使用该字段来注册或筛选后端工具。
- 后端可调用工具以 `toolkit.register_tool_function(...)` 注册结果为准(例如 `calendar_write`)。
- 因此 `tools` 可为空数组,不影响后端已注册工具的调用能力。
> 注意:请勿把后端已注册工具重复写入 `RunAgentInput.tools`,避免命名/参数描述冲突。
---
## Context Schema
```typescript
interface Context {
description: string;
value: string;
}
```
---
## forwardedProps Schema(当前仅支持 client_time
`RunAgentInput.forwardedProps` 支持透传客户端时间上下文。日历相关能力必须使用以下结构:
```typescript
interface ForwardedProps {
client_time?: {
device_timezone: string; // IANA 时区,例如 "America/Los_Angeles"
client_now_iso: string; // RFC3339 带偏移时间,例如 "2026-03-16T09:12:33-07:00"
client_epoch_ms: number; // Unix epoch 毫秒
};
}
```
### 时间来源优先级(固定)
后端在运行时按以下顺序解析事件时区:
1. `event_timezone`(工具调用显式传参)
2. `forwardedProps.client_time.device_timezone`
3. `users.profile.settings.timezone`
4. `UTC`
### 约束
- `device_timezone` 必须是有效 IANA 时区。
- `client_now_iso` 必须是 RFC3339 且包含时区偏移。
- `client_epoch_ms` 必须是整数毫秒时间戳。
- `forwardedProps` 当前仅允许 `client_time`,额外字段会触发 `422 invalid RunAgentInput.forwardedProps`
- 业务代码不得使用服务器本地时区作为事件语义时区。
### 说明
- `forwardedProps` 是透传字段,不改变 AG-UI 主体协议结构。
-`forwardedProps.client_time` 缺失或非法时,运行时回退到 `users.profile.settings.timezone`
- 日历写入必须在最终工具调用中带上 `event_timezone`,不得依赖工具默认值。
---
## Validation Rules
Backend 实现了以下验证规则:
| Rule | Error Message |
|------|---------------|
| payload ≤ 256KB | `RunAgentInput payload exceeds size limit` |
| threadId 必须是 UUID | `threadId must be a valid UUID` |
| runId 最大 128 字符 | `runId exceeds length limit` |
| messages ≤ 200 条 | `RunAgentInput.messages exceeds limit` |
| user text ≤ 10,000 字符 | `RunAgentInput user message text exceeds limit` |
| **恰好 1 条 user message** | `RunAgentInput.messages must contain exactly one user message` |
| user message 必须在第一条 | `RunAgentInput.messages[0].role must be user` |
| binary 必须是 image/* | `binary content requires image mimeType` |
| binary 必须有 url | `binary content requires url` |
| binary 不允许使用 data | `binary content data is not allowed` |
| 单条消息最多 3 张附件 | `Too many attachments` |
### forwardedProps.client_time Validation
建议在后端校验层返回以下错误(按业务实现映射到 4xx):
| Rule | Error Message |
|------|---------------|
| `device_timezone` 非 IANA 时区 | `invalid client_time.device_timezone` |
| `client_now_iso` 无法解析或缺少时区 | `invalid client_time.client_now_iso` |
| `client_epoch_ms` 非整数毫秒值 | `invalid client_time.client_epoch_ms` |
---
## Request Example
### 纯文本请求
```json
{
"threadId": "550e8400-e29b-41d4-a716-446655440000",
"runId": "run-001",
"state": {},
"messages": [
{
"id": "msg-001",
"role": "user",
"content": "帮我查一下北京今天的天气"
}
],
"tools": [],
"context": [],
"forwardedProps": {}
}
```
### 多模态请求 (带图片)
```json
{
"threadId": "550e8400-e29b-41d4-a716-446655440000",
"runId": "run-002",
"state": {},
"messages": [
{
"id": "msg-001",
"role": "user",
"content": [
{
"type": "text",
"text": "这张图片里的内容是什么?"
},
{
"type": "binary",
"mimeType": "image/png",
"url": "https://storage.example.com/agent-inputs/user-123/image.png?signature=xxx"
}
]
}
],
"tools": [],
"context": [],
"forwardedProps": {}
}
```
### 带 Tools 的请求
```json
{
"threadId": "550e8400-e29b-41d4-a716-446655440000",
"runId": "run-003",
"state": {},
"messages": [
{
"id": "msg-001",
"role": "user",
"content": "北京天气怎么样?"
}
],
"tools": [
{
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
}
},
"required": ["city"]
}
}
],
"context": [],
"forwardedProps": {}
}
```
### 带 forwardedProps.client_time 的请求
```json
{
"threadId": "550e8400-e29b-41d4-a716-446655440000",
"runId": "run-004",
"state": {},
"messages": [
{
"id": "msg-001",
"role": "user",
"content": "帮我明天早上9点创建一个日历"
}
],
"tools": [],
"context": [],
"forwardedProps": {
"client_time": {
"device_timezone": "America/Los_Angeles",
"client_now_iso": "2026-03-16T09:12:33-07:00",
"client_epoch_ms": 1773658353000
}
}
}
```
---
## Response
成功响应返回 `TaskAcceptedResponse`
```typescript
interface TaskAcceptedResponse {
taskId: string;
threadId: string;
runId: string;
created: boolean; // 是否新建会话
}
```
---
## History API
`GET /api/v1/agent/history` 返回对话历史快照。
### Request
| Parameter | Type | Description |
|-----------|------|-------------|
| `threadId` | string (query) | 可选,指定会话 ID,不指定则返回最新会话 |
| `before` | string (query) | 可选,日期格式 `YYYY-MM-DD`,返回该日期之前的快照 |
### Response
返回 `HistorySnapshotResponse`
```typescript
interface HistorySnapshotResponse {
scope: "history_day";
threadId: string | null;
day: string | null; // ISO date format "YYYY-MM-DD"
hasMore: boolean;
messages: HistoryMessage[];
}
```
### HistoryMessage
根据消息 role 不同,返回字段有所差异:
```typescript
// role = "user"
interface HistoryMessageUser {
id: string;
seq: number;
role: "user";
content: string;
attachments: HistoryAttachment[];
timestamp: string; // ISO-8601 timestamp
}
interface HistoryAttachment {
mimeType: string;
url: string;
}
// role = "assistant"
interface HistoryMessageAssistant {
id: string;
seq: number;
role: "assistant";
content: string;
ui_schema: UiSchemaRenderer | null; // 由 agent_output.ui_hints 编译
timestamp: string;
}
type HistoryMessage = HistoryMessageUser | HistoryMessageAssistant;
```
### UiSchemaRenderer
编译后的 UI 渲染结构,详见 [UiSchema Protocol](../ui/ui-schema.md)
```typescript
interface UiSchemaRenderer {
version: "2.0";
locale: string;
status: "info" | "success" | "warning" | "error" | "pending";
theme: "default" | "light" | "dark";
meta?: {
requestId?: string;
toolId?: string;
traceId?: string;
userId?: string;
};
root: UiLayoutNode;
}
```
### Example
```json
{
"scope": "history_day",
"threadId": "550e8400-e29b-41d4-a716-446655440000",
"day": "2026-03-15",
"hasMore": true,
"messages": [
{
"id": "msg-001",
"seq": 1,
"role": "user",
"content": "帮我创建一个日程",
"attachments": [
{
"mimeType": "image/png",
"url": "https://project.supabase.co/storage/v1/object/sign/agent-inputs/..."
}
],
"timestamp": "2026-03-15T10:00:00Z"
},
{
"id": "msg-002",
"seq": 2,
"role": "assistant",
"content": "好的,我来帮您创建日程。",
"ui_schema": {
"version": "2.0",
"locale": "zh-CN",
"status": "success",
"theme": "default",
"root": {
"type": "stack",
"appearance": "card",
"children": [
{"type": "text", "content": "日程已创建", "role": "title"},
{"type": "badge", "label": "SUCCESS", "status": "success"},
{"type": "text", "content": "您的会议日程创建成功", "role": "body"}
]
}
},
"timestamp": "2026-03-15T10:00:05Z"
}
]
}
```
---
## Compatibility Notes
- `UserMessage.content` 支持 string 或 array 格式,前端优先使用 array 格式以支持多模态
- binary content 的 url 必须是有效的 signed URL,由 `/api/v1/agent/attachments` 端点生成
- backend 验证通过后,会将 binary url 转换为内部存储路径
- `tools` 是前端工具通道字段;当前后端运行时不基于该字段构造后端工具 prompt
- `RunAgentInput` 同时接受 camelCase 与 snake_case 别名输入(推荐统一使用 camelCase)
- 日历能力依赖 `forwardedProps.client_time` 透传设备时间上下文;缺失时回退用户 profile 时区
- `forwardedProps` 不支持业务私有控制字段(例如 `system_agent_mode`
- tool 消息在存储层用于运行时上下文续接,不在 `/history` 对外返回