Skip to content

docs: add Frontend guides (CopilotKit + AG-UI) - #6686

Draft
ranst91 wants to merge 5 commits into
crewAIInc:mainfrom
ranst91:docs/frontend-copilotkit-section
Draft

docs: add Frontend guides (CopilotKit + AG-UI)#6686
ranst91 wants to merge 5 commits into
crewAIInc:mainfrom
ranst91:docs/frontend-copilotkit-section

Conversation

@ranst91

@ranst91 ranst91 commented Jul 27, 2026

Copy link
Copy Markdown

What

Adds a Frontend guides section documenting how to build user interfaces for CrewAI Crews and Flows with CopilotKit over the AG-UI protocol.

New sub-group under Guides (after Flows), 9 pages:

  • Overview — end-to-end integration: CrewAI FastAPI server (ag-ui-crewai) → CopilotKit runtime → React provider
  • Generative UI — the tool-rendering vs state-rendering spectrum
  • Tool-Based Generative UI — render tool calls with useRenderTool
  • Agentic Generative UI — render live agent state with useAgent
  • Human-in-the-Loop — pause/resume with useHumanInTheLoop
  • Shared State — two-way state sync
  • Frontend Actions — browser-side tools via useFrontendTool
  • Predictive State Updatescopilotkit_predict_state
  • Channels — run the agent as a Slack/Discord bot (CopilotKit Channels SDK)

Approach

  • Documents the self-hosted AG-UI path (ag-ui-crewai), consistent with the OSS integration. A note links CopilotKit's managed/Enterprise quickstart as the alternative.
  • Covers both Crews and Flows; Flow-only features are flagged.
  • Frontend uses the current CopilotKit v2 API (@copilotkit/react-core/v2, 1.61.2+); a version note calls out the difference from the older copilotkit Python package / pre-v2 hooks.
  • Backend snippets mirror the real ag-ui-crewai examples.

Versioning

Pages added to edge/en/guides/frontend/ and mirrored into v1.15.5/en/guides/frontend/, with docs.json nav updated for both. Rendered and verified locally with mint dev.

Opening as draft for maintainer review — happy to adjust placement, naming, self-hosted vs managed framing, or any API details.

ranst91 added 3 commits July 22, 2026 15:56
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.
Also register the Frontend sub-group and pages under the default
v1.15.5 version so the section is visible without switching to Edge.
- 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
Copilot AI review requested due to automatic review settings July 27, 2026 10:55
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3fd369db-8a12-45d4-86f0-6d3cf8c9c424

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Frontend guides section to the CrewAI docs, describing how to build UIs for Crews/Flows using CopilotKit over the AG-UI protocol, including patterns like tool rendering, state rendering, HITL, shared state, predictive state, and Channels.

Changes:

  • Adds new Frontend guide pages under docs/edge/en/guides/frontend/ and mirrors them under docs/v1.15.5/en/guides/frontend/.
  • Updates docs/docs.json navigation to include the new Frontend group for both Edge and v1.15.5.
  • Introduces multiple end-to-end code snippets (FastAPI + Flow + React) demonstrating the integration patterns.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
