Events
The use-agent hook is built on an event-driven architecture. Real-time events are streamed from the server, processed by a state reducer, and used to build the conversation UI incrementally. This document details the events, their purpose, and how you can use them.
Understanding the Event Lifecycle
Section titled “Understanding the Event Lifecycle”-
Raw Event Streaming
A raw message is received from the Inngest realtime websocket connection
-
Mapping
The raw message is passed to an internal
mapToNetworkEventfunction, which transforms it into a standardized, strongly-typedAgentKitEvent. Invalid or unrecognized messages are discarded. -
Dispatch
The valid
AgentKitEventis dispatched to the internalStreamingEngine. -
Reduction
The
streaming-reducerprocesses the event. It uses a sequencing and buffering mechanism to ensure events are applied in the correct order, even if they arrive out of order. -
State Update
The reducer applies the event to the state, creating or updating messages and their parts.
-
UI Render
Your React UI re-renders with the new state.
-
Callbacks
If configured,
onEvent,onStreamEnded, oronToolResultcallbacks are fired, allowing you to react to specific events.
Core Events Reference
Section titled “Core Events Reference”Run Lifecycle Events
Section titled “Run Lifecycle Events”These events manage the overall state of an agent or network execution for a given turn.
run.started
Section titled “run.started”- Description: Marks the beginning of an agent or network execution in response to a user message. This is often the first event in a sequence. It sets the agent’s status to
submitted. - Payload (
data):threadId: The ID of the thread this run belongs to.name: The name of the agent or network that started.scope:"network"or"agent".runId,parentRunId,messageId.
- State Impact: Sets
runActive: true,agentStatus: 'submitted', and may reset the event processing sequence if it’s the start of a new “epoch”.
run.completed
Section titled “run.completed”- Description: Indicates that an agent or network run has finished its logic. This does not mean all streaming is complete. It primarily finalizes any in-flight tool outputs.
- Payload (
data):threadId,scope,runId,messageId,name. - State Impact: Finalizes the state of any tools that were in the
executingstate, moving them tooutput-available. The overall agent status is not yet changed toready.
stream.ended
Section titled “stream.ended”- Description: The final event in a sequence. It indicates that all streaming for a turn is complete and the agent is now idle.
- Payload (
data):threadId,scope,runId,messageId,name. - State Impact: Sets
runActive: falseandagentStatus: 'ready'. This signals that the system is ready for new user input.
Content Streaming Events
Section titled “Content Streaming Events”These events are responsible for building the assistant’s response message part by part.
part.created
Section titled “part.created”- Description: Signals the creation of a new part within an assistant message.
- Payload (
data):messageId: The ID of the message this part belongs to.partId: The unique ID for this new part.type: Either"text"or"tool-call".metadata: Optional data, often includestoolNamefor tool calls.
- State Impact: Adds a new, empty
TextUIPartorToolCallUIPartto the parts array of the corresponding message.
text.delta
Section titled “text.delta”- Description: Streams a chunk of text for a
TextUIPart. - Payload (
data):messageId,partId.delta: The string of text to append.
- State Impact: Appends the
deltacontent to the specifiedTextUIPart.
part.completed
Section titled “part.completed”- Description: Marks a specific message part as complete. The payload varies based on the part type.
- Payload (
data):messageId,partId.type: Can be"text","tool-call", or"tool-output".finalContent: The complete, final content for the part (e.g., the full text or final tool output).
- State Impact:
- For
"text": Sets the part’sstatustocomplete. - For
"tool-call": Sets the tool’sstatetoinput-availableand populates the finalinput. - For
"tool-output": Sets the tool’sstatetooutput-availableand populates the finaloutput.
- For
Tool Call Events
Section titled “Tool Call Events”These events are specific to the lifecycle of tool calls made by an agent.
tool_call.arguments.delta
Section titled “tool_call.arguments.delta”- Description: Streams a chunk of the JSON arguments for a tool call.
- Payload (
data):messageId,partId.delta: A string chunk of the JSON arguments object.
- State Impact: Appends the
deltato theinputfield of theToolCallUIPart. The reducer attempts to parse the accumulating string as JSON. Sets the tool’sstatetoinput-streaming.
tool_call.output.delta
Section titled “tool_call.output.delta”- Description: Streams a chunk of the output from a tool execution.
- Payload (
data):messageId,partId.delta: A string chunk of the tool’s output.
- State Impact: Appends the
deltato theoutputfield of theToolCallUIPart. Sets the tool’sstatetoexecuting.
Consuming Events in Your App
Section titled “Consuming Events in Your App”The useAgent hook provides callbacks to tap into this event stream.
onEvent
Section titled “onEvent”This is the lowest-level callback. It fires for every single valid AgentKitEvent that the hook processes, giving you full visibility into the streaming process.
useAgent({ onEvent: (evt, meta) => { console.log('Event received:', evt.event, 'for thread:', meta.threadId); if (evt.event === 'run.started') { // Show a global "thinking" indicator } }})onToolResult
Section titled “onToolResult”A convenient, strongly-typed callback that fires only when a tool has finished executing and its final output is available (part.completed with type: "tool-output").
useAgent<MyAgentConfig>({ onToolResult: (result) => { if (result.toolName === 'getWeather') { const weatherData = result.data; // strongly typed! // Display a custom weather component } }})onStreamEnded
Section titled “onStreamEnded”Fires when the entire sequence of events for a turn is complete (stream.ended). Useful for triggering actions after the assistant has fully responded.
useAgent({ onStreamEnded: ({ threadId }) => { console.log(`Agent has finished responding in thread ${threadId}.`); // Maybe run some analytics or enable the input field }})