Documentation
Framework
Version
Class References
Function References
Interface References
Type Alias References
Variable References

AG-UI Event Definitions

TanStack AI implements the AG-UI (Agent-User Interaction) Protocol, an open, lightweight, event-based protocol that standardizes how AI agents connect to user-facing applications.

All streaming responses in TanStack AI consist of a series of AG-UI Events - discrete JSON objects representing different stages of the conversation lifecycle. These events enable real-time updates for content generation, tool calls, thinking/reasoning, and completion signals.

Base Structure

All AG-UI events share a common base structure:

typescript
interface BaseAGUIEvent {
  type: AGUIEventType;
  timestamp: number;      // Unix timestamp in milliseconds
  model?: string;         // Model identifier (TanStack AI addition)
  rawEvent?: unknown;     // Original provider event for debugging
}
interface BaseAGUIEvent {
  type: AGUIEventType;
  timestamp: number;      // Unix timestamp in milliseconds
  model?: string;         // Model identifier (TanStack AI addition)
  rawEvent?: unknown;     // Original provider event for debugging
}

AG-UI Event Types

typescript
type AGUIEventType =
  | 'RUN_STARTED'           // Run lifecycle begins
  | 'RUN_FINISHED'          // Run completed successfully
  | 'RUN_ERROR'             // Error occurred
  | 'TEXT_MESSAGE_START'    // Text message begins
  | 'TEXT_MESSAGE_CONTENT'  // Text content streaming
  | 'TEXT_MESSAGE_END'      // Text message completes
  | 'TOOL_CALL_START'       // Tool invocation begins
  | 'TOOL_CALL_ARGS'        // Tool arguments streaming
  | 'TOOL_CALL_END'         // Tool call completes (with result)
  | 'STEP_STARTED'          // Thinking/reasoning step begins
  | 'STEP_FINISHED'         // Thinking/reasoning step completes
  | 'STATE_SNAPSHOT'        // Full state synchronization
  | 'STATE_DELTA'           // Incremental state update
  | 'CUSTOM';               // Custom extensibility events
type AGUIEventType =
  | 'RUN_STARTED'           // Run lifecycle begins
  | 'RUN_FINISHED'          // Run completed successfully
  | 'RUN_ERROR'             // Error occurred
  | 'TEXT_MESSAGE_START'    // Text message begins
  | 'TEXT_MESSAGE_CONTENT'  // Text content streaming
  | 'TEXT_MESSAGE_END'      // Text message completes
  | 'TOOL_CALL_START'       // Tool invocation begins
  | 'TOOL_CALL_ARGS'        // Tool arguments streaming
  | 'TOOL_CALL_END'         // Tool call completes (with result)
  | 'STEP_STARTED'          // Thinking/reasoning step begins
  | 'STEP_FINISHED'         // Thinking/reasoning step completes
  | 'STATE_SNAPSHOT'        // Full state synchronization
  | 'STATE_DELTA'           // Incremental state update
  | 'CUSTOM';               // Custom extensibility events

Only AG-UI event types are supported; previous legacy chunk formats are no longer accepted.

AG-UI Event Definitions

RUN_STARTED

Emitted when a run begins. This is the first event in any streaming response.

typescript
interface RunStartedEvent extends BaseAGUIEvent {
  type: 'RUN_STARTED';
  runId: string;           // Unique identifier for this run
  threadId?: string;       // Optional thread/conversation ID
}
interface RunStartedEvent extends BaseAGUIEvent {
  type: 'RUN_STARTED';
  runId: string;           // Unique identifier for this run
  threadId?: string;       // Optional thread/conversation ID
}

Example:

json
{
  "type": "RUN_STARTED",
  "runId": "run_abc123",
  "model": "gpt-4o",
  "timestamp": 1701234567890
}
{
  "type": "RUN_STARTED",
  "runId": "run_abc123",
  "model": "gpt-4o",
  "timestamp": 1701234567890
}

RUN_FINISHED

Emitted when a run completes successfully.

