240 lines
4.9 KiB
Markdown
240 lines
4.9 KiB
Markdown
|
|
# Agent Runs Events and History Route Protocol
|
||
|
|
|
||
|
|
> **NOTE**: This document is the single source of truth for agent runs event streaming and history snapshot routes.
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Defines the transport format for:
|
||
|
|
|
||
|
|
- `POST /api/v1/agent/runs`
|
||
|
|
- `GET /api/v1/agent/runs/{thread_id}/events`
|
||
|
|
- `GET /api/v1/agent/history`
|
||
|
|
- `GET /api/v1/agent/attachments/signed-url`
|
||
|
|
|
||
|
|
## Version
|
||
|
|
|
||
|
|
- **Current**: `1.0`
|
||
|
|
- **Status**: Draft (pending full backend/frontend alignment)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Route Semantics
|
||
|
|
|
||
|
|
### `GET /api/v1/agent/history`
|
||
|
|
|
||
|
|
- Unified history endpoint.
|
||
|
|
- Query params:
|
||
|
|
- `threadId` (optional): target thread id.
|
||
|
|
- `before` (optional, `YYYY-MM-DD`): paginate by day.
|
||
|
|
- Behavior:
|
||
|
|
- With `threadId`: returns that thread's day snapshot.
|
||
|
|
- Without `threadId`: returns latest available thread snapshot for current user.
|
||
|
|
|
||
|
|
### `GET /api/v1/agent/attachments/signed-url`
|
||
|
|
|
||
|
|
- Generate temporary signed URL for attachment rendering.
|
||
|
|
- Query params:
|
||
|
|
- `bucket` (required)
|
||
|
|
- `path` (required)
|
||
|
|
- Scope rule:
|
||
|
|
- `bucket` must match current storage bucket.
|
||
|
|
- `path` must be within current user prefix `agent-inputs/{user_id}/`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## SSE Envelope (`/events`)
|
||
|
|
|
||
|
|
`GET /api/v1/agent/runs/{thread_id}/events` uses `text/event-stream`.
|
||
|
|
|
||
|
|
Each SSE frame format:
|
||
|
|
|
||
|
|
```text
|
||
|
|
id: <stream-id>
|
||
|
|
event: <EVENT_TYPE>
|
||
|
|
data: <JSON payload>
|
||
|
|
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Event Type Set
|
||
|
|
|
||
|
|
- `RUN_STARTED`
|
||
|
|
- `STEP_STARTED`
|
||
|
|
- `STEP_FINISHED`
|
||
|
|
- `TEXT_MESSAGE_START`
|
||
|
|
- `TEXT_MESSAGE_CONTENT`
|
||
|
|
- `TEXT_MESSAGE_END`
|
||
|
|
- `TOOL_CALL_RESULT`
|
||
|
|
- `RUN_FINISHED`
|
||
|
|
- `RUN_ERROR`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Common Event Fields
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface EventBase {
|
||
|
|
type: string;
|
||
|
|
threadId: string;
|
||
|
|
runId?: string;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Event Payload Schemas
|
||
|
|
|
||
|
|
### Run Lifecycle
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface RunStartedEvent extends EventBase {
|
||
|
|
type: "RUN_STARTED";
|
||
|
|
runId: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
interface RunFinishedEvent extends EventBase {
|
||
|
|
type: "RUN_FINISHED";
|
||
|
|
runId: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
interface RunErrorEvent extends EventBase {
|
||
|
|
type: "RUN_ERROR";
|
||
|
|
runId: string;
|
||
|
|
message: string;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step Lifecycle
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface StepStartedEvent extends EventBase {
|
||
|
|
type: "STEP_STARTED";
|
||
|
|
runId: string;
|
||
|
|
stepName: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
interface StepFinishedEvent extends EventBase {
|
||
|
|
type: "STEP_FINISHED";
|
||
|
|
runId: string;
|
||
|
|
stepName: string;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Text Streaming
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface TextMessageStartEvent extends EventBase {
|
||
|
|
type: "TEXT_MESSAGE_START";
|
||
|
|
runId: string;
|
||
|
|
messageId: string;
|
||
|
|
role: "assistant" | "system" | "user" | "tool";
|
||
|
|
stage?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
interface TextMessageContentEvent extends EventBase {
|
||
|
|
type: "TEXT_MESSAGE_CONTENT";
|
||
|
|
runId: string;
|
||
|
|
messageId: string;
|
||
|
|
delta: string; // incremental text chunk
|
||
|
|
}
|
||
|
|
|
||
|
|
interface TextMessageEndEvent extends EventBase {
|
||
|
|
type: "TEXT_MESSAGE_END";
|
||
|
|
runId: string;
|
||
|
|
messageId: string;
|
||
|
|
workerAgentOutput: WorkerAgentOutput;
|
||
|
|
// stage/model are intentionally excluded from this event
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Tool Result
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface ToolCallResultEvent extends EventBase {
|
||
|
|
type: "TOOL_CALL_RESULT";
|
||
|
|
messageId: string;
|
||
|
|
toolCallId: string;
|
||
|
|
toolAgentOutput: ToolAgentOutput; // required
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Worker/Tool Payloads
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface WorkerAgentOutput {
|
||
|
|
status: "success" | "partial_success" | "failed";
|
||
|
|
answer: string;
|
||
|
|
key_points?: string[];
|
||
|
|
result_type?: string;
|
||
|
|
suggested_actions?: string[];
|
||
|
|
error?: {
|
||
|
|
code: string;
|
||
|
|
message: string;
|
||
|
|
retryable?: boolean;
|
||
|
|
details?: Record<string, unknown>;
|
||
|
|
};
|
||
|
|
ui_hints?: Record<string, unknown>;
|
||
|
|
}
|
||
|
|
|
||
|
|
interface ToolAgentOutput {
|
||
|
|
tool_name: string;
|
||
|
|
tool_call_id: string;
|
||
|
|
tool_call_args?: Record<string, unknown>;
|
||
|
|
status: "success" | "partial" | "failure";
|
||
|
|
result_summary: string;
|
||
|
|
ui_hints?: Record<string, unknown>;
|
||
|
|
error?: {
|
||
|
|
code: string;
|
||
|
|
message: string;
|
||
|
|
retryable?: boolean;
|
||
|
|
details?: Record<string, unknown>;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## History Response Schema
|
||
|
|
|
||
|
|
`GET /api/v1/agent/history` returns `STATE_SNAPSHOT` payload.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface AgentHistoryResponse {
|
||
|
|
type: "STATE_SNAPSHOT";
|
||
|
|
threadId?: string;
|
||
|
|
snapshot: {
|
||
|
|
scope: "history_day";
|
||
|
|
threadId: string | null;
|
||
|
|
day: string | null; // YYYY-MM-DD
|
||
|
|
hasMore: boolean;
|
||
|
|
messages: SnapshotMessage[];
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
interface SnapshotMessage {
|
||
|
|
id: string;
|
||
|
|
seq: number;
|
||
|
|
role: "user" | "assistant" | "system" | "tool";
|
||
|
|
content: string;
|
||
|
|
metadata?: Record<string, unknown>;
|
||
|
|
timestamp: string; // ISO-8601
|
||
|
|
}
|
||
|
|
|
||
|
|
interface AttachmentSignedUrlResponse {
|
||
|
|
bucket: string;
|
||
|
|
path: string;
|
||
|
|
url: string;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Compatibility Notes
|
||
|
|
|
||
|
|
- For `TOOL_CALL_RESULT`, clients should treat `toolAgentOutput` as canonical payload.
|
||
|
|
- `TEXT_MESSAGE_CONTENT.delta` is defined as incremental text chunk. Implementations should emit multiple chunks for real streaming UX.
|
||
|
|
- `TEXT_MESSAGE_END` must not include `stage` or `model` in this protocol version.
|
||
|
|
- History snapshot `messages[]` strictly follows `backend/src/schemas/messages/chat_message.py` `AgentChatMessage` schema.
|
||
|
|
- Attachment URL rendering is decoupled from history; client should call `/api/v1/agent/attachments/signed-url` using metadata fields.
|