Commit Graph

5277 Commits

Author SHA1 Message Date
Martha Kelly Schumann 6dab592b30 docs(ag-ui): fix applications quickstart route (#6829)
## Summary

- sync the AG-UI applications quickstart with the corrected root route
- add coverage that rejects the stale `/copilotkit` URL

## Testing

- `npm test -- src/lib/__tests__/ag-ui-content-links.test.ts`
- `npm run typecheck`
- `git diff --check origin/main...HEAD`

Linear: FAC-123
2026-09-01 11:29:03 -07:00
copilotkit-qa-bot[bot] 84dd92485b docs: sync corrected AG-UI quickstart route 2026-09-01 11:07:34 -07:00
copilotkit-qa-bot[bot] f236329630 test(runtime): harden request auth isolation coverage 2026-09-01 08:39:00 -07:00
copilotkit-qa-bot[bot] 15f80f880e docs: clarify browser-controlled LangGraph config 2026-09-01 07:49:58 -07:00
copilotkit-qa-bot[bot] 9c5a3ead46 Merge remote-tracking branch 'origin/main' into codex/fac-121-configurable-channels 2026-09-01 07:47:35 -07:00
Lukas Moschitz 1a5af3890c Merge remote-tracking branch 'origin/main' into lukas/oss-1072-overview-incorporate-agent-onboarding-prominently 2026-09-01 15:10:08 +02:00
Lukas Moschitz 8bad102f16 test(showcase/harness): refresh the decommission report snapshots
The report is rendered from the live redirect table, and these two
fixtures pin it byte-for-byte. Adding INTEL-observability-root and
P7-intelligence to the shell table moves the entry count from 388 to
390 and lists both new ids among the zero-hit candidates.

Regenerated with the same inputs the test uses, so the diff is only the
two counters and the two new id lines.

Refs OSS-1078
2026-09-01 14:55:05 +02:00
Lukas Moschitz d776097afa test(showcase/shell-docs): expect the renamed Intelligence paths
Eight suites assert on the old paths — sitemap URLs, file existence,
loadDoc slugs and the Angular canonical-slug mapping. In the redirect
suite only the destinations move; the /premium/observability sources
stay, since a redirect source describes a URL that must keep resolving.

Refs OSS-1078
2026-09-01 14:00:51 +02:00
Lukas Moschitz 91ee5aa764 fix(showcase): 301 the legacy premium URLs onto the renamed Intelligence tree
/premium/* is an indexed URL surface, so the folder rename needs a
redirect for every old path — at the root and under each of the 22
canonical and 14 legacy framework slugs. A wildcard covers the tree
(including future pages and the .md/.mdx LLM variants); exact entries
cover the bare folder URLs, which no wildcard prefix can match.

Existing entries that pointed INTO the tree are repointed: the retired
observability pages, the premium folder index, and four next.config
destinations. Sources are left untouched — they describe URLs that must
keep resolving.

Two entries in next.config keep the built-in-agent surface at one hop:
its generic prefix-stripping catch-all runs before the middleware and
would otherwise hand the middleware a /premium/ path to rename in a
second hop.

The shell host and the harness probe carry their own copies of the
table, and the harness header requires them to stay in sync or the
decommission report surfaces phantom zero-hit entries. Both updated.

Refs OSS-1078
2026-09-01 14:00:37 +02:00
Lukas Moschitz eadc026341 fix(showcase/shell-docs): point the docs renderer at the renamed Intelligence tree
Three maps key off the content path or the URL slug: the shared-snippet
registries in docs-render and mdx-registry, the slug-to-component maps,
and the Angular canonical-slug map. All of them still named premium, so
after the folder rename the shared Overview, SelfHosting, Inspector and
HeadlessUI snippets would resolve to a path that no longer exists.

Refs OSS-1078
2026-09-01 14:00:21 +02:00
Lukas Moschitz e250256789 docs(showcase/shell-docs): move the Intelligence docs tree off the premium path
The product is called Intelligence, but the docs served it under
/premium/ — including a per-integration premium/ folder in twelve
integrations. Readers and coding agents both hit a URL naming a tier
that no longer exists.

Renames the folder to intelligence/ at the root, in the twelve
integration trees, and in the shared snippets, and rewrites every
inbound link. Page slugs are deliberately unchanged so the redirect
surface stays a pure prefix rename.

Also drops the premium: true frontmatter key from fourteen pages: no
code reads it, so it was dead. The one remaining piece of tier prose,
a "Premium UI capabilities" table cell, becomes "Platform-gated UI
capabilities".

Analytics surface identifiers (docs_premium_*) are left verbatim —
renaming them would silently break the PostHog dashboards that read
them. They are internal event names, not docs content, and belong in
their own change.

Refs OSS-1078
2026-09-01 14:00:03 +02:00
Lukas Moschitz 5cd54dbc90 fix(docs): match the hero prompt button to the ticket wording (refs OSS-1072)
The label is now "Copy onboarding prompt", the wording OSS-1072 asks for, and
the hint line under the action row is gone — the label already names what gets
copied, so the second line only repeated it. With nothing below the row,
HeroStartActions collapses to the row itself instead of wrapping it.
2026-09-01 13:05:37 +02:00
Lukas Moschitz 8bfcfc02ce feat(docs): lead the hero with the coding-agent prompt (refs OSS-1072)
The docs hero offered three competing entry points: a Quickstart picker, a
CLI command menu, and — buried below the fold — the onboarding prompt a
developer hands to their coding agent. The prompt is the path we want people
on, so it moves into the hero and takes the accent, Quickstart steps down to
the bordered treatment beside it, and the CLI command menu goes away with the
`create` command and the "Build with agents" link it carried. A muted hint
line names where the copied prompt is meant to go, which the removed menu
used to make obvious by showing its command inline.

The prompt is identical on every surface: the CLI's onboarding graph inspects
the repository and picks its own path, so a framework-scoped variant would be
a promise the CLI does not keep. HeroStartActions stays shared verbatim, so
the eleven framework landing pages using it get the same row. The four
frameworks with bespoke init commands render a different branch and are
untouched.

QuickstartLinkButton gains a `variant` prop defaulting to primary, so those
bespoke landing pages keep their only hero button looking unchanged.
2026-09-01 12:53:19 +02:00
lukasmoschitz 5195118345 showcase: rename byoc-* QA docs to declarative-* in 7 integrations (#6800)
## Why

`showcase/scripts/validate-parity.ts` keys spec and QA filenames to the
demo id. Seven integrations still carried the pre-rename `byoc-*` names
for the hashbrown / json-render demos, so the validator emitted spurious
`demo 'declarative-hashbrown' has no qa/declarative-hashbrown.md` style
warnings.

**454 → 446 warnings, still 21/21 pass.**

## What changed

**QA docs (14 files, all 7 integrations)** — renamed `qa/byoc-*.md` →
`qa/declarative-*.md` and reconciled against the `langgraph-python`
north star. Test Steps and Expected Results are now identical per demo
across every integration; genuinely per-integration facts (agent mount
path, env var, prompt module, preserved regression guards) live in an
`Integration notes` section. Every fact was verified against source —
pill labels, `data-testid`s, header text, package pins, API route →
`AGENT_URL` mappings — rather than carried over from the old doc.

**E2E specs (10 files, 5 integrations) — deleted, not renamed.** Those
integrations already ship `declarative-hashbrown.spec.ts` /
`declarative-json-render.spec.ts` byte-identical to the north star (md5
`57eee13d…` / `638e2ac4…`). The `byoc-*` copies point at `/demos/byoc-*`
routes that no longer exist and assert little beyond "page loads", so
renaming them would have clobbered the good specs. Spec counts stay
above demo count in all five packages, so no under-coverage warning
appears.

Python backend modules keep their `byoc_` prefix
(`byoc_hashbrown_agent.py`, `byoc_json_render_agent.py`) — the north
star uses those names too and integration `manifest.yaml` files
reference them under `highlight:`.

`claude-sdk-python` is deliberately untouched (handled in OSS-578 /
#6235).

## Found along the way, NOT fixed here

1. **`declarative-json-render` is broken in both crewai packages.** The
demo page (a north-star copy) mounts
`runtimeUrl="/api/copilotkit-declarative-json-render"`, but those
packages only ship `src/app/api/copilotkit-byoc-json-render/route.ts`,
and `next.config.ts` has no covering rewrite — the runtime URL 404s. The
rename was only half applied: page renamed, API route not. Documented as
a known break in the affected QA docs; fixing it is a runtime change, so
it wants its own PR.
2. **`langgraph-python/qa/declarative-json-render.md` still has the
stale title** `# QA: BYOC json-render — LangGraph (Python)`. Left alone
so as not to collide with #6235.

Minor, also left as-is: `crewai-*/src/app/demos/byoc-hashbrown/page.tsx`
are one-line alias re-exports of the declarative page, and the
`crewai-*` / `llamaindex` manifests still list `byoc-hashbrown` /
`byoc-json-render` under `features:` (a separate id namespace the
validator does not read).

## Verification

```
cd showcase/scripts && npx tsx validate-parity.ts
# 21 package(s) checked, 21 pass, 0 fail, 446 warning(s)
```

Diff of validator output before/after shows exactly the 8 target
warnings removed and nothing new. `showcase/scripts` suite: 78 files /
2539 tests pass. No dangling references to the deleted paths anywhere in
`showcase/` or `.github/`.
2026-09-01 11:05:59 +02:00
lukasmoschitz 199988566c chore(showcase/harness): remove stray npm lockfile (#6799)
## What

Removes `showcase/harness/package-lock.json` (3948 lines) and records in
`pnpm-workspace.yaml` why no npm lockfile belongs there.

## Why

`showcase/harness` is a **pnpm workspace member** (listed in
`pnpm-workspace.yaml`), so its only install path is pnpm from the root
`pnpm-lock.yaml`. Both consumers run exactly that:

- `showcase/harness/Dockerfile` → `pnpm install --frozen-lockfile
--filter @copilotkit/showcase-harness...`
- the `harness unit suite` job in `test_unit-showcase.yml` → `pnpm
install --frozen-lockfile`

Nothing anywhere ran `npm ci` in this directory — no Dockerfile,
workflow, or script referenced the file.

Because no gate ever read it, it rotted unobserved. Against a fresh
regeneration it was **106 package versions stale**, carried 51 packages
no longer required, and was missing `axe-core` outright. That is how it
surfaced:

```
npm error `npm ci` can only install packages when your package.json and package-lock.json are in sync.
npm error Missing: axe-core@4.11.1 from lock file
```

…for anyone who saw the file and reasonably concluded this package
installs with npm.

## Why not just regenerate it

Regenerating makes `npm ci` pass, but produces a tree that materially
differs from what CI and prod run — **9 direct deps diverge**:

| dep | pnpm (real build) | regenerated npm lock |
|---|---|---|
| `@hono/node-server` | 2.0.0 | 1.19.17 (**different major**) |
| `playwright` | 1.59.1 | 1.62.1 |
| `hono` | 4.12.15 | 4.13.5 |
| `vitest` / `@vitest/coverage-v8` | 3.2.4 | 3.2.7 |
| `@aws-sdk/client-s3` | 3.1014.0 | 3.1121.0 |

The root cause is that npm cannot see the root `pnpm.overrides` block —
**73 minimum-version floors**, several of them security patches. That
field is pnpm-only. Today those floors happen to be satisfied by luck of
"latest-in-range"; a floor raised above a `package.json` caret range
would have `npm ci` silently install *below* the intended minimum.

So a working `npm ci` here would hand a developer a green install
against versions that never ship. The stale file was a signpost pointing
the wrong way — removed rather than maintained.

## Verification

- `pnpm install --frozen-lockfile --ignore-scripts` succeeds (the real
gate is unaffected by the `pnpm-workspace.yaml` edit).
- Root `pnpm-lock.yaml` already resolves `axe-core` at `4.11.1`;
confirmed installed in the harness tree with no npm lockfile present.
- `showcase/harness` typechecks clean via `tsc --noEmit`, after
generating the gitignored showcase fixtures the way
`test_unit-showcase.yml` does (`showcase/scripts` → `tsx
generate-registry.ts`). Without that step it reports 4 pre-existing
errors, documented in that workflow.
- `pnpm-workspace.yaml` still parses; 17 `packages` entries unchanged,
`showcase/harness` still a member.
- lefthook pre-commit and commitlint pass.

## Notes for reviewers

- `showcase/scripts` is also a workspace member and legitimately
**does** ship a `package-lock.json` — it is read by `npm ci` in the
harness Dockerfile and six `showcase_*` workflows. The note in
`pnpm-workspace.yaml` calls this out so the two do not read as
contradictory.
- Related, **not** in this PR: `showcase/eval-webhook` is in the same
situation as the harness — it ships a lockfile its own Dockerfile never
copies (it uses `npm install` on `package.json` alone, so its container
builds are not reproducible). Worth a separate cleanup.
- The pre-existing CI step named "Verify lockfile is up to date" in
`showcase_validate.yml` is `pnpm install --frozen-lockfile` at the repo
root. It never ran `npm ci` in `showcase/harness` — which is correct,
since that is the path actually used; the gap was coverage of a file
with no function.
2026-09-01 11:05:46 +02:00
Lukas Moschitz 1559be1ff1 chore(showcase/harness): remove stray npm lockfile
`showcase/harness` is a pnpm workspace member (pnpm-workspace.yaml), so its
only install path is pnpm from the root `pnpm-lock.yaml`. Both consumers run
exactly that: `showcase/harness/Dockerfile` (`pnpm install --frozen-lockfile
--filter @copilotkit/showcase-harness...`) and the `harness unit suite` job
in `test_unit-showcase.yml`. Nothing anywhere ran `npm ci` in this directory
— no Dockerfile, workflow, or script referenced the lockfile.

Because no gate ever read it, it rotted unobserved. Against a fresh
regeneration it was 106 package versions stale, carried 51 packages no longer
required, and was missing `axe-core` outright — which is how it surfaced:
`npm ci` here failed with "Missing: axe-core@4.11.1 from lock file" for
anyone who saw the file and reasonably concluded this package installs with
npm.

Regenerating it was the wrong fix. npm resolves a materially different tree
than the one CI and prod actually run — 9 direct deps diverged, with
`@hono/node-server` off by a whole major (pnpm 2.0.0 vs npm 1.19.17) — and
npm cannot see the root `pnpm.overrides` block, 73 minimum-version floors
with several security patches among them, because that field is pnpm-only.
A working `npm ci` here would hand a developer a green install against
versions that never ship, and could silently resolve below an intended
security floor. The stale file was a signpost pointing the wrong way, so it
is removed rather than maintained.

The root `pnpm-lock.yaml` already resolves `axe-core` at 4.11.1 correctly;
verified that `pnpm install --frozen-lockfile --ignore-scripts` succeeds and
that axe-core 4.11.1 is present in the harness tree with no npm lockfile,
and that the harness typechecks clean once the gitignored showcase fixtures
are generated the way CI generates them.

Adds a NOTE in pnpm-workspace.yaml recording why no npm lockfile belongs
here, so the file is not re-added in good faith as it was in 671cc6ae1d.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 09:51:54 +02:00
Maximiliano Korp a26767c538 fix(integrations): activate managed starters with project key 2026-08-31 20:23:15 -07:00
Benjamin Taylor ebf180b1cd fix(docs): name the project API key correctly in managed quickstarts (refs OSS-1029)
Three defects, all in the credential this branch renames.

Twelve integration quickstarts read `CPK_INTELLIGENCE_API_KEY=your_license_key`,
eleven of them under "The runtime reads the license key from step 1". The project
API key and the self-hosted license token are different credentials with
different lifetimes, and ENT-1151 exists to take the license token out of managed
setup -- so a reader who goes looking for a license key to paste finds a dead end
on the very page meant to connect them. Now `cpk-...`, and "reads the project API
key from step 1".

The placeholder prefix was wrong in the other direction on five pages, and newly
pinned that way by a test: `cpk_...`, with `cpk-...` asserted absent. A
provisioned key is `cpk-<projectId>_<short>_<long>` -- see the `cpk-` keyPrefix
in Intelligence's `apps/app-api/src/api-keys.ts` and the `parseApiKeyToken`
fixtures. No key the platform issues starts with `cpk_`, so the placeholder
taught a reader to distrust their own key. Both assertions are flipped.

The new copy guard scans every MDX page rather than listing the twelve, so a page
added next month is covered the day it lands. It reports the offending file and
value, which is how the twelve above were enumerated.

Finally, the retired-name boundary check is extracted to an exported
`retiredNameReference` and unit-tested. It is the load-bearing half of that rule
and it fails in one direction only: the canonical name ends with the retired one,
so a plain substring match reports all ~250 correct sites and the guard gets
switched off. The repo-wide scan cannot cover this -- it can say "clean", not
that the boundary is what made it clean, and it goes green either way once the
last old name is gone.

Verified: guard script exit 0; guard tests 20 passed; managed-starter-docs 10
passed (was 9); oxfmt and oxlint clean on the three changed TypeScript files.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 20:23:15 -07:00
Mike Ryan f3b1ef345b fix(integrations): standardize Intelligence project key name 2026-08-31 20:23:15 -07:00
Mike Ryan 01bdcdc2ba fix(docs): align managed Runtime key handoff 2026-08-31 20:23:15 -07:00
Mike Ryan 30b65541ec fix(docs): restore managed API key prefix 2026-08-31 20:23:15 -07:00
Mike Ryan ae74ef2d13 fix(docs): align headless managed credentials 2026-08-31 20:23:15 -07:00
Mike Ryan 9a2197dc5c fix(docs): match managed key format 2026-08-31 20:23:15 -07:00
Mike Ryan c3847fd9c2 test(integrations): isolate starter docs contract 2026-08-31 20:23:15 -07:00
Mike Ryan 43f72c597b docs(integrations): describe managed starter setup 2026-08-31 20:23:15 -07:00
copilotkit-qa-bot[bot] 424e4138a4 Merge remote-tracking branch 'origin/main' into codex/fac-121-configurable-channels 2026-08-31 17:24:00 -07:00
copilotkit-qa-bot[bot] 34e8473e1f docs: scope LangGraph config guidance by frontend 2026-08-31 15:14:47 -07:00
copilotkit-qa-bot[bot] 73da7538f5 feat(docs): add signed-in account links 2026-08-31 15:06:16 -07:00
copilotkit-qa-bot[bot] 9e288e4ca3 Merge remote-tracking branch 'origin/main' into codex/fac-121-configurable-channels 2026-08-31 14:59:48 -07:00
Maximiliano Korp a0ee4cb8e1 style: format files after rebase 2026-08-31 10:46:15 -07:00
Maximiliano Korp 80d2414f9b fix(shared): recognize managed thread limit entitlement 2026-08-31 10:46:14 -07:00
Maximiliano Korp 4c39fe92ca docs(runtime): design thread entitlement compatibility 2026-08-31 10:46:14 -07:00
Mike Ryan 88567315c7 docs(runtime): standardize Intelligence project key name 2026-08-31 10:46:13 -07:00
Mike Ryan 0a99ef580a fix(runtime): restore managed authority contracts 2026-08-31 10:46:13 -07:00
Mike Ryan b1a5dce48c test(runtime): isolate managed docs contract 2026-08-31 10:46:12 -07:00
Mike Ryan 8d022c5eee docs(runtime): explain managed identity contracts 2026-08-31 10:46:12 -07:00
Benjamin Taylor 6e9210d2b4 fix(docs): name the onboarding run id the way every other surface does (refs OSS-1060)
Three surfaces mint an onboarding run id and report it to PostHog. The
managed-service Home and the web inspector both call it
`onboarding_run_id`, as do all six `cli.onboarding.*` events. The docs
CTA was the lone outlier, reporting the same value as `run_id`.

The cost was not cosmetic. A join written against the canonical name
found nothing on `managed_service.onboarding_prompt_copied`, which is how
that surface came to be described as unmeasurable and its runs as
stranded -- when in fact it carries the id on 100% of copies and joins
fine. The unmeasurable surface was this one, by name only.

Rename the property so all three agree.

Note for anyone querying across the change: the 31 docs copy events from
2026-08-28 to 08-31 carry `run_id`, so a window spanning this commit
needs `coalesce(properties.onboarding_run_id, properties.run_id)`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 12:34:23 -05:00
copilotkit-qa-bot[bot] 1fb030c1b9 docs: document trusted LangGraph configuration channels 2026-08-31 09:37:15 -07:00
Ben Taylor 9b35950bee docs(adk): document how an ADK agent reads the context the page shares (#6796)
## 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 -->
2026-08-31 10:38:53 -05:00
copilotkit-qa-bot[bot] 19e29e1688 test(showcase): guard AIMessage runtime import 2026-08-31 08:13:19 -07:00
copilotkit-qa-bot[bot] 66cd31d8fa Merge remote-tracking branch 'origin/main' into codex/fac-104-public-langgraph-snippets 2026-08-31 07:56:00 -07:00
Ben Taylor 1500874ac0 docs(crewai): document how a CrewAI Flow reads the context the page shares (closes OSS-1051) (#6801)
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 -->
2026-08-31 09:32:35 -05:00
Benjamin Taylor a59e46fcca docs(adk): correct the context-access and brace-substitution claims
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>
2026-08-31 09:29:21 -05:00
Rainer Hahnekamp a34a7174cf feat(angular): add registerComponent so a component can be a tool the agent calls (refs OSS-1034) (#6773)
## 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)
2026-08-31 16:21:47 +02:00
Benjamin Taylor 6f42627a12 docs(crewai): document how a CrewAI Flow reads the context the page shares
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>
2026-08-31 09:17:39 -05:00
copilotkit-qa-bot[bot] d0d88c9d50 Merge remote-tracking branch 'origin/main' into codex/fac-104-public-langgraph-snippets 2026-08-31 07:07:07 -07:00
Benjamin Taylor dd112c9cd4 docs(angular): link registerFrontendTool and registerRenderToolCall back to registerComponent
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>
2026-08-31 09:04:28 -05:00
Ben Taylor 8dd27199f0 docs(inspector): say that Inspector needs a browser and React Native has none (refs OSS-977) (#6712)
## 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.
2026-08-31 08:00:02 -05:00
Ben Taylor dafb13e61a docs(langgraph): fix crossed hook names in coagent troubleshooting accordions (#6795)
## 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 -->
2026-08-31 07:58:27 -05:00
Ben Taylor 6614448f97 docs(shell-docs): prefix vendored ag-ui links with /ag-ui (#6460)
## 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)
2026-08-31 07:53:38 -05:00