typescript
interface RunFinishedEvent extends BaseAGUIEvent {
  type: 'RUN_FINISHED';
  runId: string;
  finishReason: 'stop' | 'length' | 'content_filter' | 'tool_calls' | null;
  usage?: {
    promptTokens: number;
    completionTokens: number;
    totalTokens: number;
  };
}
interface RunFinishedEvent extends BaseAGUIEvent {
  type: 'RUN_FINISHED';
  runId: string;
  finishReason: 'stop' | 'length' | 'content_filter' | 'tool_calls' | null;
  usage?: {
    promptTokens: number;
    completionTokens: number;
    totalTokens: number;
  };
}

Example:

json
{
  "type": "RUN_FINISHED",
  "runId": "run_abc123",
  "model": "gpt-4o",
  "timestamp": 1701234567900,
  "finishReason": "stop",
  "usage": {
    "promptTokens": 100,
    "completionTokens": 50,
    "totalTokens": 150
  }
}
{
  "type": "RUN_FINISHED",
  "runId": "run_abc123",
  "model": "gpt-4o",
  "timestamp": 1701234567900,
  "finishReason": "stop",
  "usage": {
    "promptTokens": 100,
    "completionTokens": 50,
    "totalTokens": 150
  }
}

RUN_ERROR

Emitted when an error occurs during a run.

typescript
interface RunErrorEvent extends BaseAGUIEvent {
  type: 'RUN_ERROR';
  runId?: string;
  error: {
    message: string;
    code?: string;
  };
}
interface RunErrorEvent extends BaseAGUIEvent {
  type: 'RUN_ERROR';
  runId?: string;
  error: {
    message: string;
    code?: string;
  };
}

Example:

json
{
  "type": "RUN_ERROR",
  "runId": "run_abc123",
  "model": "gpt-4o",
  "timestamp": 1701234567890,
  "error": {
    "message": "Rate limit exceeded",
    "code": "rate_limit"
  }
}
{
  "type": "RUN_ERROR",
  "runId": "run_abc123",
  "model": "gpt-4o",
  "timestamp": 1701234567890,
  "error": {
    "message": "Rate limit exceeded",
    "code": "rate_limit"
  }
}

TEXT_MESSAGE_START

Emitted when a text message starts.

typescript
interface TextMessageStartEvent extends BaseAGUIEvent {
  type: 'TEXT_MESSAGE_START';
  messageId: string;
  role: 'assistant';
}
interface TextMessageStartEvent extends BaseAGUIEvent {
  type: 'TEXT_MESSAGE_START';
  messageId: string;
  role: 'assistant';
}

TEXT_MESSAGE_CONTENT

Emitted when text content is generated (streaming tokens).

typescript
interface TextMessageContentEvent extends BaseAGUIEvent {
  type: 'TEXT_MESSAGE_CONTENT';
  messageId: string;
  delta: string;       // The incremental content token
  content?: string;    // Full accumulated content so far
}
interface TextMessageContentEvent extends BaseAGUIEvent {
  type: 'TEXT_MESSAGE_CONTENT';
  messageId: string;
  delta: string;       // The incremental content token
  content?: string;    // Full accumulated content so far
}

Example:

json
{
  "type": "TEXT_MESSAGE_CONTENT",
  "messageId": "msg_abc123",
  "model": "gpt-4o",
  "timestamp": 1701234567890,
  "delta": "Hello",
  "content": "Hello"
}
{
  "type": "TEXT_MESSAGE_CONTENT",
  "messageId": "msg_abc123",
  "model": "gpt-4o",
  "timestamp": 1701234567890,
  "delta": "Hello",
  "content": "Hello"
}

TEXT_MESSAGE_END

Emitted when a text message completes.

typescript
interface TextMessageEndEvent extends BaseAGUIEvent {
  type: 'TEXT_MESSAGE_END';
  messageId: string;
}
interface TextMessageEndEvent extends BaseAGUIEvent {
  type: 'TEXT_MESSAGE_END';
  messageId: string;
}

TOOL_CALL_START

Emitted when a tool call starts.

typescript
interface ToolCallStartEvent extends BaseAGUIEvent {
  type: 'TOOL_CALL_START';
  toolCallId: string;
  toolName: string;
  index?: number;      // Index for parallel tool calls
}
interface ToolCallStartEvent extends BaseAGUIEvent {
  type: 'TOOL_CALL_START';
  toolCallId: string;
  toolName: string;
  index?: number;      // Index for parallel tool calls
}

TOOL_CALL_ARGS

Emitted when tool call arguments are streaming.

typescript
interface ToolCallArgsEvent extends BaseAGUIEvent {
  type: 'TOOL_CALL_ARGS';
  toolCallId: string;
  delta: string;       // Incremental JSON arguments delta
  args?: string;       // Full accumulated arguments so far
}
interface ToolCallArgsEvent extends BaseAGUIEvent {
  type: 'TOOL_CALL_ARGS';
  toolCallId: string;
  delta: string;       // Incremental JSON arguments delta
  args?: string;       // Full accumulated arguments so far
}

TOOL_CALL_END

Emitted when a tool call completes.

typescript
interface ToolCallEndEvent extends BaseAGUIEvent {
  type: 'TOOL_CALL_END';
  toolCallId: string;
  toolName: string;
  input?: unknown;     // Final parsed input arguments
  result?: string;     // Tool execution result (if executed)
}
interface ToolCallEndEvent extends BaseAGUIEvent {
  type: 'TOOL_CALL_END';
  toolCallId: string;
  toolName: string;
  input?: unknown;     // Final parsed input arguments
  result?: string;     // Tool execution result (if executed)
}

STEP_STARTED

Emitted when a thinking/reasoning step starts.

typescript
interface StepStartedEvent extends BaseAGUIEvent {
  type: 'STEP_STARTED';
  stepId: string;
  stepType?: string;   // e.g., 'thinking', 'planning'
}
interface StepStartedEvent extends BaseAGUIEvent {
  type: 'STEP_STARTED';
  stepId: string;
  stepType?: string;   // e.g., 'thinking', 'planning'
}

STEP_FINISHED

Emitted when a thinking/reasoning step finishes.

typescript
interface StepFinishedEvent extends BaseAGUIEvent {
  type: 'STEP_FINISHED';
  stepId: string;
  delta?: string;      // Incremental thinking content
  content?: string;    // Full accumulated thinking content
}
interface StepFinishedEvent extends BaseAGUIEvent {
  type: 'STEP_FINISHED';
  stepId: string;
  delta?: string;      // Incremental thinking content
  content?: string;    // Full accumulated thinking content
}

Chunk Ordering and Relationships

Typical Flow

  1. Content Generation:

    RUN_STARTED
    TEXT_MESSAGE_START
    TEXT_MESSAGE_CONTENT (delta: "Hello")
    TEXT_MESSAGE_CONTENT (delta: " world")
    TEXT_MESSAGE_CONTENT (delta: "!")
    TEXT_MESSAGE_END
    RUN_FINISHED (finishReason: "stop")
    
    RUN_STARTED
    TEXT_MESSAGE_START
    TEXT_MESSAGE_CONTENT (delta: "Hello")
    TEXT_MESSAGE_CONTENT (delta: " world")
    TEXT_MESSAGE_CONTENT (delta: "!")
    TEXT_MESSAGE_END
    RUN_FINISHED (finishReason: "stop")
    
  2. With Thinking:

    RUN_STARTED
    STEP_STARTED (stepType: "thinking")
    STEP_FINISHED (delta: "I need to...")
    STEP_FINISHED (delta: " check the weather")
    TEXT_MESSAGE_START
    TEXT_MESSAGE_CONTENT (delta: "Let me check")
    TEXT_MESSAGE_END
    RUN_FINISHED (finishReason: "stop")
    
    RUN_STARTED
    STEP_STARTED (stepType: "thinking")
    STEP_FINISHED (delta: "I need to...")
    STEP_FINISHED (delta: " check the weather")
    TEXT_MESSAGE_START
    TEXT_MESSAGE_CONTENT (delta: "Let me check")
    TEXT_MESSAGE_END
    RUN_FINISHED (finishReason: "stop")
    
  3. Tool Usage:

    RUN_STARTED
    TOOL_CALL_START (name: "get_weather")
    TOOL_CALL_ARGS / TOOL_CALL_END (result: "{...}")
    TEXT_MESSAGE_START
    TEXT_MESSAGE_CONTENT (delta: "The weather is...")
    TEXT_MESSAGE_END
    RUN_FINISHED (finishReason: "stop")
    
    RUN_STARTED
    TOOL_CALL_START (name: "get_weather")
    TOOL_CALL_ARGS / TOOL_CALL_END (result: "{...}")
    TEXT_MESSAGE_START
    TEXT_MESSAGE_CONTENT (delta: "The weather is...")
    TEXT_MESSAGE_END
    RUN_FINISHED (finishReason: "stop")
    
  4. Client Tool with Approval:

    RUN_STARTED
    TOOL_CALL_START (name: "send_email")
    TOOL_CALL_ARGS / TOOL_CALL_END
    CUSTOM (name: "approval-requested")
    [User approves]
    [Client executes]
    TEXT_MESSAGE_START
    TEXT_MESSAGE_CONTENT (delta: "Email sent successfully")
    TEXT_MESSAGE_END
    RUN_FINISHED (finishReason: "stop")
    
    RUN_STARTED
    TOOL_CALL_START (name: "send_email")
    TOOL_CALL_ARGS / TOOL_CALL_END
    CUSTOM (name: "approval-requested")
    [User approves]
    [Client executes]
    TEXT_MESSAGE_START
    TEXT_MESSAGE_CONTENT (delta: "Email sent successfully")
    TEXT_MESSAGE_END
    RUN_FINISHED (finishReason: "stop")
    

