Back to Copilotkit

CopilotKit × Claude Agent SDK — Python Starter

examples/integrations/claude-sdk-python/README.md

1.66.07.2 KB
Original Source

CopilotKit × Claude Agent SDK — Python Starter

A starter template for building AI agents with the Claude Agent SDK and CopilotKit. It pairs a modern Next.js frontend with a Python agent that speaks the AG-UI protocol, and shows CopilotKit driving interactive UI beyond chat:

  • a shared-state todos canvas the agent and the user both edit,
  • charts rendered from queried data,
  • flight cards and dynamic dashboards via A2UI generative UI,
  • a human-in-the-loop meeting picker,
  • a light/dark theme toggle, and
  • the SDK threads drawer (activated with a CopilotKit Intelligence license).

The agent is powered by Claude (claude-sonnet-5 by default) and exposes three backend tools — query_data, search_flights, and generate_a2ui — while the todo board is shared state the agent updates through the adapter's built-in ag_ui_update_state tool.

Prerequisites

Getting Started

  1. Copy the environment file:

    bash
    cp .env.example .env
    
  2. Add your Anthropic API key to .env:

    bash
    ANTHROPIC_API_KEY=sk-ant-...
    

    The other values are optional and already set to sensible defaults: CLAUDE_MODEL=claude-sonnet-5 and AGENT_URL=http://localhost:8000.

  3. Install dependencies:

    bash
    npm install
    

    This installs the Next.js frontend and, via the postinstall script, the Python agent's dependencies with uv sync.

  4. Start the app:

    bash
    npm run dev
    

    This runs the Next.js UI on http://localhost:3000 and the Claude agent on http://localhost:8000 concurrently.

  5. Open http://localhost:3000 and try the suggested prompts (add todos, draw a chart, search flights, build a dashboard, schedule a meeting).

  6. (Optional) Enable the Threads drawer. Thread history is gated behind a CopilotKit Intelligence license. Set COPILOTKIT_LICENSE_TOKEN (and the INTELLIGENCE_* URLs) in .env to activate live thread history; without it the drawer shows a locked state.

Running a Channel

channel-host.mts mounts the same agent as an Intelligence Channel (Slack, Teams). It requires INTELLIGENCE_API_KEY and a declared Channel in .copilotkit/channels.json — set both up with copilotkit init or copilotkit channels add, which write that file and the credentials your .env needs, then:

bash
npm run channel

The host reads which Channel to hold from .copilotkit/channels.json. If a project declares more than one, set INTELLIGENCE_CHANNEL_NAME to pick one.

The host holds no provider credentials and exposes no provider endpoint — Intelligence owns the provider edge — so the same file works for every provider.

The Channel itself is declared in channels.mts — that is where to add commands, reactions, or an onMention handler. channel-host.mts only owns the process lifetime, and is byte-identical in every starter.

Once startup finishes, the log reports the truth per Channel:

  • Channel "<name>" is online. — the session is up and can send.
  • Channel "<name>" is declared but no provider is attached yet. — a normal waiting state, not a failure. Run copilotkit channels status to see what setup remains.

Neither message proves the provider app is installed, reachable, or that anyone can message it — verify that separately (invite the bot, then message it) before treating the Channel as working.

Available scripts

  • npm run dev — start the UI and agent together (dev mode)
  • npm run dev:ui — start only the Next.js UI (port 3000)
  • npm run dev:agent — start only the Claude agent (port 8000)
  • npm run build — build the Next.js app for production
  • npm start — start the production server
  • npm run install:agent — (re)install the Python agent's dependencies
  • npm run channel — hold an Intelligence Channel open (see "Running a Channel" above)
  • npm run typecheck:channel — type-check the channel host on its own tsconfig.channel.json

Project structure

├── src/
│   ├── app/
│   │   ├── page.tsx                       # Main page (chat + todos canvas + threads drawer)
│   │   ├── layout.tsx                     # CopilotKit v2 provider + A2UI catalog
│   │   └── api/copilotkit/[[...slug]]/     # CopilotKit runtime route (HttpAgent → :8000)
│   ├── components/                        # Canvas, generative UI, chat, UI primitives
│   └── hooks/                             # Example suggestions + generative-UI examples
└── agent/                                 # Python Claude agent (AG-UI on port 8000)
    ├── main.py                            # Server: mounts the adapter's FastAPI endpoint
    ├── pyproject.toml                     # Agent dependencies (managed by uv)
    └── src/
        ├── agent.py                       # The agent: backend tools → ClaudeAgentAdapter
        ├── model.py                       # Model resolution (CLAUDE_MODEL)
        ├── query.py                       # query_data tool
        ├── a2ui_fixed_schema.py           # search_flights tool (fixed A2UI schema)
        ├── a2ui_dynamic_schema.py         # generate_a2ui tool (LLM-designed dashboard)
        ├── db.csv                         # Sample data for query_data
        └── a2ui/schemas/flight_schema.json

How it works

  • The frontend uses CopilotKit's v2 React hooks. Shared state (like the todo list) lives in the agent and syncs bidirectionally with the UI.
  • The runtime route (src/app/api/copilotkit/[[...slug]]/route.ts) connects to the agent over HTTP with HttpAgent from @ag-ui/client.
  • The agent is a thin layer on the official ag-ui-claude-sdk adapter. src/agent.py defines the three backend tools and hands them to ClaudeAgentAdapter; main.py serves it with the adapter's add_claude_fastapi_endpoint. The adapter drives Claude through the Claude Agent SDK, bridges CopilotKit frontend tools + human-in-the-loop, and manages the shared todos state via its built-in ag_ui_update_state tool.

To customize: add or edit tools in agent/src/ and the system prompt in agent/src/agent.py, and the UI in src/app/page.tsx and src/components/.

Troubleshooting

"I'm having trouble connecting to my tools" / agent unreachable

  • Make sure the agent is running on port 8000 (npm run dev:agent) and that ANTHROPIC_API_KEY is set in .env.
  • Confirm the agent's health check: curl http://localhost:8000/health{"status":"ok"}.

Python import errors

  • Reinstall the agent's dependencies: cd agent && uv sync.

Learn more

License

MIT — see LICENSE.