docs/docs.json Adds “Frontend” group to the Guides navigation for Edge and v1.15.5.
docs/edge/en/guides/frontend/overview.mdx End-to-end architecture + setup (agent server → runtime → React provider).
docs/edge/en/guides/frontend/generative-ui.mdx Introduces tool-rendering vs state-rendering concepts.
docs/edge/en/guides/frontend/tool-based-generative-ui.mdx Walkthrough for rendering tool calls with useRenderTool.
docs/edge/en/guides/frontend/agentic-generative-ui.mdx Walkthrough for rendering live Flow state with useAgent (+ emitting state).
docs/edge/en/guides/frontend/human-in-the-loop.mdx Walkthrough for pausing/resuming via useHumanInTheLoop.
docs/edge/en/guides/frontend/shared-state.mdx Walkthrough for two-way shared state with agent.setState(...).
docs/edge/en/guides/frontend/frontend-actions.mdx Walkthrough for browser-side tools via useFrontendTool.
docs/edge/en/guides/frontend/predictive-state-updates.mdx Walkthrough for copilotkit_predict_state optimistic UI updates.
docs/edge/en/guides/frontend/channels.mdx Walkthrough for running the same agent via Slack/Discord using Channels SDK.
docs/v1.15.5/en/guides/frontend/overview.mdx Snapshot copy of the Frontend Overview page.
docs/v1.15.5/en/guides/frontend/generative-ui.mdx Snapshot copy of the Generative UI page.
docs/v1.15.5/en/guides/frontend/tool-based-generative-ui.mdx Snapshot copy of the Tool-Based Generative UI page.
docs/v1.15.5/en/guides/frontend/agentic-generative-ui.mdx Snapshot copy of the Agentic Generative UI page.
docs/v1.15.5/en/guides/frontend/human-in-the-loop.mdx Snapshot copy of the Human-in-the-Loop page.
docs/v1.15.5/en/guides/frontend/shared-state.mdx Snapshot copy of the Shared State page.
docs/v1.15.5/en/guides/frontend/frontend-actions.mdx Snapshot copy of the Frontend Actions page.
docs/v1.15.5/en/guides/frontend/predictive-state-updates.mdx Snapshot copy of the Predictive State Updates page.
docs/v1.15.5/en/guides/frontend/channels.mdx Snapshot copy of the Channels page.
Comments suppressed due to low confidence (5)

docs/edge/en/guides/frontend/agentic-generative-ui.mdx:76

  • The tool schema restricts status to only "enabled", but the state model allows "disabled" (and the guide later sets step.status = "disabled"). This mismatch makes the example self-contradictory and can cause validation/tooling issues; include both enum values (or adjust the state type to match).
                            "description": {"type": "string"},
                            "status": {"type": "string", "enum": ["enabled"]},
                        },

docs/v1.15.5/en/guides/frontend/agentic-generative-ui.mdx:76

  • The tool schema restricts status to only "enabled", but the state model allows "disabled" (and the guide later sets step.status = "disabled"). This mismatch makes the example self-contradictory and can cause validation/tooling issues; include both enum values (or adjust the state type to match).
                            "description": {"type": "string"},
                            "status": {"type": "string", "enum": ["enabled"]},
                        },

docs/edge/en/guides/frontend/agentic-generative-ui.mdx:103

  • In the “Write progress into state” step, the Flow never assigns the generated tool-call arguments into self.state.steps, so the frontend won’t see any progress via agent.state. Parse the generate_task_steps tool call and write the steps into state (and optionally append a tool result for a well-formed tool-call turn).
        message = response.choices[0].message
        self.state.messages.append(message)

docs/v1.15.5/en/guides/frontend/agentic-generative-ui.mdx:103

  • In the “Write progress into state” step, the Flow never assigns the generated tool-call arguments into self.state.steps, so the frontend won’t see any progress via agent.state. Parse the generate_task_steps tool call and write the steps into state (and optionally append a tool result for a well-formed tool-call turn).
        message = response.choices[0].message
        self.state.messages.append(message)

docs/edge/en/guides/frontend/shared-state.mdx:166

  • updateRecipe can throw when agent or recipe is still undefined (e.g., { ...recipe, ...patch } will crash if recipe is undefined, and agent.setState will crash if agent is not ready). Guard against an undefined agent and default recipe to {} before spreading.
  const updateRecipe = (patch: Partial<Recipe>) =>
    agent.setState({ ...agent.state, recipe: { ...recipe, ...patch } });

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +6
---
title: Frontend Overview
description: Build interactive user interfaces for your CrewAI agents with CopilotKit and the AG-UI protocol.
icon: browser
mode: "wide"
---
Comment on lines +100 to +111
if message.get("tool_calls"):
call = message["tool_calls"][0]
if call["function"]["name"] == "generate_recipe":
args = json.loads(call["function"]["arguments"])
self.state.recipe = Recipe(**args["recipe"]) # write to shared state
self.state.messages.append({
"role": "tool",
"content": "Recipe updated.",
"tool_call_id": call["id"],
})
return "route_follow_up"
return "route_end"
Comment on lines +100 to +111
if message.get("tool_calls"):
call = message["tool_calls"][0]
if call["function"]["name"] == "generate_recipe":
args = json.loads(call["function"]["arguments"])
self.state.recipe = Recipe(**args["recipe"]) # write to shared state
self.state.messages.append({
"role": "tool",
"content": "Recipe updated.",
"tool_call_id": call["id"],
})
return "route_follow_up"
return "route_end"
Comment on lines +157 to +166
const state = agent?.state as { recipe?: Recipe } | undefined;
const isLoading = agent?.isRunning;

