## What
- Adds `integrations/adk/agent-app-context.mdx`, the page ADK was
missing.
- Lists it under **App Control** in `adk/meta.json`, beside
`frontend-tools` and `shared-state`, matching Mastra.
- Scopes the built-in-agent page's "no backend configuration needed" to
the built-in agent, and points at the per-framework pages.
## Why
`ag_ui_adk` stores `RunAgentInput.context` in ADK session state under
`CONTEXT_STATE_KEY` (`"_ag_ui_context"`) and stops there. Its own
docstring says so:
> Context from RunAgentInput is always stored in session state under the
`_ag_ui_context` key (CONTEXT_STATE_KEY), making it accessible to both
tools (via `tool_context.state`) and instruction providers (via
`ctx.state`).
Nothing in the package puts it in front of the model —
`CONTEXT_STATE_KEY` is read in exactly one place, `a2ui_tool.py`, for
the A2UI catalog entry. ADK's `inject_session_state` substitutes only
explicit `{key}` placeholders, so an `LlmAgent` built with a plain
string `instruction` (the form every ADK quickstart shows) never sees
what `useAgentContext` sent.
The agent still answers. Probing one such agent with the page's full
queue in `context` and then with `context: []`:
| context sent | report the model passed to its own tool |
| -- | -- |
| full queue | `"The payment gateway is returning 500 errors for 40% of
checkout requests…"` |
| full queue, repeated | `"The production payment service is returning
500 errors for 80%…"` |
| **empty** | `"Database connection pool exhausted on us-east-1
production cluster…"` |
Three inventions, and the empty-context run is indistinguishable from
the two full ones. Nothing errors, nothing is missing from the UI, and
the answer is well formed — which is exactly why a page is the right fix
rather than a troubleshooting note.
Mastra and LangGraph both document their retrieval step. ADK had none,
and `langgraph/programmatic-control.mdx` already links to a sibling page
that did not exist for ADK.
The page covers both retrieval forms — an `InstructionProvider` reaching
`ctx.state` (with the note that `canonical_instruction` reports
`bypass_state_injection=True` for a provider, so JSON braces in the
rendered context survive), and `tool_context.state` when only one tool
needs the data — and closes with the empty-context control as the way to
check the wiring.
## Testing
- Both `.mdx` files compile under `@mdx-js/mdx`.
- `adk/meta.json` parses, and `agent-app-context` sits in the group
Mastra puts it in.
- Internal links use the repo's own convention (`/adk/…`,
`/langgraph/agent-app-context`, `/mastra/agent-app-context`), matching
links already in the tree.
- `<Callout type="warn" title="…">` matches existing usage.
- The docs site build was not run locally — the worktree has no install.
Leaving that to CI.
Filed as OSS-1045 internally, a sibling of OSS-1027 (Pydantic AI's
adapter drops the same field outright).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Added ADK integration guidance for sharing application context with
agents, including setup steps and access from instructions and tools.
* Updated documentation navigation to include the new ADK application
context page.
* Clarified how built-in and self-hosted agents receive and process
application context, with links to framework-specific guidance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sibling of #6796 (ADK). Same class of gap, one layer earlier.
## CrewAI does not behave either
OSS-1045 asked whether CrewAI behaves, since it was one of the two
frameworks with no `agent-app-context` page. It does not, and its
failure is worse than ADK's.
`ag_ui_crewai` 0.3.0 threads `RunAgentInput.context` into the run state,
and its own comment says why:
> Thread `input.context` into the run so agent code and tools can read
it from state.
But `CopilotKitState` declares `messages` and `copilotkit` — not
`context`. A Flow state is a Pydantic model, and Pydantic drops unknown
keys by default, so the key the endpoint just populated is discarded on
validation before any `@start()` method runs:
```
CopilotKitState fields : ['agent_threads', 'copilotkit', 'current_user_message', 'ended',
'events', 'id', 'last_intent', 'last_user_message',
'messages', 'session_ready']
extra policy : None
context survived? : False <<DROPPED>>
```
`self.state.context` does not exist in the shape every quickstart shows.
ADK at least parks the value somewhere an integrator can reach
(`ctx.state[CONTEXT_STATE_KEY]`).
## Proved with a control, not by reading one answer
The same run body sent three times to a CrewAI Flow agent, unmodified,
on `ag-ui-crewai==0.3.0`. User message `Triage INC-2002.` throughout,
with a three-incident operator queue in `context`:
| context sent | `incident_summary` | severity |
| -- | -- | -- |
| full queue | `"Triage INC-2002."` | low |
| full queue, repeated | `"Triage INC-2002."` | low |
| **empty** | `"Triage INC-2002."` | low |
The empty control is indistinguishable from both full-context runs.
Declaring the field and rendering it separates them — the agent then
names the incident the page actually holds ("A canary deploy of the
search indexer is writing malformed documents…", severity medium).
Worth noting for anyone reading a CrewAI run: this fixture *refused*
rather than fabricating, because its backstory forbids invention. That
is a property of the prompt, not of the adapter. An agent without that
line fabricates exactly as the ADK one did. The page says so.
## The page's snippets were run before shipping
Two corrections came out of that and are in the page because of it:
- The rendered context goes through `inputs` rather than being formatted
into the task `description`, so JSON braces are not read as more
`{placeholder}`s.
- The flow appends its answer to `self.state.messages`. Without that the
turn completes, the crew runs, and **nothing renders** — the first draft
of this page had that bug, and the probe caught it.
Final verification, against the page's own advice: with the colleagues
context the agent answers "You should email Aisha Okonkwo, who is the
Security Lead"; with `context: []` it answers "The page sent no
colleagues" rather than inventing one.
## Also filed
The retrieval arguably belongs upstream rather than in every
integrator's agent — for CrewAI it is not a design call but a defect,
since the package's own base class discards what the package's own
endpoint wrote. Filed on `ag-ui-protocol/ag-ui`; this page is the fix
that works against the shipped version today.
Closes OSS-1051.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Added guidance for sharing app-specific context with CrewAI Flows.
* Documented how to register app state, declare context in the flow
state, and include it in prompts.
* Added troubleshooting advice for silently missing context, including
testing with an empty context.
* Added the new guide to the CrewAI Flows documentation navigation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
CodeRabbit flagged two overstatements on the new page, both confirmed
against source:
- ag_ui_adk 0.7.0's _default_run_config also copies the context into
RunConfig.custom_metadata['ag_ui_context'] when google-adk >= 1.22.0,
so ctx.state is not the only place it exists. Keep ctx.state as the
cross-version form and name the alternative.
- inject_session_state's _replace_match returns the match verbatim
unless the brace contents pass _is_valid_state_name, so JSON braces
survive a string instruction. The real hazard is an identifier-shaped
block in a context value, which raises KeyError.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Why
Angular had no counterpart to `useComponent` in
`@copilotkit/react-core/v2` and `@copilotkit/vue/v2`. Letting an agent
display one of your components meant either `registerFrontendTool` with
a handler the component does not need, or `registerRenderToolCall`,
which draws a tool the agent already has and therefore requires that
tool to exist in the agent.
That gap is load-bearing for OSS-1034, which ends the default onboarding
proof at a component rendered through the frontend's own registration.
Every other supported frontend ships `useComponent`; Angular was the
only one that could not express the shape.
## What changed
**`FrontendToolConfig.handler` is now optional**, and
`CopilotKit.#bindClientTool` returns the config unwrapped when it is
absent. This is the actual missing capability. Core already has the
render-only path — a tool that declares no handler gets an empty tool
result and the turn completes (`packages/core/src/core/run-handler.ts`,
the `if (tool.handler)` guards around lines 854 and 1112). Angular bound
a wrapper unconditionally:
\`\`\`ts
handler: (args, context) =>
runInInjectionContext(injector, () => handler(args, context)),
\`\`\`
so a display-only tool called \`undefined\` on its first tool call. A
stub handler is the wrong fix in the other direction: whatever it
returns becomes the tool's result in the thread, which is a fabricated
result rather than an absent one.
**`registerComponent`** is that shape with the model-facing description
built for it — the same prefix react-core and vue build, so the tool
reads identically to the model whichever frontend registered the
component. It carries no `handler` field at all: a display-only
component that quietly ran application code would be a different
feature, and a caller who wants both wants `registerFrontendTool`.
The component stays an ordinary `ToolRenderer` with a required
`toolCall` signal input reading `toolCall().args`. No new component
contract, and it renders through the existing `pickToolCallHandler` →
`NgComponentOutlet` path unchanged.
Because the tool is declared by the frontend and forwarded over AG-UI, a
display-only component needs nothing added to the agent — on any
framework, Python included.
\`\`\`ts
registerComponent({
name: "show_incident",
description: "Show one incident from the incident table.",
parameters: z.object({ id: z.string(), severity: z.string() }),
component: IncidentCardComponent,
});
\`\`\`
## Docs
- New `reference/angular/functions/registerComponent.mdx`, wired into
the reference index callout and the `public-api.mdx` summary.
- A display-only section and a new path-table row in the Angular
generative-UI guide.
- `packages/angular/API.md` — the `public-api-documentation.spec.ts`
gate fails on any undocumented export, which is how the omission
surfaced immediately.
The reference page also carries the grounding warning: the model fills
these props from what it knows, so a component rendered over records the
application does not hold looks identical to a correct one in a browser
and in a screenshot.
## Testing
Five tests written before the implementation, confirmed red (`(0 ,
registerComponent) is not a function` ×4, plus the handler-less binding
test) with the 14 pre-existing registration tests still passing, then
green.
- `pnpm nx run @copilotkit/angular:test` — 49 files, 321 passed, 1
skipped.
- `pnpm nx build @copilotkit/angular` — passes, so widening `handler` to
optional broke no caller.
- `showcase/shell-docs` — 66/68 files, 480 tests pass. The 2 failures
are pre-existing on `main` and read files this branch does not touch (a
shared inspector snippet, and mastra tool-rendering content).
- `pnpm run check-format` — the 22 reported files are all pre-existing;
none is in this diff.
Refs OSS-1034
🤖 Generated with [Claude Code](https://claude.com/claude-code)
OSS-1045 shipped the ADK page and left CrewAI unchecked. It does not behave, and it fails
one layer earlier than ADK does.
`ag_ui_crewai` 0.3.0 threads `RunAgentInput.context` into the run state and says so in a
comment: "so agent code and tools can read it from state". But `CopilotKitState` declares
`messages` and `copilotkit` and not `context`, and a Flow state is a Pydantic model, so the
key the endpoint just populated is dropped on validation before any `@start()` method runs.
`self.state.context` does not exist in the shape every quickstart shows. ADK at least parks
the value somewhere an integrator can reach.
Proved with a control rather than by reading one answer. The same run body sent to a CrewAI
Flow agent three times, twice with a three-incident operator queue in `context` and once
with `context: []`, produced three identical answers: the empty control was indistinguishable
from both full-context runs. Declaring the field and rendering it separates them, and the
agent then names the incident the page actually holds.
The page's own snippets were run as an agent before shipping. Two things surfaced that way
and are in the page because of it: `inputs` carries the rendered context so JSON braces are
not read as more `{placeholder}`s, and the flow appends its answer to `self.state.messages`,
without which the turn finishes with nothing rendered at all.
Verified against the page's own advice: with the colleagues context the agent answers "You
should email Aisha Okonkwo, who is the Security Lead", and with an empty context it answers
"The page sent no colleagues" rather than inventing one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The new page linked out to both, but neither linked back, so a reader on
either page had no way to discover the display-only shape. React's
useFrontendTool/useRenderTool/useDefaultRenderTool and Vue's
useFrontendTool all point at useComponent; Angular was the only frontend
where the links ran one way.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Problem
Inspector is a browser overlay, so a React Native developer cannot open
it. Nothing in the docs said so.
The docs already skipped the Open Inspector step on React Native, so
they never told a mobile developer to click a button that isn't there.
But they also never stated the absence, and Inspector is presented as
the debugging story on every other frontend.
An onboarding run on 2026-08-25 reached a fully working native app on an
Android emulator — round trip proven, three grounded turns typed into
the device — and fell back to `adb exec-out screencap` for visual proof,
with no way to tell whether the missing Inspector meant something was
wrong.
## Why the absence is permanent
- `packages/react-core/src/v2/components/CopilotKitInspector.tsx` mounts
`@copilotkit/web-inspector` through `@lit-labs/react` — a Lit custom
element needing `document` and `customElements`.
- `packages/react-native` does not depend on
`@copilotkit/web-inspector`, and
`packages/react-native/src/__tests__/headless-entry-surface.test.ts`
lists it in `FORBIDDEN_HEAVY`, so that test fails if the mobile bundle
ever reaches it.
This documents an existing, tested architectural decision. No Inspector
or package change.
## Change
- **`docs/inspector.mdx`** — new `## Where Inspector runs` section,
placed before the pane tour so a reader learns whether the page applies
to them before learning its navigation. It states the browser
requirement and maps the panes a mobile developer loses onto what
replaces them: `npx copilotkit verify --round-trip`, runtime Debug Mode
beside `adb logcat`, and the Intelligence thread view.
- **`docs/frontends/react-native.mdx`** — Inspector added to **Known
limitations**, the list a mobile developer actually checks. It already
named voice, the web-only rendering hooks, `threadId`, and the cloud
provider props.
- **`skills/inspector-docs/references/pane-map.md`** — the "Surfaces
that do not get the Open Inspector step" section now records where each
browserless surface states its absence.
Channels — Slack and Teams — are named in the same section for the same
reason.
## Tests
`inspector-docs.test.ts` already had a negative guard (`React Native and
Channels do not tell the reader to click the Inspector button`), which
forbade the wrong statement without requiring the right one. Two
positive tests now require it:
- `Inspector states that it needs a browser and React Native has none`
- `the React Native page lists the missing Inspector among its
limitations`
Both were written first and observed failing.
## Verification
- `showcase/shell-docs` `inspector-docs.test.ts`: **11/11 pass** (9
before, +2 new).
- Mutation check: replacing `There is no React Native build of
Inspector` and `no React Native surface` in the two pages fails both new
tests (2 failed | 9 passed), so they are not self-fulfilling.
- `oxfmt --check` and `oxlint` clean on the changed test.
- `scripts/sync-plugin-skills.ts --check`: `plugin skill mirror in sync`
(`inspector-docs` is a `RESERVED_LIFECYCLE_SLUGS` standalone skill, so
root `skills/` is its source, not a mirror).
- The full shell-docs suite shows 18 unrelated failures in
`channels-guide-search`, `registry`, `setup-content`, `setup-concept`,
and `llm-text`. **Confirmed pre-existing**: the same 18 fail identically
in a pristine `origin/main` worktree sharing the same `node_modules` and
the same generated `src/data`. None of them read either page touched
here.
## Companion
The CLI half is CopilotKit/Intelligence#1001 — the onboarding graph's
completion prompt carried the same unconditional "How to use the
CopilotKit Inspector" instruction. Both carry `refs OSS-977` rather than
`closes`, so the ticket stays open until both land.
## Problem
The two "check your agent name" accordions on the LangGraph
troubleshooting page each carry the **other** accordion's hook name. A
reader who lands here from the "agent not found" error gets
contradictory guidance in both directions:
| Accordion title (before) | Prose said | Code sample uses |
| --- | --- | --- |
| `Check your agent name in useCoAgent` | `useCoAgent` | `useAgent({
agentId })` |
| `Check your agent name in useCoAgentStateRender` | `useAgent` |
`useCoAgentStateRender({ name })` |
Someone migrated the first accordion's code sample to the v2 `useAgent`
hook without updating its title or prose, and the second accordion's
prose picked up `useAgent` while its title and sample stayed on
`useCoAgentStateRender`.
This matters more than a typo: the two hooks take **different prop
names** (`agentId` vs `name`), so a reader following the mislabelled
prose reaches for the wrong prop on the wrong hook while debugging
exactly the failure this page exists to explain.
## Fix
Align each accordion's title and prose with the hook its code sample
actually uses, and name the specific prop rather than the vague "what
you use":
- **`useAgent`** accordion → prose now points at the `agentId` prop.
- **`useCoAgentStateRender`** accordion → prose now points at the `name`
prop.
Both hooks are correct as documented and neither is being migrated here
— `useAgent({ agentId })` is the current v2 signature
(`packages/react-core/src/v2/hooks/use-agent.tsx:128`), and
`useCoAgentStateRender` remains exported through the v1 compatibility
surface (`packages/react-core/src/v1-deprecated-compatibility.ts:301`)
with its own reference page at
`/reference/v1/hooks/useCoAgentStateRender`. This PR only makes each
accordion internally consistent.
The two prose lines also carried `Make sure the that the` and `what you
use n`, both fixed in passing since the same lines are being rewritten.
## Testing
**1. MDX still compiles.** Compiled the page with `@mdx-js/mdx@3.1.1`
before and after:
```
--- BEFORE (origin/main) ---
MDX COMPILE OK — 17287 bytes emitted
--- AFTER (this branch) ---
MDX COMPILE OK — 17396 bytes emitted
```
**2. Title / prose / code sample now agree.** Wrote a probe that parses
every `<Accordion>` on the page and compares the hook named in the
title, the hook named in the prose, and the hook actually called in the
code sample. Ran it against `origin/main` and against this branch:
```
--- BEFORE (origin/main) ---
accordions parsed: 11
MISMATCH title=useCoAgent prose=useCoAgent code=useAgent
MISMATCH title=useCoAgentStateRender prose=useAgent code=useCoAgentStateRender
--- AFTER (this branch) ---
accordions parsed: 11
AGREE title=useAgent prose=useAgent code=useAgent
AGREE title=useCoAgentStateRender prose=useCoAgentStateRender code=useCoAgentStateRender
```
The probe reports `MISMATCH` on the pre-fix content and `AGREE` after,
so it is measuring the actual defect rather than passing vacuously.
(Probe was scratch tooling and is not committed.)
**3. Signatures verified against source, not memory.**
```
packages/react-core/src/v2/hooks/use-agent.tsx:128
* - **Bind to an agent** — `useAgent()`, `useAgent({ agentId })`. The shared
packages/react-core/src/v1-deprecated-compatibility.ts:301
useCoAgentStateRender,
```
**4. Completeness.** No remaining instances of either typo anywhere in
the repo, and nothing references the renamed accordion title:
```
$ grep -rIn "Make sure the that" --include='*.mdx' --include='*.md' . # no matches
$ grep -rIn "you use n " --include='*.mdx' --include='*.md' . # no matches
$ grep -rIn "Check your agent name in useCoAgent" ...
common-coagent-issues.mdx:140: <Accordion title="Check your agent name in useCoAgentStateRender"> # the intended one
```
The sibling snippet `snippets/shared/troubleshooting/common-issues.mdx`
does **not** contain these accordions, so the fix is correctly confined
to one file.
## Note on overlap with #6787
Community PR #6787 edits these same two lines, fixing the `the that` /
`use n` typos but leaving the crossed hook names in place. This PR
supersedes both of its hunks. Whichever lands second will need a trivial
conflict resolution — happy to rebase behind #6787 if you'd rather merge
that one first.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Updated coagent troubleshooting guidance with clearer terminology,
including “open-source” and “GitHub.”
* Renamed the `useCoAgent` troubleshooting section to `useAgent` and
clarified its `agentId` reference.
* Corrected the `useCoAgentStateRender` guidance to reference its `name`
parameter accurately.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What does this PR do?
Fixes 112 broken doc links in the vendored `ag-ui` content tree.
That tree is vendored from `ag-ui-protocol/ag-ui`, where those docs are
served at the **site root** (`docs.ag-ui.com/concepts/events` → 200). On
`docs.copilotkit.ai` the same pages live one level down under `/ag-ui`,
so every root-relative link copied over verbatim 404s:
```
404 https://docs.copilotkit.ai/concepts/events
200 https://docs.copilotkit.ai/ag-ui/concepts/events
```
This is the same class of breakage as the `/concepts/copilot-runtime`
link reported in #2082 and fixed in #5296 — I found the rest while
verifying that PR.
**What changed:** each link that names a real vendored ag-ui page is
repointed at its actual URL — `/concepts/*`, `/sdk/*`, `/drafts/*`,
`/development/contributing`, `/quickstart/applications`, and the bare
`/integrations` (which in these pages means AG-UI's integrations page,
not CopilotKit's). The Kotlin SDK links additionally carried an upstream
`/docs/` prefix (`/docs/sdk/kotlin/core/types`), which is dropped.
**What deliberately did not change:** links that resolve to CopilotKit's
own pages — `/`, `/quickstart`, `/frontend-tools`,
`/integrations/<framework>` — all return 200 today and have no ag-ui
counterpart, so a blanket prefix sweep would have broken them. Each of
the 52 distinct link targets in the tree was checked individually rather
than rewritten by pattern.
Also adds a regression test, because there is no automated sync for this
tree: a future re-vendor from upstream would otherwise silently
reintroduce the same 404s.
## Why not fix this upstream or in the renderer?
- **Not upstream:** these links are *correct* in `ag-ui-protocol/ag-ui`
— that site serves at the root. The breakage is introduced purely by
vendoring under a subpath, so the fix belongs in this copy only.
- **Not in `resolveDocsHref`:** a render-time `/ag-ui` prefix rule would
rewrite the 13 links that legitimately point at CopilotKit pages,
turning working links into 404s. The mapping is not mechanical, so it is
pinned in content and enforced by test.
## Testing
- **New test fails before the change, passes after.** Written first, run
against unfixed content: 112 violations across 27 files. After the fix:
```
✓ src/lib/__tests__/ag-ui-content-links.test.ts (2 tests) 71ms
✓ root-relative links that name an ag-ui page carry the /ag-ui prefix
✓ no links use the upstream /docs/ path prefix
Test Files 1 passed (1)
```
- **Every one of the 38 unique new link targets was fetched against
production:** 35 return 200. The 3 exceptions are pre-existing page
errors, unrelated to link paths (see below).
- **Residue check** — the only root-absolute links left in the tree are
the intended CopilotKit-owned ones:
```
6 / 2 /quickstart 2 /integrations 2 /frontend-tools 11
/integrations/<framework>
```
and no `](/ag-ui/ag-ui` double prefixes or leftover `](/docs/sdk/`
remain.
- `oxfmt --write` + `oxlint` clean on the new test file. No changesets
(docs/test only).
- Pre-existing, unrelated: `src/lib/__tests__/docs-link-rewrite.test.ts`
cannot collect in a fresh worktree because `@/data/setup-content.json`
is generated at build time and untracked. Unaffected by this change.
## Separately: 6 of 8 AG-UI Rust SDK pages return 500 in production
Found while verifying link targets — **not** a link problem and **not**
fixed here; the URLs below are correct and the MDX files exist:
```
500 /ag-ui/sdk/rust/client/agent-trait 500 /ag-ui/sdk/rust/core/types
500 /ag-ui/sdk/rust/client/http-agent 500 /ag-ui/sdk/rust/core/events
500 /ag-ui/sdk/rust/client/subscriber 500 /ag-ui/sdk/rust/core/overview
200 /ag-ui/sdk/rust/client/overview 200 /ag-ui/sdk/rust/overview
```
Only the two `overview` pages render. I ruled out the obvious MDX
hazards (bare `<Generic>` brackets, braces outside code fences,
frontmatter shape, missing `meta.json`) — none correlate with the
failures, so the cause is elsewhere in the page pipeline. Happy to open
a separate issue for it.
## Related PRs and Issues
- Follows #5296 / #2082 (same breakage class, CopilotKit-authored side)
## What
Brings the just-released A2UI support and the latest Microsoft Agent
Framework
(Python) into the showcase, and moves the MAF A2UI demos onto the native
subagent / auto-inject technique so they match the langgraph-python
reference
instead of the pre-1.2.0 hand-rolled path.
- **Bump MAF to 1.2.0.** `agent-framework-ag-ui[a2ui]==1.2.0`,
`agent-framework-openai==1.14.0`, `agent-framework-core==1.15.0`,
`ag-ui-a2ui-toolkit==0.0.4`. 1.2.0 is A2UI's first release; the `[a2ui]`
extra
pulls the toolkit.
- **New `a2ui-recovery` demo** (the one A2UI demo the integration lacked
vs
langgraph-python). Backend-owned via the adapter's native `enable_a2ui`
(`injectA2UITool: false`), which runs the shared toolkit's
validate/retry
recovery loop in-process. Heal pill recovers a malformed first render;
exhaust
pill hits the attempt cap and surfaces the `a2ui_recovery_exhausted`
fallback.
Adds the agent, route, page, chat, suggestions, a D6 fixture, and an e2e
spec.
- **Migrate `declarative-gen-ui` to native A2UI auto-injection.**
Removed the
hand-rolled `generate_a2ui` (a raw secondary OpenAI call to
`_design_a2ui_surface`); the agent now binds no A2UI tool and the route
sets
`injectA2UITool: true`, so the adapter's `plan_a2ui_injection`
auto-injects the
native `generate_a2ui` sub-agent. Reworked the D6 fixture to the native
`render_a2ui` shape.
- **Migrate `beautiful-chat` to native A2UI auto-injection.** Same
change for the
flagship composite: removed its hand-rolled `generate_a2ui`, flipped the
route
to `injectA2UITool: true`. The adapter now auto-injects the native
sub-agent
alongside the agent's own tools (todos, query, flights).
- **`a2ui-fixed-schema` unchanged** — it is the fixed-schema pattern
(client
authored schema, agent streams data via a backend `display` tool,
`injectA2UITool: false`), which langgraph-python does identically. Not
hand-rolled generation.
- **Docs.** Enriched the MAF A2UI docs page into real "how to A2UI"
content
(dynamic / fixed / recovery) and connected the A2UI demos via
`docs-links`.
## Why native (not the dojo's example agents)
The showcase mirrors langgraph-python's frontend-catalog + auto-inject
pattern,
not the AG-UI dojo's `a2ui_config` example agents. Before 1.2.0 the MAF
adapter
had no native A2UI, so the showcase hand-rolled `generate_a2ui`. 1.2.0
ships the
native path, so these demos now use it and match langgraph 1:1.
## Validation
- `validate-pins` clean (FAIL count + hash unchanged), `validate-parity`
PASS,
`generate-registry` clean.
- **D6 (full frontend, aimock replay), all green:**
- `a2ui-recovery` — heal paints the recovered surface; exhaust shows the
hard-failure UI.
- `declarative-gen-ui` — all 4 dashboard pills paint on the auto-inject
path
(confirms the runtime forwards `injectA2UITool: true` and
`plan_a2ui_injection` fires).
- `beautiful-chat` — regression across all 5 features (pie/bar chart,
schedule-meeting, search-flights, toggle-theme): wrapping the multi-tool
agent in the A2UI planner loop does not break its non-A2UI tools.
- **AG-UI protocol layer** (published 1.2.0 wheel + aimock): recovery
(heal/exhaust), declarative, and beautiful-chat all stream real
`a2ui_operations` / `a2ui_recovery_exhausted`, RUN_FINISHED, no
RUN_ERROR.
- **Remove the last hand-rolled A2UI (default agent).** The
general-purpose
default agent (`agent.py`, catch-all `/` endpoint) also carried a
hand-rolled
`generate_a2ui`; removed it (the default agent no longer offers A2UI,
matching
langgraph's default agent). Stripped the stale `_design_a2ui_surface`
fixture
residue and refreshed the e2e-spec comments that described the old
mechanism.
After this PR the MAF-python integration has **zero hand-rolled A2UI
anywhere
except the fixed-schema demo** (which is the intended fixed-schema
pattern,
identical to langgraph). The shared `tools/generate_a2ui.py` module is
intentionally left intact — it is symlinked by other integrations (ag2,
agno, …)
that have not migrated; MAF-python simply no longer imports it.
## Pre-existing, out of scope
Full D6 for ms-agent-python is 37/40. The 3 red cells — `multimodal`,
`voice`,
`hitl-approve-deny` — are **not** touched by this PR: their agents are
byte-identical to main and never used `generate_a2ui`. `multimodal` is
the known
shared-CopilotKit frontend bug (`runStartCount=0`, the run never
starts);
`voice`/`hitl-approve-deny` complete the run but their text does not
settle inside
the probe's tight budget. All A2UI and default-agent cells pass.
## Summary
- Adds a Human-in-the-Loop guide for governed side-effect actions
- Shows a vendor-neutral action envelope with summary, tool, reference,
verdict, and arguments
- Covers allow, deny, and require_approval handling with useInterrupt
and useHumanInTheLoop examples
## Validation
- Parsed human-in-the-loop meta.json and verified governed-actions is
present
- Checked the new MDX frontmatter and required approval terms/hooks
- Confirmed the new guide contains no OSuite/osuite branding
`ag_ui_adk` stores `RunAgentInput.context` in ADK session state under `CONTEXT_STATE_KEY`
and stops there. Nothing puts it in front of the model, so an `LlmAgent` built with a plain
string `instruction` -- the form every ADK quickstart shows -- never sees what
`useAgentContext` sent. The agent still answers, fluently and in the right shape, from
nothing.
Mastra and LangGraph both document their retrieval step. ADK had no Agent App Context page
at all, and `langgraph/programmatic-control.mdx` already linked to a sibling page that did
not exist for ADK. This adds it, with the `InstructionProvider` form that reaches
`ctx.state` and the `tool_context.state` form for a single tool.
The built-in-agent page's "no backend configuration needed" is true of the built-in agent
and reads as a property of the hook, which is the sentence that makes the ADK behaviour
surprising. It now says which agent it speaks for and points at the per-framework pages.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## What does this PR do?
Adds Novita to the list of OpenAI-compatible providers documented for
the built-in agent's model selection, alongside OpenRouter, Ollama,
Together, and Groq. Novita exposes an OpenAI-compatible `/openai/v1`
endpoint, so it works through the existing `createOpenAI({ baseURL })`
pattern already documented for those providers.
A follow-up commit adds a callout clarifying that Novita only implements
the Chat Completions endpoint, not Responses — so readers should call
`provider.chat(model)` rather than the bare `provider(model)` form shown
in the adjacent OpenRouter example, which routes through Responses and
would error on Novita's endpoint.
## Related PRs and Issues
- None
## Verification
- `npm run typecheck` — pass
- `npm run test` — 55/55 files, 374/374 tests pass
- `npm run build` — Next.js production build succeeded, 222/222 static
pages generated
- Live verification: called Novita's OpenAI-compatible endpoint via
`createOpenAI({ baseURL }).chat(model)` with model
`deepseek/deepseek-v4-pro-0813` — HTTP 200, finish reason `stop`, usage
populated
## Checklist
- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [ ] "Allow edits by maintainers" is checked
The "Advanced — Action Handlers" link pointed to
`./advanced#action-handlers`, but there is no `advanced.mdx` page in
`docs/generative-ui/a2ui/`. The "Action handlers (reference)" section
lives in this same file, so the link now points to it directly with
`#action-handlers-reference`.
The two "agent name" accordions on the LangGraph troubleshooting page each
carried the other one's hook name, so a reader debugging "agent not found"
got contradictory guidance:
- The accordion titled `useCoAgent` showed a `useAgent({ agentId })` sample.
- The accordion titled `useCoAgentStateRender` told the reader to check
"the `useAgent` hook" while showing a `useCoAgentStateRender({ name })`
sample.
Align each accordion's title and prose with the hook its code sample actually
uses, and name the specific prop to match — `agentId` for `useAgent`, `name`
for `useCoAgentStateRender` — since the differing prop name is the actual
gotcha. Also fixes the "the that" and "use n" typos on those two lines.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The A2UI overview pages for both the DeepAgents and LangGraph
integrations link to ./fixed-schema-streaming, but that file does not
exist (only dvanced, dynamic-schema, ixed-schema, index, styling
exist). Point both links to the existing ./fixed-schema page.
## Summary
- replace the homepage Channels activation block with an Intelligence
onboarding prompt focused on Learning
- place the same onboarding prompt across framework quickstarts, with
feature-specific copy for Learning and Rich Threads
- generate the CLI run ID only when the prompt is copied and record
successful copies in PostHog
- use existing local Lucide icons with no additional package or external
font dependency
## Experiment
The CTA uses one canonical agentic onboarding prompt everywhere while
changing the product promise by surface. Learning placements explain
Rich Threads, Learning, and support for new or existing agents. Threads
placements focus on persistent conversations.
Successful copies emit `docs.intelligence_onboarding_prompt_copied` with
`feature`, `from_path`, `run_id`, and `surface`. The same `run_id` is
embedded in the copied CLI command.
## Validation
- `pnpm exec oxfmt --check` on changed TypeScript files
- `npm run lint` in `showcase/shell-docs` (no errors; existing warnings
remain)
- `npm run typecheck` in `showcase/shell-docs`
- `vitest run src/lib/__tests__/inspector-docs.test.ts --maxWorkers=1`
(10/10 passed)
- memory-capped `npm run build` in `showcase/shell-docs`
- manual desktop, mobile, light-mode, and dark-mode checks on `/`,
`/threads`, and a framework quickstart
The full Shell Docs test command currently also reports failures
unrelated to this change, including unhydrated Git LFS image fixtures
and generated-doc baselines on current `main`. The affected Inspector
docs test passes independently.
Vue ships CopilotThreadsDrawer and useThreads but no page documents
them, so an integration guide that needs to name a Vue threads page has
nothing to cite. Adds the guide, modelled on the Angular one.
Needed by CopilotKit/Intelligence OSS-1033, whose conversion leg cites
this URL.
## Notes
Corrected against the source while writing this
(`packages/vue/src/v2/components/chat/CopilotThreadsDrawer.vue`,
`packages/vue/src/v2/hooks/use-threads.ts`):
- The "drawer + chat as bare siblings" example in the draft would not
actually sync selection to the chat — `CopilotThreadsDrawer` only calls
`config.value?.setActiveThreadId(...)` when a
`CopilotChatConfigurationProvider` ancestor exists; a sibling
`CopilotChat` provides its own config internally, which a sibling drawer
can't see. Wrapped both in a shared `CopilotChatConfigurationProvider`,
matching how the Angular guide documents the same pattern.
- `Thread.name` is `string | null`, not `title`; fixed the headless
example to use `name` with a fallback for `null`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Correcting the ticket first
OSS-1037 was filed on a wrong diagnosis, mine. It said the Vue
generative-UI guide was unreachable because of a routing defect. It is
not:
```
docs.staging.copilotkit.ai/vue/guides/generative-ui.md 200
docs.copilotkit.ai/vue/guides/generative-ui.md 404
```
The page is merged, built, and live on staging. `showcase_promote.yml`
is `workflow_dispatch` only — *"Humans trigger. No automatic prod
promotes."* — so prod is simply behind. The same is true of
`pydantic-ai/agent-app-context.md` (added 08-28, also 404 on prod, 200
on staging), while pages from 08-24 are live. Nothing about Vue is
broken, and there is nothing here to "publish".
So this PR does the one thing that *was* actually wrong with the guide.
## What was wrong
`@copilotkit/vue/v2` exports its own `useComponent` — a Vue-native
composable, not the React one — and the guide never named it. Not in the
path table, not in the body, not in the closing reference list.
Its path table sent "your components" to `useRenderTool`, or
`useFrontendTool` with a `render`. Both work, and both ask the reader
for more than the display-only case needs: the agent shows a component
and nothing else runs. It is also the case the onboarding graph now
tells a Vue run to reach for, so a developer arriving at this guide
afterwards would not find the hook they had just been told to use.
## What changed
- A path-table row for the case: **A component the agent shows** →
`useComponent`. The existing row is re-scoped to what it is actually for
— the agent already owns the tool and you draw its call.
- A **Let the agent display a component** section, placed before the
server-side section because it is the shorter path. Vue SFC component
plus registration, with the schema arriving as props.
- A callout answering the question a reader will have — `useComponent`
or `useRenderTool`? The give-away is where the tool lives: if removing
the component would remove the tool from the agent's list, it is a
`useComponent`.
- The grounding warning. The model fills these props from what it knows,
so a card rendered over records the application does not hold looks
identical in a browser, a screenshot and a video to a correct one.
Points at `useAgentContext`.
- `useComponent` added to **Next steps**.
Every URL the new section cites was probed and returns 200:
`reference/vue/hooks/useComponent`,
`reference/vue/hooks/useAgentContext`,
`reference/vue/hooks/useRenderTool`.
## Testing
New `vue-generative-ui-docs.test.ts`, written first and confirmed red
(`expected '---\ntitle: Generative UI in Vue…' to contain
'useComponent'`). It asserts against the raw source, the loaded doc, and
the rendered llm-text, following `deepagents-interrupt-docs.test.ts`,
and separately asserts that a **path-table row** names the composable —
naming it only in prose would leave the table still recommending the
longer route for the simpler job.
`showcase/shell-docs`: 68/70 files, 487 tests pass. The 2 failures are
pre-existing on `main` and read files this branch does not touch — a
shared inspector snippet that says "Playground", and mastra
tool-rendering content.
Closes OSS-1037
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Why
OSS-1034 makes `/<framework>/generative-ui/tool-based.md` the terminal
page every onboarding run fetches, on all 19 framework routes. That
page's `## How it works in code` section is a bundled
`frontend-tools-setup` concept, and only **5 of 19** frameworks shipped
one.
Where the concept is unbundled, `FrameworkSetup` returns `null` and the
section renders nothing. Absence encoded two different facts and nothing
separated them:
- this framework needs no agent-side wiring, or
- it needs some and nobody wrote it down.
For the 5 that had a snippet, the requirement is substantial and
load-bearing — ADK's `AGUIToolset()` in the `tools=` list, LangGraph's
`CopilotKitMiddleware` / `CopilotKitStateAnnotation`, Claude SDK's
Messages-API tool conversion. So "nobody wrote it down" was a live
possibility for the other 14, not a theoretical one.
## Coverage: 6 → 10 of 19
Four frameworks whose own `gen-ui-tool-based` demo agent settles the
question. I used the demo agents as the evidence rather than the docs,
because the demos are the thing that actually runs.
**Nothing to wire** — `pydantic-ai`, `llamaindex`, `ms-agent-python`.
Their demo agents declare no tools at all and say why in as many words:
> *"CopilotKit's runtime injects those tool definitions into the agent
request at runtime, so the agent does not need to declare them locally —
PydanticAI's AG-UI bridge surfaces frontend-registered tools to the
model on each run."*
> — `showcase/integrations/pydantic-ai/src/agents/gen_ui_tool_based.py`
Their snippets say that, and then say the half that is easy to miss:
**the tool arriving is not the same as the model calling it.** Every one
of those demo agents carries a `SYSTEM_PROMPT` naming the tool. Omit it
and the agent answers in prose while the component never renders — which
looks like a broken integration and is not one.
**Real wiring** — `crewai-crews`. The opposite case, and the one the
silence was hiding. A Flow owns its own model call, so the forwarded
tools do not reach the model unless the Flow passes them: read
`state.copilotkit.actions`, hand them over as `tools=`, wrap in
`copilotkit_stream` so the call reaches the browser as it streams, and
drive `tool_choice`. Its own demo comments on why:
> *"Force the chart on the user's turn. Once the browser has returned
the render result the follow-up is plain narration, so leaving this on
'auto' is what ends the run."*
I did **not** write snippets for the nine I could not establish from
source. Guessing "nothing is required" into the docs is worse than the
silence it replaces.
## A compile failure is no longer silent
```ts
// before — both states returned null
if (source === null) return null; // nobody bundled it: deliberate
} catch (err) { console.error(...); return null; } // bundled and broken: a defect
```
A snippet that fails to compile shipped looking exactly like a framework
with no requirement, and the only trace was a `console.error` nobody
reads in production. Absence stays quiet; a broken snippet now throws.
This is the shape `llm-text.ts` already refuses for
`channels-agent-setup`.
## The remaining nine are named, not silent
`frontend-tools-setup-coverage.test.ts` holds
`REQUIREMENT_NOT_ESTABLISHED` — `ag2`, `agno`, `built-in-agent`,
`deepagents`, `mastra`, `ms-agent-dotnet`, `ms-agent-harness-dotnet`,
`strands`, `strands-typescript`. Two tests bind it in both directions: a
framework serving the page with no snippet and no listing fails, and a
listed framework that has since been documented fails until its name is
removed. So a new framework cannot join the gap quietly, and closing one
is a deletion.
That test earned its keep immediately — it caught that I had written
`aws-strands` (the docs folder) where the registry slug is `strands`.
A third test asserts the two snippet shapes stay distinguishable, so a
future edit cannot quietly turn the CrewAI wiring into a "nothing
required" note.
## Testing
- `setup-concept.test.ts` — 2 new tests, the compile-failure one
confirmed red before the fix.
- `frontend-tools-setup-coverage.test.ts` — 3 new tests.
- `showcase/shell-docs`: 487 tests pass. The 2 failures are pre-existing
on `main` and read files this branch does not touch.
- Formatting: my files pass `oxfmt`. The two `claude-sdk-*` snippets it
also flags are pre-existing and untouched here.
## Not done
The nine frameworks above. Each needs its AG-UI adapter and demo agent
read, then a snippet — including where the honest content is "nothing is
required". Left on OSS-1036.
Refs OSS-1036
🤖 Generated with [Claude Code](https://claude.com/claude-code)
`generative-ui/tool-based` is now the terminal page every onboarding run fetches
(OSS-1034), and its "How it works in code" section is a bundled
`frontend-tools-setup` concept. Only 5 of 19 frameworks shipped one, so for the
rest the section rendered nothing and absence encoded two different facts: this
framework needs no agent-side wiring, or it needs some and nobody wrote it down.
Four frameworks whose own gen-ui-tool-based demo agent settles the question get
a snippet. pydantic-ai, llamaindex and ms-agent-python declare no tools at all --
the AG-UI request forwards them and their demo agents say so in as many words --
so their snippet states that, and then states the half that is easy to miss: a
model with no instruction about the tool answers in prose and the component never
renders. CrewAI is the opposite case. A Flow owns its own model call, so it has
to read `state.copilotkit.actions` and pass them itself, wrap the call in
`copilotkit_stream`, and drive `tool_choice`.
A compile failure in a bundled snippet no longer returns null. It shared that
return with "nobody bundled this", so a rendering defect shipped looking exactly
like a deliberate omission, traceable only through a console.error nobody reads
in production. Absence stays quiet; a broken snippet throws.
The nine frameworks still undetermined are named in a list a test reads, so a new
framework cannot join the gap silently and closing one means deleting a name.
Refs OSS-1036
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`@copilotkit/vue/v2` exports its own `useComponent`, and the guide never named
it. Its path table sent the display-only case -- the agent shows a component and
nothing else runs -- to `useRenderTool` or `useFrontendTool` with a `render`,
both of which ask the reader for more than that case needs, and neither of which
is what the onboarding graph now tells a Vue run to reach for.
The guide gains a row for the case, a section that teaches the composable, and
the distinction that decides between the two: `useComponent` declares the tool
from the frontend, `useRenderTool` draws a tool the agent already owns. It also
carries the grounding warning, because a card rendered over records the
application does not hold looks the same in a browser as a correct one.
Refs OSS-1037
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Angular had no counterpart to `useComponent` in react-core and vue, so the only
way to let an agent display one of your components was `registerFrontendTool`
with a handler the component does not need, or `registerRenderToolCall`, which
requires the tool to already exist in the agent.
`FrontendToolConfig.handler` becomes optional, and `#bindClientTool` returns the
config unwrapped when it is absent. Core already has the render-only path: a tool
declaring no handler gets an empty tool result and completes the turn. Binding a
wrapper regardless called `undefined` on the first tool call, and a stub handler
would write a fabricated result into the thread instead.
`registerComponent` is that shape with the model-facing description built for it,
identical to the one react-core and vue build, so the tool reads the same to the
model whichever frontend registered the component. The component stays an
ordinary `ToolRenderer` reading `toolCall().args`.
The tool is declared by the frontend and forwarded over AG-UI, so a display-only
component needs nothing added to the agent, on any framework.
Refs OSS-1034
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## What does this PR do?
Adds `getLearningContainerId` to `CopilotKitIntelligence` so developers
can assign Intelligence Threads to Learning Containers without a
theta-prefixed Runtime option.
The selector receives:
- The resolved application `user`.
- The parsed AG-UI `input` for the run.
- The `agentId` and the `web` or `channel` surface.
Web runs pass the exact parsed `RunAgentInput`. Channel runs build the
same canonical input that the AgentRunner receives. Channels also carry
the resolved application user through the core and Intelligence adapter
boundaries.
The Runtime validates the selected stable ID and sends only that ID with
the existing Thread create or lock call. Intelligence stays responsible
for project scope, entitlements, Container lookup, and the one-time
Thread binding. Persisted AG-UI events remain the source for Learning
snapshots.
The old `ɵlearning` Runtime option remains as a deprecated fallback. The
Runtime rejects configurations that set both APIs.
## Why?
Learning Container assignment is an Intelligence SDK concern. Developers
also need the resolved user and complete run input to select a Container
from application data without reading raw transport details.
## Related PRs and Issues
- Refs
[ENT-1149](https://linear.app/copilotkit/issue/ENT-1149/enable-projects-to-learn-from-agent-runs-and-publish-reusable-skills)
- Related design: #6746
## Validation
- GitHub CI: 53 passed, 3 skipped
- `pnpm nx run-many -t test,check-types,build -p @copilotkit/runtime
@copilotkit/channels-core @copilotkit/channels-intelligence`
- `pnpm nx run-many -t publint,attw,check-dts -p @copilotkit/runtime
@copilotkit/channels-core @copilotkit/channels-intelligence`
- `pnpm lint` (0 errors; existing warnings remain)
- `npm run typecheck` and `npm run build` in `showcase/shell-docs`
- `npm test` in `showcase/shell-docs` has one pre-existing failure at
`inspector-docs.test.ts:141`: the tracked Threads callout contains
`Playground`.
## Checklist
- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] Maintainer edits are available because this PR uses a branch in
the main repository
## Problem
Pydantic AI's AG-UI adapter reads `messages`, `tools`, `state`,
`thread_id` and `resume` off `RunAgentInput`, and nothing else.
`context` — the field `useAgentContext` travels on — is never passed to
the agent.
Nothing errors when it is dropped. There is no warning and no console
message, so an agent that received none of the page's entries still
answers confidently about them. A developer who wires `useAgentContext`
against a Pydantic AI agent gets a well-formed answer about data the
agent never had.
Verified against `pydantic-ai-slim` 2.33.0 and current upstream `main`:
zero references to `run_input.context` across all nine modules in
`pydantic_ai/ui/ag_ui/`.
## Why there was no page
The omission is deliberate upstream, not a bug.
[pydantic/pydantic-ai#7105](https://github.com/pydantic/pydantic-ai/issues/7105)
was closed as completed by
[#7106](https://github.com/pydantic/pydantic-ai/pull/7106): `run_input`
is public, so `adapter.run_input.context` has always worked, and
auto-injecting client-submitted text into `instructions` would let a
prompt injection inherit operator authority. Upstream documented the
route instead of adding API.
What was missing was a CopilotKit page saying any of this.
`useAgentContext`'s reference page documents the frontend hook only, and
the four existing `agent-app-context` pages cover built-in-agent,
langgraph, mastra and microsoft-agent-framework.
## What's here
`pydantic-ai/agent-app-context.mdx`, the fifth such page, wired into the
integration's App Control nav after `shared-state`.
Two details the page pins down, both verified against a running agent
rather than adapted from a sibling page:
- **`value` is a string, not your object.** `useAgentContext` calls
`JSON.stringify` before the run leaves the browser, and AG-UI types
`Context.value` as a string on both ends. `json.loads` is required, and
a shape check like `isinstance(entry.value, list)` can never pass. A
failed check is indistinguishable from context never being sent, which
is what makes this one expensive.
- **`from_request`, not `dispatch_request`.** The one-line
`AGUIAdapter.dispatch_request(request, agent=agent)` used elsewhere in
these docs parses the request internally, leaving no `run_input` to
build `deps` from. The context route needs the two-step form.
The page also carries upstream's trust rule: entries reach the model as
tool output, never as `instructions`, and facts the *server* established
are what belong in instructions.
## Verification
The documented `agent.py`, served over real HTTP with AG-UI request
bodies shaped exactly as the runtime sends them:
| Case | Result |
|---|---|
| Asks about the shared entries | Answers from them, all three
colleagues |
| Asks about someone never sent | Declines, and names exactly the three
the page did send |
| `context` arrives empty | Reports an empty list rather than inventing
one |
Suite: **480 passed / 2 failed**. Both failures (`inspector-docs`,
`llm-text` mastra tool-rendering) reproduce identically on pristine
`origin/main` content — confirmed by reverting both files and
re-running.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Pydantic AI's AG-UI adapter reads `messages`, `tools`, `state`, `thread_id`
and `resume` off `RunAgentInput`, and nothing else. `context` -- the field
`useAgentContext` travels on -- is never passed to the agent, and nothing
errors when it is dropped, so an agent that received none of the page's
entries still answers confidently about them.
That omission is deliberate upstream (pydantic/pydantic-ai#7105, closed by
#7106): entries are client-submitted, so the adapter leaves it to the
application to decide what to trust, and `run_input` is public for exactly
this purpose. What was missing on our side was a CopilotKit page saying so.
Add `pydantic-ai/agent-app-context.mdx`, the fifth such page, alongside
built-in-agent, langgraph, mastra and microsoft-agent-framework, and wire it
into the integration's App Control nav.
Two details the page pins down, both verified against a running agent rather
than adapted from a sibling page:
- `useAgentContext` JSON-stringifies `value` and AG-UI types
`Context.value` as a string on both ends, so `json.loads` is required and
a shape check like `isinstance(entry.value, list)` can never pass.
- The one-line `AGUIAdapter.dispatch_request(request, agent=agent)` used
elsewhere in these docs parses the request internally, leaving no
`run_input` to build `deps` from. The page uses the two-step
`from_request` form instead.
The page also carries upstream's trust rule: entries reach the model as tool
output, never as `instructions`, so a prompt injection cannot inherit
operator authority.
Verified: the documented `agent.py` served over HTTP answers from the shared
entries, names exactly what the page did send when asked about a colleague it
did not, and reports an empty list when `context` arrives empty. Suite is
480 passed / 2 failed, both failures identical on pristine origin/main.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## The bug
`src/polyfills.ts` is five side-effect-only imports plus
`installStreamingFetch()`. The published barrel was 195 bytes:
```js
// node_modules/@copilotkit/react-native/dist/polyfills.mjs — 1.69.2
import { t as installStreamingFetch } from "./streaming-fetch-BnQh3vBz.mjs";
installStreamingFetch();
export { };
```
Every React Native app following the documented setup died on its first
runtime call:
```
E ReactNativeJS: '[CopilotKit] Error (runtime_info_fetch_failed):',
[ReferenceError: Property 'ReadableStream' doesn't exist]
```
## Root cause
The `sideEffects` field, but not in the way it first looks. It is
correct for *consumers* and wrong for *this package's own build*:
```json
"sideEffects": ["./dist/index.*", "./dist/headless.*", "./dist/polyfills.*", "./dist/polyfills/**/*"]
```
tsdown/rolldown reads the package's own `sideEffects` while bundling and
matches it against **source** paths. `src/polyfills/streams.ts` matches
none of those `dist` globs, so it is declared side-effect-free — a hard
assertion that lets rolldown drop the import without analysing the
`globalThis` assignments inside.
Reproduced in isolation at the pinned tsdown (0.20.3):
| `sideEffects` | built barrel |
|---|---|
| `["./dist/polyfills.*", "./dist/polyfills/**/*"]` | `export { };` —
empty |
| same + `["./src/polyfills.*", "./src/polyfills/**/*"]` | `import
"./polyfills/streams.mjs";` |
| field absent | `import "./polyfills/streams.mjs";` |
**Wider than the ticket recorded:** `dist/index.mjs` and
`dist/headless.mjs` also had zero polyfill code, so the package's
advertised auto-install on first import did not happen either. Not
RN-specific in principle — but I surveyed every package at `origin/main`
and this is the only one exposed. The other `sideEffects` arrays
(`react-core`, `react-ui`, `react-textarea`) are `["**/*.css"]`, which
matches source and works.
## The fix
Add matching `./src/**` globs. Barrel goes 195B → 362B with all five
imports; `headless.mjs` now leads with `import "./polyfills.mjs"`.
## The test, and why the existing one didn't catch this
`src/__tests__/polyfills.test.ts` has ~20 assertions covering all five
groups and was green the whole time — it imports `"../polyfills"`, the
TypeScript **source**, which vitest transpiles without bundling and
therefore without tree-shaking. It exercises a graph the published
package does not contain.
So the new check runs against `dist/`. Two things it has to get right to
be honest:
- **Node ships these globals natively.** Asserting `ReadableStream` is
"defined" after import passes on an empty barrel. The probe clears all
nine first, emulating Hermes.
- **The two formats need different treatment.** CJS is executed for real
in a child realm. ESM is checked structurally — it cannot be executed
here because `encoding.mjs` takes a named import from CommonJS
`text-encoding`, which Metro rewrites to a `require()` but bare Node ESM
rejects.
It is wired into `build`, so a dead barrel fails the build rather than
reaching npm — which matters, because this shipped through a fully green
suite.
## Docs
Added the `Property 'ReadableStream' doesn't exist` symptom to
troubleshooting, which previously covered only the inverse case (a
polyfill *conflict*).
I deliberately left the reference docs' "auto-installs on first import"
claims and the crypto import-order callout alone: both become **true**
once the build is fixed, and I verified the auto-install behaviourally.
## Verification
- **Red/green proven, not assumed:** reverted the `sideEffects` change,
rebuilt → 5/5 groups FAIL in both formats. Restored → 5/5 PASS. There is
also a test for a *single* group regressing, which a whole-barrel
assertion would wave through.
- **Packed tarball** (`pnpm pack`) verified behaviourally: all nine
globals install.
- 289 vitest + 26 script tests pass; `check-types` clean; `attw` green;
`publint` clean apart from a pre-existing `repository.url` suggestion;
oxfmt/oxlint clean.
- Added `{projectRoot}/scripts/**` to the package's `test` inputs and
confirmed cache invalidation (19/19 cached → 18/19 after touching the
verifier); without it, editing the verifier alone would restore a cached
pass.
**Not verified:** the on-device round trip — no emulator in this
environment. The bare-realm equivalent passes on the packed tarball.
## Follow-up worth its own ticket
`dist/polyfills/encoding.mjs` uses a named import from CommonJS
`text-encoding`. Metro handles it; a true-ESM consumer would not.
Pre-existing and not RN-facing, so left out of this change.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Five onboarding-sweep defects that share one shape: a page states something the
library stopped doing, or never said something the library requires.
Mastra `resourceId` (OSS-936) — `getLocalAgents({ mastra })` does not typecheck
against `@ag-ui/mastra`; `resourceId` is required. It is Mastra's memory-scoping
key, required identically on the local, single-agent and remote option types, so
the snippets were wrong rather than the type over-strict. Fixed at all six doc
sites, including the tracing example that #6663 left behind.
Angular Inspector (OSS-948) — `@copilotkit/angular@0.4.0` ships the auto-mount
with a pinned `@copilotkit/web-inspector`. The Angular Inspector page still
taught a hand-written mount whose unconditional `DestroyRef.onDestroy` tears out
the element the framework now owns. Rewritten as a thin migration page that
points at `/inspector` instead of restating it, and the Angular Open Inspector
snippet — which asserted "Angular does not mount Inspector by default" — is
deleted in favour of the shared one every other web frontend already uses.
Angular runtime port (OSS-950) — say plainly that the runtime is its own
process, and name `PORT` as the way to move it off 8200. `COPILOT_RUNTIME_PORT`
appears nowhere in either repo and is not the mechanism.
`copilotkit verify` (OSS-953) — documented nowhere in the product docs. Added to
the shared CLI snippet, stating what `--round-trip` cannot prove: it records the
answer's character count and tool-call names, never its text, and proves an
agent answered under the declared id, not which deployment. React Native now
links that section rather than restating it, and its claim that the CLI defaults
to `:8200` is corrected to the real default, `:3000`.
A2UI flight example (OSS-944, part) — mark the domain illustrative on the page
the onboarding graph is mandated to fetch. The domain swap itself is not here:
it is 106 files across 21 showcase cells and wants the post-OSS-942 re-run
first.
Also fixes a shipped skill that taught `import { CopilotKitWebInspector }`, an
export that does not exist (OSS-891's failure mode, found in passing).
Two new tests guard the Angular claims, both mutation-checked.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Inspector Threads now has **Try from here**. One click copies a stored
thread into a Playground scratch session. The stored thread does not
change.
If the copy fails, Inspector stays on Threads and keeps the current
Playground scratch. Example tour threads and locked Threads do not show
the button.
## What does this PR do?
Adds **Try from here** on a real stored thread in Inspector Threads. One
click copies messages and thread state into a Playground scratch
session. The stored thread does not change.
If the copy fails, Inspector stays on Threads and keeps the current
Playground scratch. Example tour threads and locked Threads do not show
the button.
## Related PRs and Issues
- Linear: OSS-873
- Playground base: https://github.com/CopilotKit/CopilotKit/pull/6580
(merged)
## Checklist
- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] "Allow edits by maintainers" is checked
## Testing
**Commands run**
1. Rebased `feat/oss-873-try-from-here` onto `origin/main` and resolved
6 conflict files.
2. `npx nx run @copilotkit/web-inspector:test` — 626 tests passed (after
the stale-result guard).
3. `npx nx run @copilotkit/web-inspector:check-types` — passed.
**Manual test**
1. Open Inspector on localhost with Intelligence on, so a real stored
thread exists.
2. Open that thread. Confirm **Try from here** is in the thread header.
3. Click **Try from here**. Confirm Inspector opens Playground with the
copied messages and the stored thread is unchanged.
4. Open an example tour thread. Confirm **Try from here** is not shown.
5. Force a copy failure (disconnect runtime). Confirm Inspector stays on
Threads and the prior Playground scratch is unchanged.
**How this PR makes testing easy**
- `packages/web-inspector/src/__tests__/inspector-navigation.spec.ts`
covers the button, copy path, failure path, and a stale click that must
not overwrite Playground.
- `packages/web-inspector/src/lib/__tests__/telemetry.test.ts` covers
`oss.inspector.threads_try_from_here_clicked`.
## Risk / rollback
Risk is limited to Inspector Threads and Playground. A revert of this PR
removes the button and the new telemetry event. No runtime protocol
change.
## Public API change
New Inspector telemetry export and event name:
**Before**
```ts
trackThreadsTabClicked(props);
```
**After**
```ts
trackThreadsTabClicked(props);
trackThreadsTryFromHereClicked({ ...props, outcome: "success" });
```
`CpkThreadInspector` also emits a `tryFromHere` custom event when the
user clicks the button.