641d847008
- Update api-endpoints.md with new agent endpoints - Update run-agent-input.md with new input schemas - Update sse-events.md with new event types - Update ui-schema.md with schema changes
13 KiB
13 KiB
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
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
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
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
interface SystemMessage {
id: string;
role: "system";
content: string;
name?: string | null;
encryptedValue?: string | null;
}
ToolMessage
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
interface Tool {
name: string;
description: string;
parameters: object; // JSON Schema 格式
}
Example
{
"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
interface Context {
description: string;
value: string;
}
forwardedProps Schema(支持 agent_type + client_time)
RunAgentInput.forwardedProps 支持透传运行模式与客户端时间上下文。日历相关能力必须使用以下结构:
interface ForwardedProps {
agent_type: string; // 必填,运行模式(如 "worker" / "memory")
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 毫秒
};
}
时间来源优先级(固定)
后端在运行时按以下顺序解析事件时区:
event_timezone(工具调用显式传参)forwardedProps.client_time.device_timezoneusers.profile.settings.timezoneUTC
约束
device_timezone必须是有效 IANA 时区。client_now_iso必须是 RFC3339 且包含时区偏移。client_epoch_ms必须是整数毫秒时间戳。forwardedProps.agent_type必填,且必须匹配后端已注册的 agent type。agent_type=memory为自动化任务内部模式,HTTP/agent/runs入口不接受该值。forwardedProps仅允许agent_type与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 |
| forwardedProps.agent_type 必填 | invalid RunAgentInput.forwardedProps |
| 恰好 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
纯文本请求
{
"threadId": "550e8400-e29b-41d4-a716-446655440000",
"runId": "run-001",
"state": {},
"messages": [
{
"id": "msg-001",
"role": "user",
"content": "帮我查一下北京今天的天气"
}
],
"tools": [],
"context": [],
"forwardedProps": {
"agent_type": "worker"
}
}
多模态请求 (带图片)
{
"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": {
"agent_type": "worker"
}
}
带 Tools 的请求
{
"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": {
"agent_type": "worker"
}
}
带 forwardedProps.client_time 的请求
{
"threadId": "550e8400-e29b-41d4-a716-446655440000",
"runId": "run-004",
"state": {},
"messages": [
{
"id": "msg-001",
"role": "user",
"content": "帮我明天早上9点创建一个日历"
}
],
"tools": [],
"context": [],
"forwardedProps": {
"agent_type": "worker",
"client_time": {
"device_timezone": "America/Los_Angeles",
"client_now_iso": "2026-03-16T09:12:33-07:00",
"client_epoch_ms": 1773658353000
}
}
}
Response
成功响应返回 TaskAcceptedResponse:
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:
interface HistorySnapshotResponse {
scope: "history_day";
threadId: string | null;
day: string | null; // ISO date format "YYYY-MM-DD"
hasMore: boolean;
messages: HistoryMessage[];
}
HistoryMessage
根据消息 role 不同,返回字段有所差异:
// 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:
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
{
"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是前端工具通道字段;当前后端运行时不基于该字段构造后端工具 promptRunAgentInput同时接受 camelCase 与 snake_case 别名输入(推荐统一使用 camelCase)- 日历能力依赖
forwardedProps.client_time透传设备时间上下文;缺失时回退用户 profile 时区 forwardedProps.agent_type是受控路由字段,必须由调用方显式传入;后端 task 不做默认赋值- tool 消息在存储层用于运行时上下文续接,不在
/history对外返回