> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crewai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Agentic Generative UI

> Render your CrewAI Flow's live state as UI that updates as the agent works through multi-step tasks.

## Render the agent's live state

Some work does not fit into a single tool call. A research task, a multi-step plan, a long-running job: the interesting thing to show the user is not one result, but *progress*. Agentic generative UI renders the agent's **state** and re-renders it every time that state changes.

The pattern has two halves:

1. Your Flow writes progress into its own state as it works.
2. Your frontend reads that state with `useAgent` and paints it, re-rendering as the state streams in.

The Flow's state reaches the frontend over AG-UI without you wiring up any transport. A state snapshot is emitted automatically at each step (method) boundary of the Flow, and you can push intermediate updates during a long-running step by calling `copilotkit_emit_state` explicitly. You subclass the state to add your own fields, update them in the Flow, and read them in React.

> [!NOTE]
>
> State-driven rendering requires a **Flow** with custom state (`Flow[AgentState]`). Crews are chat-oriented and do not expose custom state this way, so with a Crew use [tool rendering](https://docs.crewai.com/edge/en/guides/frontend/tool-based-generative-ui.md) instead.

## Build a live task planner

This example builds a planner that breaks a request into about ten steps and streams them to the UI as a checklist. It assumes you already have a CrewAI server and a CopilotKit frontend wired up. If you do not, start with the [Frontend Overview](https://docs.crewai.com/edge/en/guides/frontend/overview.md).

**1. Add your own fields to the agent state**

Subclass `CopilotKitState` to declare the state your UI needs. `CopilotKitState` already carries the conversation (`messages`); you add whatever else you want to render, here a list of task steps.

```python theme={null}
from typing import List, Literal
from pydantic import BaseModel, Field
from ag_ui_crewai.sdk import CopilotKitState


class TaskStep(BaseModel):
    description: str
    status: Literal["enabled", "disabled"]


class AgentState(CopilotKitState):
    steps: List[TaskStep] = Field(default_factory=list)
```

Everything on `AgentState` is included in the state snapshot the frontend receives. A snapshot is emitted automatically at each step boundary, so writing to `self.state` is enough for the UI to pick it up between steps. To update the UI *during* a long step, emit explicitly (shown below).

**2. Write progress into state from the Flow**

Type your Flow with the custom state (`Flow[AgentState]`) and let the model fill it in. Here the LLM calls a `generate_task_steps` tool; the streamed tool call lands in the conversation and the steps become visible in state.

```python theme={null}
from crewai.flow.flow import Flow, start
from litellm import acompletion
from ag_ui_crewai.sdk import copilotkit_stream

GENERATE_TASK_STEPS_TOOL = {
    "type": "function",
    "function": {
        "name": "generate_task_steps",
        "description": "Break a task into about 10 short imperative steps.",
        "parameters": {
            "type": "object",
            "properties": {
                "steps": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "description": {"type": "string"},
                            "status": {"type": "string", "enum": ["enabled"]},
                        },
                        "required": ["description", "status"],
                    },
                },
            },
            "required": ["steps"],
        },
    },
}


class TaskPlannerFlow(Flow[AgentState]):
    @start()
    async def chat(self):
        response = await copilotkit_stream(
            await acompletion(
                model="openai/gpt-4o",
                messages=[
                    {"role": "system", "content": "Plan the task the user asks for."},
                    *self.state.messages,
                ],
                tools=[GENERATE_TASK_STEPS_TOOL],
                parallel_tool_calls=False,
                stream=True,
            )
        )
        message = response.choices[0].message
        self.state.messages.append(message)
```

Wrapping the LLM call in `copilotkit_stream` streams the assistant's tokens and tool call to the frontend as they are produced. The `steps` you write to `self.state` are sent in the state snapshot emitted at the end of this step.

**3. Stream progress during a long step (optional)**

The automatic snapshot fires at step boundaries. If a single step does substantial work and you want the checklist to fill in *as it happens*, emit intermediate state yourself with `copilotkit_emit_state`. Each call pushes the current state to the frontend immediately.

```python theme={null}
from ag_ui_crewai.sdk import copilotkit_emit_state

class TaskPlannerFlow(Flow[AgentState]):
    @start()
    async def execute(self):
        for step in self.state.steps:
            step.status = "disabled"          # mark done as you go
            await copilotkit_emit_state(self.state)   # push update now
            await do_work(step)
```

Import `copilotkit_emit_state` from `ag_ui_crewai.sdk`. It requires the CopilotKit SDK (`pip install "copilotkit[crewai]"`). Reach for it only when a step is long enough that waiting for its boundary snapshot would feel unresponsive.

**4. Serve the Flow over AG-UI**

Register the Flow exactly as any other, on its own path:

```python theme={null}
# server.py
from fastapi import FastAPI
from ag_ui_crewai.endpoint import add_crewai_flow_fastapi_endpoint
from my_agents.task_planner import TaskPlannerFlow

app = FastAPI(title="CrewAI Agent Server")

add_crewai_flow_fastapi_endpoint(
    app=app,
    flow=TaskPlannerFlow(),
    path="/task_planner",
)
```

See the [Frontend Overview](https://docs.crewai.com/edge/en/guides/frontend/overview.md) for the full server, runtime, and provider setup, and remember to register the agent (here `task_planner`) in your CopilotKit runtime route.

**5. Read the live state in React**

On the frontend, `useAgent` gives you the agent's live state. Subscribe to state changes so your component re-renders every time the Flow writes an update.

```tsx theme={null}
"use client";
import { useAgent, UseAgentUpdate } from "@copilotkit/react-core/v2";

function TaskPlan() {
  const { agent } = useAgent({
    agentId: "task_planner",
    updates: [UseAgentUpdate.OnStateChanged],
  });

  const steps = agent?.state?.steps ?? [];

  return (
    <ul>
      {steps.map((s, i) => (
        <li key={i}>{s.description}</li>
      ))}
    </ul>
  );
}
```

`useAgent` returns `{ agent }`. A few things to know:

* `agent.state` is the live Flow state. Its shape matches the fields you added to `AgentState`, so `agent.state.steps` is your list of task steps.
* `agent.isRunning` tells you when the agent is actively working, useful for showing a spinner or disabling input.
* `updates: [UseAgentUpdate.OnStateChanged]` re-renders the component whenever state changes, so the checklist fills in as the Flow streams its steps.

## Where this goes next

Reading state is the foundation. Two guides build directly on it:

* [Shared State](https://docs.crewai.com/edge/en/guides/frontend/shared-state.md) adds the other direction: editing the agent's state from the UI and having the Flow pick up the change.
* [Predictive State](https://docs.crewai.com/edge/en/guides/frontend/predictive-state-updates.md) streams a tool's in-progress arguments into state so the UI reflects work before it is committed.

## Related

> **[Shared State](https://docs.crewai.com/edge/en/guides/frontend/shared-state.md)**
>
> Sync agent state and app UI in both directions.

> **[Predictive State](https://docs.crewai.com/edge/en/guides/frontend/predictive-state-updates.md)**
>
> Stream in-progress tool arguments into state.

> **[Tool-Based Generative UI](https://docs.crewai.com/edge/en/guides/frontend/tool-based-generative-ui.md)**
>
> Map agent tool calls to components.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.