State Rendering
Render your agent's state with custom UI components in real-time.
Open your coding agent in your project's folder, or in an empty folder for a new app.This runs in a coding agent on your computer.
This feature (shared-state-streaming) hasn't been tagged in any Google Antigravity cell yet. Try CopilotKit's Built-in Agent, LangGraph (Python), LangGraph (TypeScript).
What is this?#
State rendering lets you build UI that reflects your agent's state in real-time. As your agent progresses through nodes and emits state updates, your frontend renders those changes, showing progress, drafts, or intermediate results.
Free course: See this pattern built end-to-end in Build Interactive Agents with Generative UI — a free DeepLearning.AI short course taught by CopilotKit's CEO covering the full Generative UI spectrum (Controlled, Declarative, and Open-Ended).
When should I use this?#
Use state rendering when you want to:
- Show real-time progress (e.g. "Researching... 2/5 complete")
- Display drafts that update as the agent works
- Build dashboards that reflect agent state
- Render structured output outside of the chat
How it works in code#
On the frontend, subscribe to the agent's state. Each time the backend forwards a fresh value, your component re-renders with the latest partial output.
On the backend, a state-streaming mapping forwards a specific tool argument
straight into a state key as it's being generated. Some frameworks provide
that as middleware; direct SDK adapters can emit STATE_SNAPSHOT events from
their streaming loop. Either way, the UI can watch the answer assemble
token-by-token rather than appearing in one burst between checkpoints.
Antigravity streams state per tool call, not per token
The Antigravity harness hands the adapter each tool call with its arguments already complete, so there is no partial argument to map into a state key while the model is still generating. Token-by-token state streaming is not available with Antigravity.
The closest pattern is a tool that writes state each time the model calls it.
experimental_set_state() streams a STATE_SNAPSHOT as the tool finishes, so a plan that
the model sends step by step, one call per update, still assembles in the UI
while the run continues.
def set_steps(steps: list[dict]) -> str:
"""Publish the current plan + step statuses. Call this every time a step
transitions (including the first enumeration of steps).
Each step has: id, title, and status ("pending", "in_progress" or
"completed").
"""
experimental_set_state({**experimental_get_state(), "steps": steps})
return f"Published {len(steps)} step(s)."