const recipe = state?.recipe;

// setState replaces the whole state object, so spread the current
// state and override only the field you changed. Passing just
// `{ recipe }` would drop messages and other runtime fields.
const updateRecipe = (patch: Partial<Recipe>) =>
agent.setState({ ...agent.state, recipe: { ...recipe, ...patch } });
Comment on lines +34 to +45
from typing import List, Literal
from pydantic import BaseModel
from ag_ui_crewai.sdk import CopilotKitState


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


class AgentState(CopilotKitState):
steps: List[TaskStep] = []
Comment on lines +34 to +45
from typing import List, Literal
from pydantic import BaseModel
from ag_ui_crewai.sdk import CopilotKitState


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


class AgentState(CopilotKitState):
steps: List[TaskStep] = []
Copilot AI review requested due to automatic review settings July 28, 2026 10:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (9)

docs/v1.15.5/en/guides/frontend/overview.mdx:5

  • This file is being added under docs/v1.15.5/, but repo docs policy treats docs/v*/ as frozen release snapshots managed by devtools; CI rejects edits there unless this is a [docs-freeze] PR. These pages should live under docs/edge/ only and be snapshotted by the release tooling.
---
title: Frontend Overview
description: Build interactive user interfaces for your CrewAI agents with CopilotKit and the AG-UI protocol.
icon: browser
mode: "wide"

docs/edge/en/guides/frontend/agentic-generative-ui.mdx:45

  • steps: List[TaskStep] = [] is a mutable default. Use Field(default_factory=list) to avoid accidentally sharing state between instances (and to match the pattern used elsewhere in the docs).
class AgentState(CopilotKitState):
    steps: List[TaskStep] = []

