Agent Protocol
The io.Intelligence Agent Protocol is the backend contract used by frontend clients such as @interopio/ai-web and @interopio/io-assist-ng.
It starts with AG-UI for the streaming wire format, then extends that foundation with the route surface, thread APIs, frontend tool reporting rules, and passthrough conventions used by the io.Intelligence bridge stack.
How It Relates to AG-UI
AG-UI provides the core streaming primitives that the protocol keeps on the wire:
- the SSE event model
- the discriminated message roles
- tool declarations and tool calls
- run lifecycle semantics
The io.Intelligence protocol adds the pieces AG-UI does not define:
- the
/io-bridgeHTTP route surface - agent, thread, and message REST endpoints
- frontend tool result reporting routes
forwardedPropsconventions for bridge-specific metadata- conformance levels for streaming, tools, persistence, and agent discovery
In practice, AI Web does not talk to "raw AG-UI". It talks to a backend that implements this extended bridge contract.
Default Route Surface
The default API prefix is /io-bridge.
| Method | Path | Purpose |
|---|---|---|
POST | /run | Start a streaming run |
POST | /runs/:runId/tool-calls/:toolCallId/result | Submit one frontend tool result back to an active run |
GET | /agents | List available agents |
GET | /agents/:agentId | Read one agent |
POST | /threads | Create a thread |
GET | /threads | List threads |
GET | /threads/:threadId | Read one thread |
PATCH | /threads/:threadId | Update a thread |
DELETE | /threads/:threadId | Delete a thread |
GET | /threads/:threadId/messages | Read thread messages |
Backends may use a different prefix, but the route shapes stay the same.
Streaming Contract
Runs use Streamable HTTP:
- request:
POST /runwithapplication/json - response:
text/event-stream - lifecycle: one request, one SSE stream, one terminal event
The request body is a RunAgentInput-style payload with these core fields:
| Field | Required | Purpose |
|---|---|---|
threadId | Yes | Correlation identifier and, on persistent backends, the thread key |
runId | Yes | Unique run identifier |
messages | Yes | Conversation history in AG-UI message form |
tools | Yes | Tool declarations available to the model |
context | Yes | Additional context entries |
forwardedProps | No | Bridge-specific passthrough metadata |
Event Set
The current bridge contract uses this AG-UI event subset:
| Category | Events |
|---|---|
| Run lifecycle | RUN_STARTED, RUN_FINISHED, RUN_ERROR |
| Text streaming | TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT, TEXT_MESSAGE_END |
| Tool lifecycle | TOOL_CALL_START, TOOL_CALL_ARGS, TOOL_CALL_END, TOOL_CALL_RESULT |
| Step markers | STEP_STARTED, STEP_FINISHED |
Required lifecycle guarantees
RUN_STARTEDmust be first.RUN_FINISHEDorRUN_ERRORmust be last.- No events may appear after a terminal event.
- Every open text sequence must close before the stream ends.
- Every open tool call must close before the stream ends.
TEXT_MESSAGE_CONTENT.deltamust be non-empty.- Concatenated
TOOL_CALL_ARGS.deltavalues must form valid JSON.
These guarantees are what let AI Web and io.Assist NG treat different backends as one predictable streaming surface.
Message Roles
The protocol keeps AG-UI's role-based message model and uses these roles in practice:
userassistantsystemdevelopertoolactivityreasoning
Two roles are bridge-relevant extensions in day-to-day use:
activitymessages are frontend-only markers and must not be forwarded to the modelreasoningmessages may be present in history, but must not be forwarded to the model
For replayable tool history, backends must preserve:
- assistant
toolCalls - tool-message
toolCallId
Tool Execution Model
The protocol supports both frontend-executed and server-executed tools.
Frontend tools
- The backend emits
TOOL_CALL_START,TOOL_CALL_ARGS, andTOOL_CALL_END. - The frontend executes the tool locally after
TOOL_CALL_END. - The frontend submits the result with
POST /runs/:runId/tool-calls/:toolCallId/result. - The backend resolves the pending tool execution inside the same run.
- Mastra emits
TOOL_CALL_RESULTand continues reasoning with memory intact.
Server-side tools
When the backend executes the tool itself, it emits TOOL_CALL_RESULT for that toolCallId. Frontends must not execute that tool again locally.
Mixed turns
The protocol allows both models in the same turn. Frontend clients must execute only the locally owned tools they recognize and leave all visible TOOL_CALL_RESULT events to the backend stream.
forwardedProps Convention
forwardedProps exists so clients and backends can extend the run request without changing the core message schema.
Common keys in the spec and current bridge implementations include:
| Key | Purpose |
|---|---|
agentId | Select the backend agent |
resourceId | Scope authorization and thread ownership |
memoryOptions | Pass backend memory settings |
modelSettings | Optional backend-specific model overrides |
structuredOutput | Current bridge extension used for schema-constrained output |
Unknown keys should be tolerated and, when safe, passed through rather than rejected.
Conformance Levels
The specification defines four cumulative levels:
| Level | Adds |
|---|---|
| Level 1 | POST /run streaming core |
| Level 2 | Tool execution events and tool-loop behavior |
| Level 3 | Thread and message persistence routes |
| Level 4 | Agent discovery routes |
@interopio/ai-mastra-bridge is intended to implement the full contract that AI Web expects in normal use.
Who Uses This
- AI Web Overview for custom frontend integrations
- io.Assist NG Overview for the packaged Angular frontend
- AI Mastra Bridge Overview for the Mastra backend implementation
- AI Mastra Bridge Routes and Events for the Mastra-specific implementation view