mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-08-29 00:58:00 +00:00
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Vulnerability Scan / Detect changes (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
* docs: add Frontend guides section (CopilotKit + AG-UI) Add a Frontend sub-group under Guides documenting how to build user interfaces for CrewAI Crews and Flows with CopilotKit over the AG-UI protocol. Pages: overview, generative UI, tool-based generative UI, agentic generative UI, human-in-the-loop, shared state, frontend actions, predictive state updates, and channels. * docs: mirror Frontend guides into v1.15.5 (Latest) Also register the Frontend sub-group and pages under the default v1.15.5 version so the section is visible without switching to Edge. * docs(frontend): address audit — correct APIs and claims - Use useRenderTool for display-only tool rendering (was useFrontendTool) - Correct state 'auto-streams' claims: snapshot at step boundaries, document copilotkit_emit_state for mid-step progress - Fix setState usage to spread full state (replace, not merge) - Add tool description to the frontend-action example - Rewrite Channels with the real @copilotkit/channels createBot API (Slack + Discord adapters); drop unsupported platform claims - Note self-hosted vs managed CopilotKit paths and pin package versions * docs(frontend): remove versions callout from overview * docs(frontend): drop package-generation framing from emit_state note * docs(frontend): add generative UI spectrum (A2UI, reasoning) + Conversational Flows Rewrite generative-ui as the controlled/declarative/open-ended spectrum; add A2UI (declarative), Reasoning (controlled), and a Conversational Flows page; add a backend-tools section to tool-based; note the three execution shapes in the overview. * docs(frontend): address review — edge-only, attribute access, safe defaults Remove the docs/v1.15.5 mirror (versioned snapshots are cut from edge by the release tooling; the docs-snapshots CI guard rejects manual docs/v* writes). Use attribute access on the LiteLLM message in shared-state, guard setState against undefined agent/recipe, and use Field(default_factory=list) for the agent-state list.
209 lines
8.0 KiB
Plaintext
209 lines
8.0 KiB
Plaintext
---
|
|
title: Agentic Generative UI
|
|
description: Render your CrewAI Flow's live state as UI that updates as the agent works through multi-step tasks.
|
|
icon: list-check
|
|
mode: "wide"
|
|
---
|
|
|
|
## 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](/en/guides/frontend/tool-based-generative-ui) instead.
|
|
</Note>
|
|
|
|
## 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](/en/guides/frontend/overview).
|
|
|
|
<Steps>
|
|
|
|
<Step title="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
|
|
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).
|
|
|
|
</Step>
|
|
|
|
<Step title="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
|
|
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.
|
|
|
|
</Step>
|
|
|
|
<Step title="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
|
|
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.
|
|
|
|
</Step>
|
|
|
|
<Step title="Serve the Flow over AG-UI">
|
|
|
|
Register the Flow exactly as any other, on its own path:
|
|
|
|
```python
|
|
# 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](/en/guides/frontend/overview) for the full server, runtime, and provider setup, and remember to register the agent (here `task_planner`) in your CopilotKit runtime route.
|
|
|
|
</Step>
|
|
|
|
<Step title="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
|
|
"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.
|
|
|
|
</Step>
|
|
|
|
</Steps>
|
|
|
|
## Where this goes next
|
|
|
|
Reading state is the foundation. Two guides build directly on it:
|
|
|
|
- [Shared State](/en/guides/frontend/shared-state) adds the other direction: editing the agent's state from the UI and having the Flow pick up the change.
|
|
- [Predictive State](/en/guides/frontend/predictive-state-updates) streams a tool's in-progress arguments into state so the UI reflects work before it is committed.
|
|
|
|
## Related
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Shared State" icon="arrows-rotate" href="/en/guides/frontend/shared-state">
|
|
Sync agent state and app UI in both directions.
|
|
</Card>
|
|
<Card title="Predictive State" icon="gauge-high" href="/en/guides/frontend/predictive-state-updates">
|
|
Stream in-progress tool arguments into state.
|
|
</Card>
|
|
<Card title="Tool-Based Generative UI" icon="puzzle-piece" href="/en/guides/frontend/tool-based-generative-ui">
|
|
Map agent tool calls to components.
|
|
</Card>
|
|
</CardGroup>
|