docs/docs.json:692

  • docs/v*/ is a frozen snapshot; adding new pages to the v1.15.5 nav will trigger the docs-snapshots CI guard unless this is a [docs-freeze] PR. Please remove the v1.15.5/en/guides/frontend/* entries and keep the new Frontend section in edge/ only.
    docs/edge/en/guides/frontend/tool-based-generative-ui.mdx:85
  • This example treats message as an object with .tool_calls/.id, but elsewhere in CrewAI docs and code, chat messages are handled as dicts (e.g., message.get("tool_calls")). As written, one of these shapes will break for users copying the snippet.
        message = response.choices[0].message
        self.state.messages.append(message)

        if message.tool_calls:
            self.state.messages.append({
                "tool_call_id": message.tool_calls[0].id,
                "role": "tool",

docs/edge/en/guides/frontend/shared-state.mdx:166

  • { ...recipe, ...patch } will throw if recipe is undefined (object-spread on undefined/null). Since recipe is optional initially, this can break the example as soon as the user types into the input.
  const updateRecipe = (patch: Partial<Recipe>) =>
    agent.setState({ ...agent.state, recipe: { ...recipe, ...patch } });

docs/edge/en/guides/frontend/generative-ui.mdx:37

  • This code calls useRenderTool(...) at module scope. Since it is a React hook, calling it outside a component/custom hook violates the Rules of Hooks and will crash/lint-fail in real Next.js apps.
useRenderTool({
  name: "generate_recipe",
  parameters: z.object({
    title: z.string(),
    ingredients: z.array(z.string()),
  }),
  render: ({ args }) => <RecipeCard title={args.title} ingredients={args.ingredients} />,
});

docs/edge/en/guides/frontend/frontend-actions.mdx:45

  • This example calls useFrontendTool(...) at module scope. As a React hook, it needs to run inside a component (or custom hook) to satisfy the Rules of Hooks.
useFrontendTool({
  agentId: "assistant",
  name: "set_theme",
  description: "Switch the app between light and dark mode.",
  parameters: z.object({
    theme: z.enum(["light", "dark"]),
  }),
  followUp: false,
  handler: async ({ theme }) => {

docs/edge/en/guides/frontend/human-in-the-loop.mdx:124

  • This snippet calls useHumanInTheLoop(...) at module scope. As a React hook, it should be invoked inside a component/custom hook to avoid Rules-of-Hooks violations in Next.js.
useHumanInTheLoop({
  agentId: "human_in_the_loop",
  name: "generate_task_steps",
  parameters: z.object({
    steps: z.array(
      z.object({
        description: z.string(),
        status: z.enum(["enabled", "disabled", "executing"]),
      })
    ),
  }),
  render: ({ args, respond, status }) => (

docs/edge/en/guides/frontend/tool-based-generative-ui.mdx:138

  • This snippet calls useRenderTool(...) at module scope. Since it is a React hook, this violates the Rules of Hooks in real Next.js apps; wrap the registration in a component and render it under your <CopilotKit> provider.
useRenderTool({
  name: "generate_haiku",
  parameters: z.object({
    japanese: z.array(z.string()),
    english: z.array(z.string()),
  }),
  render: ({ args, status }) => {
    if (!args.japanese) return <></>; // still streaming
    return <HaikuCard japanese={args.japanese} english={args.english} />;

Copilot AI review requested due to automatic review settings July 28, 2026 10:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (4)

docs/edge/en/guides/frontend/shared-state.mdx:104

  • This snippet treats message as a dict (message.get(...), message[...]), but elsewhere in this repo the OpenAI-style message object is accessed via attributes (e.g., message.tool_calls). As written, the example will raise at runtime if message is not dict-like, and it’s inconsistent with the other examples in this new section.
        if message.get("tool_calls"):
            call = message["tool_calls"][0]
            if call["function"]["name"] == "generate_recipe":
                args = json.loads(call["function"]["arguments"])
                self.state.recipe = Recipe(**args["recipe"])  # write to shared state

docs/edge/en/guides/frontend/shared-state.mdx:172

  • This input stays enabled while agent is still undefined, which makes it easy to trigger the updateRecipe handler before the agent is ready. Disable the input until the agent is available (or until loading completes).
        disabled={isLoading}

docs/edge/en/guides/frontend/shared-state.mdx:166

  • updateRecipe calls agent.setState(...) unconditionally, but agent can be undefined on first render (before the hook initializes). That would throw if the user types immediately. Guard against agent being undefined before calling setState.

This issue also appears on line 172 of the same file.

  const updateRecipe = (patch: Partial<Recipe>) =>
    agent.setState({ ...agent.state, recipe: { ...recipe, ...patch } });

docs/edge/en/guides/frontend/agentic-generative-ui.mdx:76

  • The tool schema for generate_task_steps only allows status to be "enabled", but later in this guide you set step.status = "disabled". Update the JSON schema enum to match the statuses the guide uses so the tool call validates correctly.
                            "description": {"type": "string"},
                            "status": {"type": "string", "enum": ["enabled"]},
                        },

Comment thread docs/docs.json
Comment on lines +678 to +692
{
"group": "Frontend",
"icon": "browser",
"pages": [
"v1.15.5/en/guides/frontend/overview",
"v1.15.5/en/guides/frontend/generative-ui",
"v1.15.5/en/guides/frontend/tool-based-generative-ui",
"v1.15.5/en/guides/frontend/agentic-generative-ui",
"v1.15.5/en/guides/frontend/human-in-the-loop",
"v1.15.5/en/guides/frontend/shared-state",
"v1.15.5/en/guides/frontend/frontend-actions",
"v1.15.5/en/guides/frontend/predictive-state-updates",
"v1.15.5/en/guides/frontend/channels"
]
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants