SSE Event Contract: Slack Bot ↔ Dynamic Agents
Date: 2026-04-14 Protocol: AG-UI over SSE Direction: Dynamic Agents (server) → Slack Bot (client)
Transport
- Method:
POSTwithAccept: text/event-stream - Content-Type:
text/event-stream(response) - Encoding: UTF-8
- Frame format:
event: <TYPE>\ndata: <JSON>\n\n
Endpoints
Start Stream
POST /api/v1/chat/stream/start?protocol=agui
Content-Type: application/json
Authorization: Bearer <jwt> (when AUTH_ENABLED=true)
X-Client-Source: slack-bot
{
"message": "string",
"conversation_id": "uuid-string",
"agent_id": "string",
"trace_id": "string | null"
}
Response: SSE stream with events listed below.
Error responses:
404: Agent not found ({"detail": "Agent configuration not found"})403: Access denied ({"detail": "Access denied to agent"})
Resume Stream (after HITL)
POST /api/v1/chat/stream/resume?protocol=agui
Content-Type: application/json
Authorization: Bearer <jwt>
{
"agent_id": "string",
"conversation_id": "string",
"form_data": "json-string-or-rejection-text",
"trace_id": "string | null"
}
Response: Same SSE stream format as Start Stream.
Invoke (Non-Streaming)
POST /api/v1/chat/invoke
Content-Type: application/json
Authorization: Bearer <jwt>
{
"message": "string",
"conversation_id": "uuid-string",
"agent_id": "string",
"trace_id": "string | null"
}
Response (JSON):
{
"success": true,
"content": "agent response text",
"agent_id": "string",
"conversation_id": "string",
"trace_id": "string | null"
}
Error response (JSON):
{
"success": false,
"error": "error description",
"agent_id": "string",
"conversation_id": "string",
"trace_id": "string | null"
}
Health Check
GET /healthz
Response: 200 OK with health status JSON.
SSE Event Types
RUN_STARTED
Emitted once at the beginning of every stream.
{
"type": "RUN_STARTED",
"runId": "uuid-string",
"threadId": "uuid-string",
"timestamp": 1713100000.0
}
TEXT_MESSAGE_START
Emitted when the first content chunk arrives for a message.
{
"type": "TEXT_MESSAGE_START",
"messageId": "msg-uuid",
"role": "assistant",
"timestamp": 1713100001.0
}
TEXT_MESSAGE_CONTENT
Emitted for each text token.
{
"type": "TEXT_MESSAGE_CONTENT",
"messageId": "msg-uuid",
"delta": "text chunk",
"timestamp": 1713100001.1
}
TEXT_MESSAGE_END
Emitted at the end of a text message sequence.
{
"type": "TEXT_MESSAGE_END",
"messageId": "msg-uuid",
"timestamp": 1713100002.0
}
TOOL_CALL_START
Emitted when an AI message contains tool calls.
{
"type": "TOOL_CALL_START",
"toolCallId": "call-uuid",
"toolCallName": "search_jira",
"timestamp": 1713100003.0
}
TOOL_CALL_ARGS
Emitted immediately after TOOL_CALL_START with truncated arguments.
{
"type": "TOOL_CALL_ARGS",
"toolCallId": "call-uuid",
"delta": "{\"query\": \"OOM issues\"}",
"timestamp": 1713100003.1
}
TOOL_CALL_END
Emitted when a tool result (ToolMessage) arrives.
{
"type": "TOOL_CALL_END",
"toolCallId": "call-uuid",
"timestamp": 1713100004.0
}
RUN_FINISHED (success)
Emitted when the stream completes successfully.
{
"type": "RUN_FINISHED",
"runId": "uuid-string",
"threadId": "uuid-string",
"outcome": "success",
"timestamp": 1713100005.0
}
RUN_FINISHED (interrupt — HITL)
Emitted when the agent requests human input. Mutually exclusive with the success variant.
{
"type": "RUN_FINISHED",
"runId": "uuid-string",
"threadId": "uuid-string",
"outcome": "interrupt",
"interrupt": {
"id": "interrupt-uuid",
"reason": "human_input",
"payload": {
"prompt": "Please confirm the Jira ticket details",
"fields": [
{
"field_name": "summary",
"field_label": "Ticket Summary",
"field_type": "text",
"required": true,
"default_value": "OOM issue in production"
},
{
"field_name": "priority",
"field_label": "Priority",
"field_type": "select",
"field_values": ["Critical", "High", "Medium", "Low"],
"required": true
},
{
"field_name": "approval",
"field_label": "Approve creation?",
"field_type": "boolean",
"required": true
}
],
"agent": "platform-engineer"
}
},
"timestamp": 1713100005.0
}
RUN_ERROR
Emitted on unrecoverable error.
{
"type": "RUN_ERROR",
"message": "Agent runtime error: model rate limited",
"code": "RATE_LIMITED",
"timestamp": 1713100005.0
}
CUSTOM (WARNING)
Non-fatal warning.
{
"type": "CUSTOM",
"name": "WARNING",
"value": {
"message": "MCP server argocd is unavailable",
"namespace": []
},
"timestamp": 1713100002.0
}
CUSTOM (NAMESPACE_CONTEXT)
Emitted before subagent events to identify the source agent.
{
"type": "CUSTOM",
"name": "NAMESPACE_CONTEXT",
"value": {
"namespace": ["jira-agent"]
},
"timestamp": 1713100002.0
}
CUSTOM (TOOL_ERROR)
Emitted when a tool returns an error result.
{
"type": "CUSTOM",
"name": "TOOL_ERROR",
"value": {
"tool_call_id": "call-uuid",
"error": "Connection refused: argocd server unavailable"
},
"timestamp": 1713100004.0
}
Event Ordering
A typical successful stream:
RUN_STARTED
[CUSTOM NAMESPACE_CONTEXT]? # If subagent
TEXT_MESSAGE_START
TEXT_MESSAGE_CONTENT (×N)
TEXT_MESSAGE_END
[TOOL_CALL_START # If tools used
TOOL_CALL_ARGS
TOOL_CALL_END]*
[TEXT_MESSAGE_START # Response after tool
TEXT_MESSAGE_CONTENT (×N)
TEXT_MESSAGE_END]
RUN_FINISHED (outcome=success)
A HITL interrupt stream:
RUN_STARTED
TEXT_MESSAGE_START
TEXT_MESSAGE_CONTENT (×N) # Explanation before interrupt
TEXT_MESSAGE_END
RUN_FINISHED (outcome=interrupt)
An error stream:
RUN_STARTED
[partial events]?
RUN_ERROR