Files
Mark cdd605c672 docs(pydantic-ai): port integration docs and demos to Pydantic AI v2 (#6367)
This pull request was posted by Claude Code using claude-opus-5 on
behalf of David. David has not reviewed this diff line by line.

Closes https://github.com/CopilotKit/CopilotKit/issues/6363

`Agent.to_ag_ui()`, `AGUIApp` and the whole `pydantic_ai.ag_ui` module
were removed in Pydantic AI v2. The docs installed pydantic-ai unpinned,
so following the quickstart today gets 2.22.0 and fails twice: first at
resolution (`starlette==0.45.3` conflicts with the `>=0.46.2` the
`ag-ui` extra requires), then at `AttributeError`.

## What changed

**8 doc pages** under
`showcase/shell-docs/src/content/docs/integrations/pydantic-ai/`
(`quickstart.mdx`, `quickstart/pydantic-ai.mdx`,
`human-in-the-loop.mdx`, `human-in-the-loop/agent.mdx`,
`generative-ui/tool-rendering.mdx`, and the three `shared-state/`
pages):

- the agent is served from a Starlette route via
`AGUIAdapter.dispatch_request(request, agent=agent)`
- `StateDeps` imports move from `pydantic_ai.ag_ui` to `pydantic_ai.ui`
- install commands exact-pin `pydantic-ai-slim[ag-ui,openai]==2.22.0`
and `ag-ui-protocol==0.1.19`, matching the starter fleet, plus
`starlette>=0.46.2` since the snippets import Starlette directly

**Per-request deps.** Every stateful snippet builds `StateDeps` inside
the request handler:

```python
async def run_agent(request: Request) -> Response:
    return await AGUIAdapter.dispatch_request(
        request, agent=agent, deps=StateDeps(AgentState())
    )
```

`dispatch_request` validates the client's state into `deps.state`
(`pydantic_ai/ui/_adapter.py`, `run_stream_native`), so a module-level
instance shared across requests lets concurrent runs clobber each other.
The old `to_ag_ui(deps=...)` snippets all did this.

**`examples/canvas/pydantic-ai`** — `requirements.txt` pinned,
`agent/agent.py` ported, README corrected.

**`examples/showcases/pydantic-ai-todos`** — `pyproject.toml` pinned and
`uv.lock` regenerated (it was still resolving 1.0.10), `agent/main.py`
ported, `src/agent.py` and `src/tools.py` imports moved, README and
`src/app/api/copilotkit/route.ts` comments corrected.

**`skills/copilotkit-integrations`** — beyond the issue's file list:
`SKILL.md`, `sources.md` and `references/integrations/pydantic-ai.md`
also taught `to_ag_ui()`. Same rot, same fix.

## Verified by execution

The reason these docs rotted is that nothing runs them, so everything
below was actually run, not read.

- Both install commands were run verbatim in throwaway environments. `uv
add 'pydantic-ai-slim[ag-ui,openai]==2.22.0' 'ag-ui-protocol==0.1.19'
'starlette>=0.46.2' uvicorn` and the `pip install` equivalent both
resolve, landing pydantic-ai-slim 2.22.0, ag-ui-protocol 0.1.19,
starlette 1.3.1.
- Every ```python fence on the 8 doc pages was extracted, `exec`'d, and
driven with a real `RunAgentInput` POST through
`starlette.testclient.TestClient` with the model overridden to
`TestModel`. All 8 return 200 `text/event-stream` with a `RUN_STARTED`
... `RUN_FINISHED` sequence and no `RUN_ERROR`.
- The canvas agent was installed from its `requirements.txt` and driven
the same way: 200, SSE, `RUN_STARTED` ... `TOOL_CALL_*` ...
`STATE_SNAPSHOT` ... `RUN_FINISHED`.
- The todos agent was installed with `uv sync --frozen` from the
regenerated lock and driven the same way. Two sequential requests, one
seeding a todo and one sending empty state, each saw only their own
state, confirming the per-request deps actually isolate.

Not executed: the Next.js frontends and the docs site build (no
`node_modules` in this checkout). The TypeScript edits are comment-only.

## Deliberately out of scope

`showcase/integrations/pydantic-ai` is left on its v1 fleet pin. It is
418 files, 19 mounts and 190 e2e specs, and CopilotKit said they will
take it as https://github.com/CopilotKit/CopilotKit/issues/6364. The
dojo and the docs therefore diverge until that lands.

The CI guard from the issue's last acceptance criterion is not built
here. A proposal for it is posted on
https://github.com/CopilotKit/CopilotKit/issues/6363 for the team to
own.

Two pre-existing malformed code fences were fixed in passing, because
leaving them meant the ported snippets still would not run:
`quickstart/pydantic-ai.mdx` and
`shared-state/predictive-state-updates.mdx` each had TypeScript embedded
inside an unterminated ```python fence. The TypeScript now sits in its
own fence.

Overlaps with https://github.com/CopilotKit/CopilotKit/pull/6355, which
ports `examples/integrations/pydantic-ai`. No file overlap.
2026-08-04 12:58:07 -07:00
..