docs/v1.15.16/en/guides/frontend/reasoning.mdx
When a reasoning-capable model thinks before it answers, CopilotKit renders that thinking right in the chat. This is the simplest generative-UI pattern in the whole section: there is nothing to build. No hook, no component, no props. Use a reasoning-capable model, keep the streaming wrapper your Flows already have, and the chat surface from the Overview does the rest.
Reasoning is surfaced automatically by copilotkit_stream, which every Flow example already wraps the model call in. The bridge reads the model's reasoning deltas and emits them to the frontend. It is provider-agnostic and works over both of CrewAI's streaming transports, so the only thing you change is the model.
# recipe_flow.py
from crewai.flow.flow import Flow, start
from ag_ui_crewai.sdk import copilotkit_stream, CopilotKitState
from litellm import acompletion
class RecipeFlow(Flow[CopilotKitState]):
@start()
async def chat(self):
response = await copilotkit_stream(
acompletion(
# any reasoning-capable model, e.g. deepseek-reasoner
model="deepseek/deepseek-reasoner",
messages=self.state.messages,
stream=True,
)
)
message = response.choices[0].message
self.state.messages.append(message)
Models that emit reasoning over the standard channel include DeepSeek deepseek-reasoner, Anthropic extended thinking (Claude), and Gemini thinking, among others. Swap the model for one of these and its thinking starts streaming through.
This works the same for both Crews and Flows, since both run their model calls through copilotkit_stream.
There is no frontend step. The CopilotChat, CopilotSidebar, or CopilotPopup surface you already mounted shows the reasoning as it streams, above the answer it produced.
import { CopilotChat } from "@copilotkit/react-core/v2";
<CopilotChat agentId="recipe" />