Multiple Tool Calls

When the model calls multiple tools in parallel:

RUN_STARTED
TOOL_CALL_START (index: 0, name: "get_weather")
TOOL_CALL_START (index: 1, name: "get_time")
TOOL_CALL_END (toolCallId: "call_1", result: "...")
TOOL_CALL_END (toolCallId: "call_2", result: "...")
TEXT_MESSAGE_START
TEXT_MESSAGE_CONTENT (delta: "Based on the data...")
TEXT_MESSAGE_END
RUN_FINISHED (finishReason: "stop")
RUN_STARTED
TOOL_CALL_START (index: 0, name: "get_weather")
TOOL_CALL_START (index: 1, name: "get_time")
TOOL_CALL_END (toolCallId: "call_1", result: "...")
TOOL_CALL_END (toolCallId: "call_2", result: "...")
TEXT_MESSAGE_START
TEXT_MESSAGE_CONTENT (delta: "Based on the data...")
TEXT_MESSAGE_END
RUN_FINISHED (finishReason: "stop")

TypeScript Union Type

All chunks are represented as the AG-UI event union (StreamChunk = AGUIEvent):

typescript
type StreamChunk =
  | RunStartedEvent
  | RunFinishedEvent
  | RunErrorEvent
  | TextMessageStartEvent
  | TextMessageContentEvent
  | TextMessageEndEvent
  | ToolCallStartEvent
  | ToolCallArgsEvent
  | ToolCallEndEvent
  | StepStartedEvent
  | StepFinishedEvent
  | StateSnapshotEvent
  | StateDeltaEvent
  | CustomEvent;
type StreamChunk =
  | RunStartedEvent
  | RunFinishedEvent
  | RunErrorEvent
  | TextMessageStartEvent
  | TextMessageContentEvent
  | TextMessageEndEvent
  | ToolCallStartEvent
  | ToolCallArgsEvent
  | ToolCallEndEvent
  | StepStartedEvent
  | StepFinishedEvent
  | StateSnapshotEvent
  | StateDeltaEvent
  | CustomEvent;

This enables type-safe handling in TypeScript:

typescript
function handleChunk(chunk: StreamChunk) {
  switch (chunk.type) {
    case 'TEXT_MESSAGE_CONTENT':
      console.log(chunk.delta);
      break;
    case 'STEP_FINISHED':
      console.log(chunk.content);
      break;
    case 'TOOL_CALL_START':
      console.log(chunk.toolName);
      break;
    // ... other cases
  }
}
function handleChunk(chunk: StreamChunk) {
  switch (chunk.type) {
    case 'TEXT_MESSAGE_CONTENT':
      console.log(chunk.delta);
      break;
    case 'STEP_FINISHED':
      console.log(chunk.content);
      break;
    case 'TOOL_CALL_START':
      console.log(chunk.toolName);
      break;
    // ... other cases
  }
}

See Also