Commit Graph

1163 Commits

Author SHA1 Message Date
github-actions[bot] 8114ddd623 style: auto-fix formatting 2026-08-20 11:53:24 +00:00
Alem Tuzlak a9714d1c02 docs: call Inspector out in quickstarts and feature pages
After the first chat, web quickstarts now tell the reader to open Inspector and confirm Agents, AG-UI Events, and Threads. Feature pages that map to a shipped pane get a short Callout. Angular links the Inspector install page first. Vue sets show-dev-console=auto so the overlay appears on localhost. The inspector-docs skill keeps pane-to-docs pointers in sync when Inspector panes change.
2026-08-20 13:50:15 +02:00
Benjamin Taylor 6f58b2c6a4 fix(runtime): unify the Intelligence key name and publish the wiring (refs OSS-881)
Three names for one value were live in CopilotKit's own documentation, and
following the wrong one with a CLI-provisioned project yields an undefined
key:

- `INTELLIGENCE_API_KEY` — what `copilotkit project select` writes, used by
  all 34 integration examples and the docs site.
- `COPILOTKIT_INTELLIGENCE_API_KEY` — the seven Channels package READMEs and
  the packaged skills. Nothing ever read it.
- `COPILOTKIT_API_KEY` — the Slack and Teams examples, and the TSDoc on
  `CopilotKitIntelligence` itself, which is what an IDE shows on hover.

`INTELLIGENCE_API_KEY` wins, because it is the name the CLI provisions and
changing it would break every scaffolded project in the wild.
`COPILOTKIT_INTELLIGENCE_API_KEY` is retired outright — no code read it.
`COPILOTKIT_API_KEY` stays readable as a deprecated alias in the two
examples that consume it, so an existing `.env` keeps working, and is
documented as deprecated everywhere it appears.

The skills reference also documented `organizationId`, sourced from a fourth
and fifth env name, as a `CopilotKitIntelligence` option. It is not one:
`CopilotKitIntelligenceConfig` has no such field, so the copy-pasteable
sample it appeared in would not compile. Removed from the samples, and the
prose that told readers to fetch a value for it corrected.

The Intelligence wiring itself was published only inside
`node_modules/@copilotkit/runtime/skills/`, and the only docs pages showing
`CopilotKitIntelligence` were the two Channels frontends — so a developer on
the plain web path had no page to reach it from. Adds
`/premium/connect-your-runtime`, which covers the wiring, how to confirm the
credential is actually consumed, and the self-hosted two-URL rule.

`scripts/validate-intelligence-env-names.ts` keeps this from drifting back.
It runs unfiltered in CI on purpose: the two workflows that would otherwise
cover it filter paths, and static/quality ignores `examples/**` — exactly
where the deprecated alias lives.
2026-08-19 17:50:09 -05:00
Benjamin Taylor f94d1ab0fb fix(runtime): name useSingleEndpoint when a single-route envelope hits a multi-route runtime
The v1-compatible `<CopilotKit>` provider pins `useSingleEndpoint` to `true`,
so it POSTs `{ method: "info" }` at the base path. A multi-route runtime — the
default — matches no route for that path and answered a bare `{"error":"Not
found"}`, which is indistinguishable from a wrong `basePath` or an unmounted
handler. Two independent onboarding validation runs hit this on their first
attempt and had to guess the cause.

The runtime now recognises the envelope at the one point multi-route routing
gives up, and answers the 404 with a message naming the prop, plus a
`logger.warn` so it also lands in the dev server terminal. Status and shape are
unchanged for every other miss.

That message was reaching nobody: all four `/info` callers threw away the
response body and reported only the status. They now route through
`runtimeInfoError`, which folds a string `message` from the body into the
error — so any future server-side diagnosis reaches the developer too.

Docs: five pages paired a v2 multi-route handler with `<CopilotKit>` without
mentioning the prop. Their snippets now pass `useSingleEndpoint={false}` and
link to the provider/handler mapping. `backend/runtime-endpoints.mdx` already
documents the pairing and is untouched; `cookbook/arcade.mdx` deliberately uses
single-route mode and already explains it.

Closes OSS-882

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 17:40:31 -05:00
Tyler Slaton 4b2586bd90 fix(web-inspector): load saved threads in active chats 2026-08-19 15:34:03 -07:00
Alem Tuzlak 1ef16b6789 feat(web-inspector): pop the Inspector into its own window
Keep the same live Inspector session in a named browser popup, restore it when the popup closes, and document the workflow.
2026-08-19 14:03:12 -07:00
Martha Kelly Schumann 3fc33398af Merge branch 'main' into codex/ent-1157-shared-clerk-session 2026-08-19 13:28:46 -07:00
Ben Taylor 092058b224 docs(a2ui): require a literal-or-binding union for bound props (refs OSS-857) (#6573)
Four defects were reported from a LangGraph TypeScript + Next.js
onboarding run. Two
were unverified and one was unsound as stated, so each was reproduced or
traced to
source before anything was written. Two needed a fix, one needed a fix
plus a package
re-export, and one turned out to be correct as documented.

## Per-defect findings

**Defect 1 — bound props need a literal-or-binding union schema. REAL,
and the page said the opposite.**
Confirmed, with the mechanism. `scrapeSchemaBehavior` in
`@a2ui/web_core`'s
`GenericBinder` decides whether to resolve a `{ path }` binding by
inspecting the prop's
Zod type: a `ZodUnion` containing an object with a `path` key (and no
`componentId`)
becomes `DYNAMIC`; everything else falls through to `STATIC`, whose
handler is
`case 'STATIC': return value;`. So a bound prop declared as a plain
`z.string()` is never
resolved and the raw `{ path: "/origin" }` object reaches the renderer,
where the first
thing that renders it as text throws React error #31.

The page was not merely silent about this — it asserted the opposite:

> The A2UI binder resolves those paths *before* the React renderer runs,
so renderer
> props are typed as their resolved values (plain `z.string()`, not a
path-or-literal union).

The reference cell has declared the union all along and carries a
comment naming the exact
React error, but that comment sits *outside* the
`@region[definitions-types]` marker, and
`extractRegion` returns only the lines between the markers — so it never
reaches the page.
The rule is now stated where the reader declares the prop, with the
failure mode.

**Defect 2 — `DynamicStringSchema` is not re-exported. Explanation 2:
the symbol exists in a package that had not been searched.**
It is real and it is not a wished-for helper. It lives in
`@a2ui/web_core` at
`src/v0_9/schema/common-types`, reachable on the export map as
`@a2ui/web_core/v0_9`, and
it is a three-member union (`z.string()`, `DataBindingSchema`,
`FunctionCallSchema`) —
slightly wider than the two-member `DynString` the reference cells
hand-roll. The earlier
search was correct that it appears nowhere under `packages/`; it is a
dependency symbol.

It is also genuinely unreachable for users: `@a2ui/web_core` is a plain
`dependency` of
`@copilotkit/a2ui-renderer`, so application code cannot rely on
importing it. Re-exported
from `@copilotkit/a2ui-renderer` with its numeric/boolean/list siblings
and their types,
and noted in the docs as an alternative to hand-rolling the union.

**Defect 3 — the quickstart recommended the host form that fails. REAL,
verified independently for both runtimes.**
The advice was *"try using `0.0.0.0` or `127.0.0.1` instead of
`localhost`"*, in shared prose.
For the Node runtime that is exactly backwards, and it was verified from
source and by
running it, not taken on report. Rewritten and split across the page's
existing
Python/TypeScript language tabs so neither runtime sees the other's
advice. Also corrected
the `0.0.0.0` half, which is wrong for both: it is a bind-all address
for a server, not a
target for a client URL.

**Defect 4 — `useSingleEndpoint` guidance for the compat component. NOT
A DEFECT. Nothing changed.**
The docs are right. The compat wrapper resolves its default at

`packages/react-core/src/components/copilot-provider/copilotkit.tsx:108`:

```tsx
useSingleEndpoint={props.useSingleEndpoint ?? true}
```

and the v2 provider maps `true → "single"`, `false → "rest"`, `undefined
→ "auto"`
(`CopilotKitProvider.tsx:616-620`, again at `777-781`). So omitting the
prop really does
keep a single-route default, and `useSingleEndpoint={false}` really is
what a multi-route
Runtime needs. The same `CopilotKit` component is exported from both
`@copilotkit/react-core`
and `@copilotkit/react-core/v2`, so the guidance holds for either
import. Reported as one
observation from one run rather than an established finding — it did not
survive checking.

## Two things worth flagging

**The URL is served by the root page, not the LangGraph one.** Both
`generative-ui/a2ui/fixed-schema.mdx` and
`integrations/langgraph/generative-ui/a2ui/fixed-schema.mdx` exist, and
the resolution is the
opposite of what the directory layout suggests: all three langgraph
slugs are
`docs_mode: generated` in their manifests, and in that branch root MDX
wins
(`[framework]/[[...slug]]/page.tsx:836-841`). Confirmed live — the
LangGraph-scoped copy is a
thinner, older duplicate that is **not served at that URL for any
framework**. Left in place,
but it is a trap for the next person and probably wants deleting
separately.

**Overlap with #6569.** That PR is still open and edits both files this
one touches.
`git merge-tree` against its head merges clean, so no action needed, but
the two should be
read together.

## Testing

Worktree off `origin/main` (which already contains #6566 and #6568).

**Defect 1 — mechanism, against the locked `@a2ui/web_core@0.10.4`.**
Schema classification:

```
plain z.string()  -> {"type":"STATIC"}
literal|binding   -> {"type":"DYNAMIC"}
```

End-to-end through the real `GenericBinder`, feeding `{ path: "/origin"
}` against a data
model of `{ origin: "SFO" }`:

```
z.string()      : typeof=object value={"path":"/origin"}
literal|binding : typeof=string value="SFO"
z.string() -> renderable as a React child? NO — React throws: Objects are not valid as a
              React child (found: object with keys {path})
literal|binding -> renderable as a React child? yes
```

**Defect 2 — the re-export works from the built entry point**, and
behaves identically to the
hand-rolled union in the binder (it has a third union member, so this
needed checking):

```
DynamicStringSchema parses a literal: "SFO"
DynamicStringSchema parses a binding: {"path":"/origin"}
hand-rolled union   -> {"type":"DYNAMIC"}
DynamicStringSchema -> {"type":"DYNAMIC"}
plain z.string()    -> {"type":"STATIC"}
```

**Defect 3 — both runtimes verified from CLI source, and the Node
binding reproduced.**
`@langchain/langgraph-cli@1.4.4` `dist/cli/dev.mjs:19` defaults `--host`
to `"localhost"`
and passes it to `serve({ hostname })`; `langgraph_cli-0.4.31`
`cli.py:664-666` defaults
`--host` to `"127.0.0.1"`. Reproducing what Node does with `{ host:
"localhost" }` on this
dual-stack machine:

```
node version: v22.14.0
bound to: {"address":"::1","family":"IPv6","port":42024}
  localhost   -> CONNECTED
  127.0.0.1   -> ECONNREFUSED
  ::1         -> CONNECTED
  0.0.0.0     -> ECONNREFUSED
```

`127.0.0.1` is refused by the very server `localhost` reaches — so the
old advice broke a
working setup.

**Rendered checks (`next dev`, body-inspected — this site soft-404s, so
no status codes were trusted).**
`/langgraph-typescript/...` and
`/langgraph-python/generative-ui/a2ui/fixed-schema`: root-file
marker present, LangGraph-file marker absent, new prose and the
React-error callout present,
old wrong sentence gone. The `{path}` braces render literally inside
`<code>` and the
`#declare-the-component-definitions` anchor resolves to a real heading
id.

Quickstart troubleshooting tabs resolve per framework, so the gating is
right:

```
/langgraph-typescript/quickstart   Python selected=false   TypeScript selected=true
/langgraph-python/quickstart       Python selected=true    TypeScript selected=false
/langgraph-fastapi/quickstart      Python selected=true    TypeScript selected=false
```

The `<Tabs>` nested in a list item renders as a real `<ul><li>` with a
working tablist, not
broken MDX.

**Suites.**

| Check | Result |
| --- | --- |
| `packages/a2ui-renderer` `tsc --noEmit` | pass |
| `packages/a2ui-renderer` build (`tsdown`) | pass, 143 files |
| `packages/a2ui-renderer` `vitest run` | 4 files, 22 tests passed |
| `oxlint` on the changed source | 0 warnings, 0 errors |
| `shell-docs` `npm run typecheck` | pass (exit 0) |
| `shell-docs` `npm run lint` | pass (exit 0) |
| `shell-docs` `npm run test` | 58/59 files, 420/421 tests |

The one failing test is `channels-docs.test.ts > publishes the Channels
overview only through
provider navigation`. It is **pre-existing on `origin/main`** and
unrelated to these files —
verified by reverting all three changes to a pristine checkout and
re-running it, where it
fails identically (`1 failed | 29 passed`).

## Conventions pass

Checked the added prose against the docs tree's actual conventions
rather than by ear, which
turned up four things worth changing:

- **`Callout type="warn"`** is the house spelling (84 uses vs 11
`warning`) — already correct.
- **Code identifiers in Callout titles are backticked** (95-odd
precedents, e.g.
``title="`identifyUser` is not an authentication gate"``). Mine wasn't;
fixed. Note these
render as *literal* backticks — verified that existing titles behave
identically on `/auth`,
  so this matches the site rather than diverging from it.
- **Dropped a hand-written code fence.** The first draft illustrated the
union with a synthetic
`ts` block that (a) wasn't valid TypeScript — an orphaned object
property with no enclosing
object — and (b) duplicated the `<Snippet region="definitions-types" />`
rendered immediately
below it. Hand-copied code next to the generated snippet is exactly the
drift the snippet
architecture exists to prevent, so the prose now names `DynString` and
`Airport`'s `code` and
lets the snippet carry the code. Confirmed those two names are present
in **all 21**
integration cells that feed this page, since the root page serves every
framework.
- **Matched local line-style.** The quickstart's other troubleshooting
bullets are single
unwrapped lines, so the new bullet's prose is too; the a2ui page wraps
at ~70–80 columns and
  the new paragraphs match that.

Also tightened two things for accuracy over emphasis: the binder rule
now says "a union with a
`{ path }` member" rather than "a union containing an object with a
`path` key", which was
over-broad (a `{ componentId, path }` member is classified `STRUCTURAL`,
not `DYNAMIC`), and
the package comment was cut from nine lines to six to sit better among
that file's one-line
section labels.

Re-verified after the rewrite: `tsc` pass, `vitest` 22 passed, `oxlint`
clean, `oxfmt` clean,
shell-docs typecheck/lint pass, tests unchanged at 420/421 with the same
pre-existing channels
failure, and both pages re-rendered — anchor still resolves, tabs still
resolve per framework
(`langgraph-python` → Python, `langgraph-typescript` → TypeScript).

Out of scope and untouched: `snippets/shared/premium/inspector.mdx`. No
changeset added.
Does not close OSS-857.
2026-08-19 15:27:44 -05:00
Martha Kelly Schumann af6c7ad5e0 Merge branch 'main' into codex/ent-1157-shared-clerk-session 2026-08-19 13:20:24 -07:00
Benjamin Taylor 4df1e3dccd docs(a2ui): require a literal-or-binding union for bound props (refs OSS-857)
Three findings from a LangGraph TypeScript onboarding run, plus the
supporting re-export.

The A2UI binder decides whether to resolve a `{ path }` binding by
inspecting the prop's Zod type: `scrapeSchemaBehavior` classifies a
`ZodUnion` containing an object with a `path` key as DYNAMIC and
everything else as STATIC, and STATIC returns the value untouched. A
bound prop declared as a plain `z.string()` therefore reaches the
renderer as the raw `{ path: "/origin" }` object, and the first thing
that renders it as text throws React error #31. The fixed-schema page
said the opposite — that renderer props are "plain z.string(), not a
path-or-literal union" — so the obvious declaration produced an opaque
crash. The reference cell already declares the union and carries a
comment explaining why, but that comment sits outside the
`definitions-types` region marker and so never reaches the page.

`DynamicStringSchema` is real; it lives in `@a2ui/web_core`, which is a
transitive dependency of `@copilotkit/a2ui-renderer` and so not
reliably importable from application code. Re-exported here with its
numeric/boolean/list siblings and their types.

The LangGraph quickstart's troubleshooting advice told everyone with a
connection problem to swap `localhost` for `0.0.0.0` or `127.0.0.1`.
That is backwards for the Node runtime: `langgraphjs dev` defaults to
`--host localhost`, which Node resolves to IPv6 and binds `::1` only,
so `127.0.0.1` is refused by the same running server. The Python CLI
defaults to `--host 127.0.0.1` and behaves the other way, so the advice
is now split across the page's existing Python/TypeScript language tabs
instead of stated once in shared prose.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 14:48:49 -05:00
Ben Taylor 68d6c5c62d docs(inspector): document mounting the Inspector in Angular (refs OSS-857) (#6572)
## What this fixes

The Inspector is `cpk-web-inspector`, a framework-agnostic web component
from
`@copilotkit/web-inspector`. `@copilotkit/angular` does not reference
that package
and does not mount the element, so an Angular application has to create
it
itself. Nothing in the docs said so.

It was worse than a missing paragraph. `ANGULAR_DOC_REDIRECTS` mapped
the
`inspector` slug onto `guides/troubleshooting`, so
`/angular/*/inspector`
**redirected away from the Inspector**, and the Angular sidebar's
"Observe & Operate" section contained a single entry — the VS Code
extension:

```
== Observe & Operate
- VS Code Extension [vs-code-extension]
```

## What I documented

New Angular-owned page, `frontends/angular/inspector.mdx`, sourced from
`examples/integrations/adk-angular/src/app/web-inspector.ts`:

- the Inspector is a web component and `@copilotkit/angular` does not
mount it
- the mount component: `afterNextRender`, reuse-or-create, append to
`document.body`
- `inspector.core = copilotKit.core` plus `auto-attach-core="false"`,
and why —
  given no core the element hunts for development globals such as
`window.__COPILOTKIT_CORE__`, so turning the search off is what
guarantees it
  observes the app's core and never a different one
- anchoring the launcher bottom-left, clear of a chat panel's close
button
- keeping it out of production builds via `@defer (when isDev)` +
`isDevMode()`
- server rendering (`afterNextRender` + the deferred import vs.
`customElements`)
- cleanup through `DestroyRef.onDestroy`

Plus: the redirect is gone so the page is reachable, and
`frontends/angular/guides/troubleshooting.mdx` links to it.

**React's Inspector content is untouched** — not edited, not moved, not
gated.

### House style

Checked against the eleven existing Angular-owned pages rather than
written to
taste, which changed four things from my first draft:

- **`## Next steps` with a bare link list.** Every Angular guide closes
that way;
  I had `## Related` with a prose gloss per link.
- **No `<video>`.** No Angular-owned page embeds media, and none uses
`<Callout>`
or `<Steps>` either — that surface is prose, tables, and fences. I had
carried
  the Inspector video over from the shared snippet.
- **Imperative task headings**, matching "Send the current session" /
  "Validate every runtime request" in `auth.mdx`: "Mount the element",
  "Supply the application's core", "Position the launcher". I had
  "Mount it yourself" and "Hand it the application's core".
- **Declarative sentences, no rhetorical fragments.** "The mount is
yours, so the
exclusion is yours as well." and a bare "`DestroyRef.onDestroy` does."
are not
  this surface's register; both are now plain statements of mechanism.

Frontmatter (`title`/`description`/`icon`/`doc_type: how-to`), h2-only
structure, ~80-column wrapping, and the `{runtimeUrl}` placeholder
convention all
follow the siblings. `<AngularSnippet region=…>` does **not** apply —
that
component pulls code extracted from the Angular Showcase at build time,
and this
mount component is not in the Showcase. Nav needs no `meta.json` entry
either:
`frontends/meta.json` carries only a title, and the Angular sidebar is
derived in
`getAngularDocsNavTree`. Verified the entry renders anyway.

### Two deviations from the brief, both deliberate

**1. Structural gating instead of `<FrontendOnly frontend="angular">` in
the
shared snippet.** The brief described
`snippets/shared/premium/inspector.mdx` as
the real Inspector content with the per-framework pages as shims onto
it. On
current `main` that is only half true: `docs/inspector.mdx` is now a
131-line
standalone page that does **not** render `<Inspector />`, and it is what
the
Angular root and every `docs_mode: generated` framework resolve to. I
built the
`FrontendOnly` version first and it forced the Angular guide to be
duplicated
into two files that had already diverged. An Angular-owned page instead
matches
how all eleven existing Angular guides work, keeps one source of truth,
and
gates by resolution rather than by branch.

The repo's own test agrees on the direction —
`angular-docs-content.test.ts`
lists `<FrontendOnly` in `REACT_ONLY_CONTENT`, i.e. it treats the tag as
something that should not reach the Angular surface.

That test also gave me a real mutation check for free. My first attempt
leaked
React's `<CopilotKit … enableInspector={false}>` into 19 Angular pages,
and the
suite caught every one:

```
× keeps the complete Angular surface free of another frontend's code
+   "inspector: <CopilotKit
+   publicLicenseKey={process.env.NEXT_PUBLIC_COPILOTKIT_LICENSE_KEY}
+   enableInspector={false}
+ >",
× keeps every Angular and backend combination frontend-native
    expected [ …(18) ] to deeply equal []
```

**2. I document the CSS override for positioning, not
`setAttribute("anchor", …)`.**
The scaffold sets that attribute, but `cpk-web-inspector` never reads
it. Runtime
proof against the built `dist`:

```
observedAttributes: ["auto-attach-core"]
static properties keys: ["core","autoAttachCore","_capabilitiesVersion"]
'anchor' observed? -> false
```

There is no `getAttribute("anchor")` anywhere in the package, and
`defaultAnchor`
(the prop React's `CopilotKitInspector` accepts) is not consumed either.
What
actually moves the panel is the CSS in the scaffold's own `styles.css` —
as its
comment already says: "CSS in styles.css enforces this too." So the docs
describe
the mechanism that works. **The scaffold has one dead line** its owner
may want
to drop; I did not touch it (see below).

## The adk-angular dependency is discharged

`examples/integrations/adk-angular` is planned for removal, and its
`web-inspector.ts` comment was the only written record of this pattern.
That
pattern is now documented. **Whoever removes that scaffold no longer
needs to
preserve it.** I only read the scaffold — no file under
`examples/integrations/adk-angular` is modified by this PR.

## The VS Code extension claim: both halves reproduced

The report said Angular users are pointed at a VS Code extension
instead, that
its `cpk-debug-events` endpoint is documented at the wrong path, and
that it
produced no events for a real run. I verified each independently rather
than
acting on the report.

**Pointed at the extension — confirmed.** See the one-entry sidebar
above.

**Wrong path — confirmed, and fixed.** The router suffix-matches
`cpk-debug-events`, but a runtime mounted with a `basePath` rejects
anything
outside it. Against a real runtime on `basePath: "/api/copilotkit"`:

```
runtime mounted at basePath=/api/copilotkit, NODE_ENV=development
/cpk-debug-events                -> 404  application/json  {"error":"Not found"}
/api/copilotkit/cpk-debug-events -> 200  text/event-stream  ": connected\n\n"
/api/copilotkit/info             -> 200  application/json   {"version":"1.64.1",…}
```

The docs said "available at `GET /cpk-debug-events` on your CopilotKit
runtime"
and gave the panel default as the bare origin `http://localhost:4000`,
so a
reader supplying their server's origin gets a 404. Now documented as
`GET {runtimeUrl}/cpk-debug-events`, base-path-relative, with the worked
`localhost:8200` example and a `curl` check, in both
`troubleshooting/event-inspector.mdx` and `vs-code-extension.mdx`.

**No events for a real run — confirmed, cause is runtime mode.** The
debug bus is
fed from exactly one place, `handlers/shared/sse-response.ts`, reached
only by
`handlers/sse/run.ts` and `handlers/sse/connect.ts`. An
Intelligence-configured
runtime dispatches to `handlers/intelligence/run.ts` and
`handlers/intelligence/connect.ts`, which return `Response.json` and
hand the
browser a realtime connection — no AG-UI event ever passes through the
runtime's
SSE layer. Neither file mentions `debugEventBus`. So on an
Intelligence-backed
runtime the endpoint connects, emits `: connected`, and then stays
silent
forever. That is now a callout on the event-inspector page pointing
readers at
the in-app Inspector, which reads the events client-side.

I did not change runtime code for this — it is a docs-accuracy gap, and
whether
the Intelligence path *should* feed the bus is a product decision, not
mine to
make here.

## Testing

From `showcase/shell-docs`:

**`npm run test`** — 403 passed, 1 failed, and that failure is
pre-existing on
`origin/main`. Verified in a pristine `origin/main` worktree with no
changes:

```
❯ src/lib/__tests__/channels-docs.test.ts (30 tests | 1 failed)
    × publishes the Channels overview only through provider navigation
```

It asserts `channels-architecture-dark.png` in the Channels overview
source and
is unrelated to anything here. The seven `angular-docs-content.test.ts`
tests —
the ones that police frontend separation — all pass.

**`npm run typecheck`** — identical output on my branch and on a
pristine
`origin/main` worktree (5 pre-existing `@testing-library/react`
resolution
errors from my symlinked `node_modules`, all in test files I did not
touch). No
new errors.

**`npm run lint`** — exit 0, no warnings in any file I changed.

**`npx oxfmt --check`** on the one `.ts` file — "All matched files use
the
correct format."

### Render check, both namespaces

`next dev`, following redirects, checking bodies rather than status
codes since
this site soft-404s:

| URL | http | Angular mount content | React `enableInspector` |
| --- | --- | --- | --- |
| `/angular/langgraph-typescript/inspector` | 200 | yes
(`afterNextRender`, `auto-attach-core`, `cpk-web-inspector`) | **no** |
| `/langgraph-python/inspector` | 200 | **no** | yes |

Each namespace shows only its own instructions. The only `tsx` string on
the
Angular page is Next.js dev chunk filenames, not content.

Before this change `/angular/langgraph-typescript/inspector` answered
`307 -> /angular/langgraph-typescript/guides/troubleshooting`.

Also confirmed 200-with-content, no redirect, and the mount instructions
present
on `/angular/inspector`, `/angular/google-adk/inspector`, and
`/angular/mastra/inspector`; the sidebar now carries
`href="/angular/langgraph-typescript/inspector"` under "Observe &
Operate"; the
Angular troubleshooting page links to it; and the new event-inspector
callouts
render in both the React and Angular namespaces with `/inspector`
correctly
rewritten to `/angular/<backend>/inspector`.

## Notes for reviewers

- **OSS-857 stays open** — other defects on it are unresolved.
- No changeset, per this repo's release process.
- Follow-up for the adk-angular owner, not done here:
`setAttribute("anchor", "bottom-left")` in `web-inspector.ts` is a no-op
and
can be deleted; the `styles.css` rule below it is what positions the
panel.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-19 14:46:03 -05:00
Ben Taylor 3801de3708 docs(runtime): map the provider/handler pairs and guard BuiltInAgent (refs OSS-857) (#6569)
Follow-up to #6566. Fixes **defects 5 and 9** of OSS-857, plus the half
of **defect 6** that lives on the Built-in Agent quickstart. Defects **1
and 2** are deliberately left — they land with the non-interactive
`project list`/`select` work, since the real fix is tooling that
provisions and names the key, not prose.

**Do not close OSS-857 on this PR** — 1 and 2 remain.

## The finding that reframes defect 5

The three names are **not interchangeable**. They pair up, and nobody
had written the pairing down. Traced through source, not inferred:

| Provider | `useSingleEndpoint` | Transport | Needs handler |
| --- | --- | --- | --- |
| `<CopilotKit>` (v1 wrapper) | omitted → `true` | `single` |
single-route |
| `<CopilotKit>` | `{false}` | `rest` | multi-route |
| `<CopilotKitProvider>` (v2) | omitted | `auto`, detected from `/info`
| either |
| `<CopilotKitProvider>` | `{true}` | `single` | single-route |

`copilotkit.tsx:108` is the whole story:
`useSingleEndpoint={props.useSingleEndpoint ?? true}`. The v1 wrapper
renders `<CopilotKitProvider>` internally and **pins single-route
transport unless you pass the prop.** So the LangGraph quickstart is
internally coherent — v1 provider asks for single,
`copilotRuntimeNextJSAppRouterEndpoint` serves single — which is exactly
why chat works there and Threads cannot.

### The constraint nobody had documented

I swept every v1-era wrapper:

- `copilotRuntimeNextJSAppRouterEndpoint` →
`createCopilotEndpointSingleRoute`
- `copilotRuntimeNodeHttpEndpoint` → `createCopilotEndpointSingleRoute`
- `copilotRuntimeNextJSPagesRouterEndpoint`,
`copilotRuntimeNodeExpressEndpoint`, `copilotRuntimeNestEndpoint` → all
delegate to `copilotRuntimeNodeHttpEndpoint`

**Every one builds its handler with `mode: "single-route"` and exposes
no option to change it.** There is no v1-shaped multi-route handler
anywhere in the package.

The consequence is sharper than defect 5 as filed: **Rich Threads and
the Inspector are unreachable from the wiring both quickstarts teach, at
any provider setting.** Setting `useSingleEndpoint={false}` cannot fix
it — it just points the browser at routes the wrapper will not serve.
You need a v2 `CopilotRuntime` from `@copilotkit/runtime/v2` plus
`createCopilotRuntimeHandler`. That is a server-side change, not a
provider prop, and it is the structural reason defect 3's trap exists.
Worth its own ticket.

## Why I did not converge the quickstarts on v2

That was the original plan for this PR and I abandoned it after checking
the backend half. The split matters:

- **Frontend would have been free.** Both quickstarts already import
from `@copilotkit/react-core/v2`, where `CopilotKit` is labelled in
source as a *"V1 backward-compat re-export"*. `CopilotKitProvider` ships
from that same entry, and `CopilotSidebar` already depends on
`useLicenseContext` from it. Swapping is an import change.
- **Backend would not.** The multi-route handler takes a v2
`CopilotRuntimeLike`; the quickstart's v1 `CopilotRuntime` only reaches
it via an internal `.instance` getter that lazily news up a
`CopilotRuntimeVNext`. Converging means teaching v2 runtime construction
and dropping `ExperimentalEmptyAdapter` mid-quickstart — a real v1→v2
migration for every reader of the two highest-traffic pages.

v1 is supported, so the default path stays put. The mapping documents
all pairs instead, and the Threads upgrade stays a labelled, complete
recipe on the page the quickstarts already link to.

## What changed

**`backend/runtime-endpoints.mdx`** — new "Provider and handler pairs"
section: the provider table, the handlers-by-mode table, the
deprecated-alias mapping (`createCopilotEndpoint`,
`createCopilotEndpointSingleRoute`, and the Express pair), the wrapper
constraint above, and a "read the symptom" callout (a mismatch fails at
discovery — `GET {basePath}/info` 404s, or the Runtime rejects the
envelope — never in your application code).

**Both quickstarts** — a short callout naming the pair the page uses and
linking the mapping.

**Defect 9, `integrations/built-in-agent/quickstart.mdx`** — this is
what `/quickstart` actually serves (verified: both URLs return the
identical 8175-byte body; the root `quickstart.mdx` is a 17-line routing
shim that 308-redirects to `/`). `BuiltInAgent` extends `AbstractAgent`
and calls the model directly via `streamText`, so registering it as
`default` replaces the developer's agent rather than connecting to it.
Added a caution: readers with an existing agent take the frontend steps
here and the runtime wiring from their framework's quickstart.

**Defect 6, second half** — same page installed `@copilotkit/react-ui`
and never used it, importing `CopilotKit`/`CopilotSidebar` from
`@copilotkit/react-core/v2`. Dropped, matching #6566.

## Testing

```
$ npx vitest run
Test Files  1 failed | 58 passed (59)
     Tests  1 failed | 417 passed (418)
```

The one failure is `channels-docs.test.ts > publishes the Channels
overview only through provider navigation` — pre-existing, and proven so
in #6566 by stashing on a clean tree.

**I broke two tests and fixed them, which is worth recording** because
it caught a real defect in my first draft.
`angular-docs-content.test.ts` flagged:

```
built-in-agent/backend/runtime-endpoints: @copilotkit/react
langgraph-python/backend/runtime-endpoints: @copilotkit/react
... 10 surfaces total
```

`backend/runtime-endpoints.mdx` also serves the **Angular** surface, and
my provider prose named React packages there. Correct fix, not a
suppression: the provider axis is React-only — Angular's
`provideCopilotKit` has no `useSingleEndpoint` — so the provider table
is now `<FrontendOnly frontend="react">` with an Angular branch saying
only the handler half applies. Both Angular tests pass.

### Render checks

Per surface, `.md` and HTML:

| surface | provider table | Angular note | `@copilotkit/react` |
wrapper callout |
|---|---|---|---|---|
| langgraph-python | ✅ | — | 3 | ✅ |
| langgraph-typescript | ✅ | — | 3 | ✅ |
| angular | — | ✅ | **0** | ✅ |

The wrapper-constraint callout correctly stays on all three: it is a
server-side fact that applies to Angular too.

Defect 9 / 6b on `/quickstart` and `/built-in-agent/quickstart` — both
8175 bytes, caution present, `react-ui` gone from the install line, pair
pointer present.

Every link I added was **body-verified, never by status code** (this
site soft-404s with HTTP 200):

```
/langgraph-python/quickstart                 bytes=428497  soft404=0  h1=Quickstart
/                                            bytes=248255  soft404=0  h1=CopilotKit
/backend/runtime-endpoints                   bytes=375782  soft404=0  h1=Runtime HTTP endpoints
/langgraph-python/backend/runtime-endpoints   bytes=395130  soft404=0  h1=Runtime HTTP endpoints
```

New anchors confirmed present (`id="provider-and-handler-pairs"`,
`id="which-handlers-serve-which-mode"`), and the pointer rewrites into
the reader's namespace correctly — `/langgraph-python/backend/...` from
the LangGraph page, `/backend/...` from the root surface.

## Voice pass

A third commit runs a tone/voice check over everything added for
OSS-857, measured against the corpus instead of guessed. It also
corrects the wording that already landed in #6566, so the whole ticket
reads in one voice.

**Second person stays.** It is emphatically the house voice: 22 of 29
top-level and backend pages use `you`/`your`, and the three pages
involved used it **17, 23 and 64 times** before any of these edits.
Stripping it would make the new prose stand out, not blend in.
Mid-sentence `**bold**` also stays — the corpus does that 17 times.

What genuinely drifted, and is now fixed:

| Issue | Was | Now |
|---|---|---|
| British spelling | `honours` | `serves` |
| Third person on a second-person page | `A developer adding A2UI to an
agent they already wrote…` | `If you added A2UI to an agent you already
wrote…` |
| Essay register | `That default is the one thing to remember:` | plain
statement of the fact |
| Meta phrasing | `so this is the mapping` | `so this table is the
mapping` |
| Conversational | `no provider pairing to get wrong` | `to configure` |
| Conversational | `` `uvicorn` is told to listen on `8123` `` | ``
`main.py` sets uvicorn's port to `8123` `` |
| Literary | `you may also meet these deprecated aliases` | `Older code
may use these deprecated aliases` |
| Coinage | `agent construct` | `how the agent itself is built` |
| Coinage | `without that steer` | `Without it, the model tends to…` |
| Aphoristic Callout title | `Mismatched pair? Read the symptom, not the
code` | `A mismatched pair fails at discovery` |
| Epigram | `It replaces your agent; it does not connect to one.` | `It
replaces your agent rather than connecting to it.` |
| Redundancy | `nothing supplies persistence for you` | `nothing
supplies persistence` |

Two of these were objective, not stylistic: the corpus is American
English (`behavior` 66:6, `customize` 77:4, `serialize` 18:1, `organize`
15:0) and its only `honour` was mine; and it contains exactly two
instances of `a developer`, one of which was mine on a page that
addresses the reader directly throughout.

Callout titles were checked against the house set — declarative or plain
question (`v1 behaves differently`, `Three routes are not user-scoped`,
`Using a custom backend?`) — which is why the aphorism was the one
outlier.

Re-verified after the rewording: tests back to the single pre-existing
failure, every reworded string renders on the right surface, Angular
still shows **zero** React package mentions, and the `StateGraph` step
is still gated to langgraph-python + langgraph-fastapi only.

## Coordination

Draft PR #6112 (onsclom) also touches
`integrations/built-in-agent/quickstart.mdx`, but only two prose lines —
the signup sentence and the "Already have an app?" callout. My hunks are
the install line and the runtime step, so they should merge cleanly.
Flagging rather than assuming.

## Follow-ups this surfaced

- **Threads needs a v2 server migration** from either quickstart's
starting point. No v1-shaped multi-route handler exists. Own ticket.
- **Defects 1 and 2** ride the non-interactive project-selection work.
2026-08-19 14:38:47 -05:00
Benjamin Taylor 9ffe2546ce docs(inspector): document mounting the Inspector in Angular
The Inspector is the framework-agnostic `cpk-web-inspector` web component.
`@copilotkit/angular` does not reference or mount it, so an Angular app has to
create the element itself — and nothing said so. Worse, the Angular docs mapped
the `inspector` slug onto `guides/troubleshooting`, so `/angular/*/inspector`
redirected away from the Inspector entirely and the only thing left under
"Observe & Operate" was the VS Code extension.

Add an Angular-owned Inspector page covering the mount component, the
`core` handoff with `auto-attach-core="false"`, positioning, production
exclusion, server rendering, and cleanup on destroy. Drop the redirect so the
page is reachable, and point at it from the Angular troubleshooting guide.
React's Inspector content is untouched and unmoved.

Also correct the `/cpk-debug-events` path: it is relative to the runtime's
mounted `basePath`, not the server origin, and it only carries events for a
self-hosted SSE runtime — an Intelligence-backed runtime answers runs over the
platform's realtime connection, so the stream connects and stays empty.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 14:37:03 -05:00
Benjamin Taylor 6c1a9eb4b4 docs: match the house voice in the OSS-857 prose (refs OSS-857)
A voice pass over everything added for OSS-857, measured against the
corpus rather than guessed.

Second person stays: it is emphatically the house voice — 22 of 29
top-level and backend pages use you/your, and the three pages involved
used it 17, 23 and 64 times before any of these edits. Mid-sentence
`**bold**` for emphasis also stays; the corpus does that 17 times.

What actually drifted:

- `honours` → `serves`. The corpus is American English (behavior 66:6,
  customize 77:4, serialize 18:1, organize 15:0) and the single
  `honour` in it was mine.
- `A developer adding A2UI to an agent they already wrote…` → second
  person. The corpus contains exactly two `a developer`, and one was
  mine; the page around it addresses the reader directly throughout.
- Essay register: "That default is the one thing to remember:" → a plain
  statement of the fact. "so this is the mapping" → "so this table is
  the mapping".
- Conversational: "no provider pairing to get wrong" → "to configure";
  "`uvicorn` is told to listen on 8123" → "`main.py` sets uvicorn's port
  to 8123"; "you may also meet these deprecated aliases" → "older code
  may use these deprecated aliases".
- Coinages: "agent construct" → "how the agent itself is built"; "that
  steer" → "Without it, the model tends to…".
- Aphoristic Callout title "Mismatched pair? Read the symptom, not the
  code" → "A mismatched pair fails at discovery". House titles are
  declarative or plain questions ("v1 behaves differently", "Three
  routes are not user-scoped", "Using a custom backend?").
- Epigram: "It replaces your agent; it does not connect to one." → "It
  replaces your agent rather than connecting to it."
- Redundancy: "nothing supplies persistence for you" → "nothing
  supplies persistence".

The a2ui and LangGraph quickstart wording landed in #6566; those files
are corrected here so the whole ticket reads in one voice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 13:50:19 -05:00
Benjamin Taylor 4078a11f36 docs(runtime): map the provider/handler pairs and guard BuiltInAgent (refs OSS-857)
Fixes defects 5 and 9 from the OSS-856 phase 1 validation run, plus the
half of defect 6 that lives on the Built-in Agent quickstart. Every claim
was traced through package source.

Defect 5 — three provider/handler names presented as interchangeable.
They are not interchangeable; they pair up, and the pairing is what was
undocumented. Added a "Provider and handler pairs" section to
`backend/runtime-endpoints.mdx`:

- The v1 `<CopilotKit>` wrapper renders `<CopilotKitProvider>` internally
  and pins `useSingleEndpoint` to `true` unless the prop is passed
  (`copilotkit.tsx:108`), so it asks for single-route transport even
  against a multi-route Runtime. `<CopilotKitProvider>` with the prop
  omitted resolves to `auto` and detects from `/info`.
- A table of which handlers serve which mode, and the deprecated aliases
  (`createCopilotEndpoint`, `createCopilotEndpointSingleRoute`, and the
  Express pair) mapped to their replacements.
- The constraint nobody had written down: every `copilotRuntime*Endpoint`
  wrapper builds its handler with `mode: "single-route"` and exposes no
  option to change it. Next.js App Router and node-http call the
  single-route helper directly; pages-router, node-express and nest all
  delegate to node-http. So Rich Threads is unreachable from the wiring
  the quickstarts teach at ANY provider setting — it needs a v2
  `CopilotRuntime` plus a multi-route handler. That is the structural
  reason behind defect 3.
- Provider half is scoped to `<FrontendOnly frontend="react">` with an
  Angular branch, because this page also serves the Angular surface and
  `provideCopilotKit` has no `useSingleEndpoint`.

Both quickstarts gain a short callout naming the pair they use and
linking the mapping.

Defect 9 — the Built-in Agent quickstart (what `/quickstart` actually
serves) instantiates `new BuiltInAgent(...)` as the `default` agent with
nothing warning a reader who already has one. `BuiltInAgent` extends
`AbstractAgent` and calls the model directly via `streamText`, so
registering it replaces the developer's agent rather than connecting to
it — the `user_code_preservation` violation the ticket describes. Added a
caution telling readers with an existing agent to take the frontend steps
here and the runtime wiring from their framework's quickstart.

Defect 6, second half — the same page installed `@copilotkit/react-ui`
and never used it, importing `CopilotKit` and `CopilotSidebar` from
`@copilotkit/react-core/v2`. Dropped it, matching the LangGraph fix in
#6566.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 13:35:43 -05:00
copilotkit-qa-bot[bot] 573a614112 Merge main into codex/fac-126-strands-ts-starter 2026-08-19 11:34:30 -07:00
copilotkit-qa-bot[bot] b9d41c0e3a Merge main into codex/fac-126-strands-ts-starter 2026-08-19 11:31:21 -07:00
Benjamin Taylor 99d3f99f4c docs(backend): construct the Intelligence client and name its key (refs OSS-857)
Fixes OSS-857 defects 1 and 2, which are one root cause. No page on the web
path ever constructs `CopilotKitIntelligence`, so `intelligence` reads as an
undefined identifier in the `new CopilotRuntime({ agents, intelligence,
identifyUser })` example, and `INTELLIGENCE_API_KEY` reads as a credential
with no consumer. `apiKey` IS that consumer.

The construction was already documented correctly, but only on the Channels
pages (frontends/slack.mdx, frontends/teams.mdx). This lifts the same pattern
onto the web path rather than inventing a second vocabulary for it.

Verified against packages/runtime source rather than inferred:

- `CopilotKitIntelligence` is exported publicly from `@copilotkit/runtime/v2`
  via intelligence-platform -> v2/runtime/index.ts -> v2/index.ts
- `apiKey` is the only required field of `CopilotKitIntelligenceConfig`
- `apiUrl` and `wsUrl` default to the managed platform, and
  `warnOnPartialHostOverride` logs a warning when one is set without the other,
  which is why the docs now say to override both together

The Inspector page was NOT wrong to show `NEXT_PUBLIC_COPILOTKIT_LICENSE_KEY` --
that is the correct variable for that purpose. The defect is that a reader whose
.env holds `INTELLIGENCE_API_KEY` cannot tell whether the two are the same
credential. So that page disambiguates rather than substitutes: publishable
browser key versus server-side project key, with a pointer to what consumes the
latter.

Not verified: the site build and its vitest suite. A fresh worktree has no
installed toolchain (oxlint is absent), and oxlint covers JS/TS rather than MDX,
so it would not have exercised these edits. What was checked instead: <Step>,
<FrontendOnly> and code-fence balance in both files, and both new links against
existing usage -- `](/inspector)` appears 7 times and
`](/backend/runtime-endpoints)` 10 times elsewhere in the content tree. The site
soft-404s on unknown paths, so a link cannot be verified by status code.

Defects 5 and 9 remain open and are not addressed here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 13:16:39 -05:00
Benjamin Taylor f24c4e2f22 docs(langgraph): correct the A2UI StateGraph framing after re-verification (refs OSS-857)
Three fixes found on a second pass over the docs changes:

- The new StateGraph step claimed "the snippet above is the reference
  cell's `create_agent` form". It is not: `create_agent` appears on that
  page only as an *import* — both snippet regions stop inside the tool
  body, so the agent construction is never shown at all. Reworded to say
  that, which is the sharper version of defect 11: the page never shows
  how the tool attaches to any agent, leaving `create_agent`,
  `CopilotKitMiddleware` and `ChatOpenAI` as imports the reader cannot act
  on.
- Carry over the system-prompt caveat. The reference cell steers the model
  to call `display_flight` once and stop because the tool result *is* the
  card; a StateGraph reader who drops that gets repeat tool calls.
- The install note named only two of the four packages the FastAPI tab
  adds on top of the shared line. List all four.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 12:39:11 -05:00
Benjamin Taylor 3ec309b724 docs(langgraph): fix 8 verified defects in the LangGraph onboarding docs (refs OSS-857)
Fixes defects 3, 4, 6, 7, 8, 10, 11 and 12 from the OSS-856 phase 1
validation run. Every claim below was re-verified against installed
package source or a live run, not recalled.

LangGraph quickstart (`integrations/langgraph/quickstart.mdx`):

- Route shape: a caution at the route step. The POST-only route runs the
  runtime in single-route mode, which is all chat needs; Threads and the
  Inspector need the multi-route catch-all with GET/POST/PATCH/DELETE.
  Links to the canonical runtime-endpoints section.
- Port: bare `langgraph dev` serves 2024, not 8123. Verified against both
  CLIs (`@langchain/langgraph-cli` help output, and `default=2024` in
  `langgraph_cli/cli.py`). The guide keeps `--port 8123` to stay
  consistent with every sibling page, and now says so.
- Drop `@copilotkit/react-ui` from the install list. `CopilotSidebar`
  lives in `@copilotkit/react-core/v2`; react-ui exports no `./v2` JS
  entry point and the v2 react example does not depend on it.
- Checkpointer: state the reason each tab differs. `langgraph dev` fails
  to load a graph compiled with a custom checkpointer (reproduced), while
  the FastAPI tab needs one because `ag-ui-langgraph` calls
  `graph.aget_state(...)`, which raises `ValueError: No checkpointer set`.
- Narrow the shared `uv add` line to what both tabs import, and warn that
  a project with exact pins should add them by hand.

A2UI fixed schema (`generative-ui/a2ui/fixed-schema.mdx`):

- Add the missing install step for `@copilotkit/a2ui-renderer` + `zod`,
  which the catalog/definitions/renderer snippets all import.
- Add a `StateGraph` + `ToolNode` form for developers who already have a
  hand-built graph, gated to the Python LangGraph slugs by a new
  `a2ui_agent_form` docs flag so the shared page does not show Python to
  langgraph-typescript or LangGraph code to LlamaIndex/ADK/Mastra.
- Repoint the cross-tree `/integrations/langgraph/...` link, which 301'd
  back to this same page, at the action-handler reference it promises.

Raw Markdown pipeline (`src/lib/llm-text.ts`):

- `renderPageToLlmText` never applied `filterFrameworkScopedBlocks`, so
  `/<framework>/<page>.md` emitted every `<WhenFrameworkHas>` branch with
  raw JSX tags, each carrying the one selected framework's snippet. On the
  A2UI page that produced three mutually-exclusive "how the schema is
  delivered" sections whose prose contradicted the identical code under
  each. Gate on the same framework the snippets resolve to, with a
  regression test.

Also corrects a factually wrong comment in the langgraph-python showcase
`.env.example` that claimed 8123 was the `langgraph dev` default — the
same mis-belief this ticket found in the docs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 12:19:52 -05:00
Mark 38b013c5a0 fix(showcase): cap public Claude demo traffic 2026-08-19 10:06:08 -07:00
copilotkit-qa-bot[bot] c81c6e2535 fix: harden Strands TypeScript request boundaries 2026-08-19 08:45:15 -07:00
copilotkit-qa-bot[bot] 1d32e8bd31 Merge main into codex/fac-126-strands-ts-starter 2026-08-19 08:18:38 -07:00
Alem Tuzlak 06cef9e659 feat(web-inspector): add view thread in your app
Let the Inspector load a saved thread into the official React or Vue chat. Core owns a two-way EventClient bridge. Official chat configuration applies an in-memory override that wins over a pinned threadId. Production builds hide the action.
2026-08-19 13:50:39 +02:00
Ran Shem Tov a1ca0150b8 feat: configure Claude cookbook model 2026-08-19 11:15:11 +02:00
copilotkit-qa-bot[bot] bd91313517 feat: add AWS Strands TypeScript starter 2026-08-18 15:51:47 -07:00
copilotkit-qa-bot[bot] 4879b941ab docs(deepagents): make state rendering example executable 2026-08-18 14:40:02 -07:00
copilotkit-qa-bot[bot] ed5d370936 docs: initialize shared-state rendering example 2026-08-18 14:08:48 -07:00
copilotkit-qa-bot[bot] c45a50fa71 docs: scope tool setup copy to Claude 2026-08-18 13:45:59 -07:00
copilotkit-qa-bot[bot] 40608dc01d docs: show Claude tool-rendering backend wiring 2026-08-18 12:53:15 -07:00
copilotkit-qa-bot[bot] 35f14ff4d0 fix(showcase): prune Claude test deps and clean snippets 2026-08-18 11:02:30 -07:00
copilotkit-qa-bot[bot] a234b6836d fix(docs): repair latest-main docs regressions 2026-08-18 10:29:08 -07:00
copilotkit-qa-bot[bot] f5c4279bd3 fix(showcase): route docs auth through the matching Ops environment 2026-08-18 10:28:51 -07:00
copilotkit-qa-bot[bot] ec4439c8d9 Merge origin/main into codex/ent-1157-shared-clerk-session 2026-08-18 10:28:01 -07:00
copilotkit-qa-bot[bot] 778dde6627 test(showcase): cover Claude SDK MCP wiring 2026-08-18 10:01:58 -07:00
copilotkit-qa-bot[bot] 0d528d57cc docs(showcase): expose Claude fixed-schema backend wiring 2026-08-18 09:48:32 -07:00
Benjamin Taylor dc2aee1218 docs(channels): name which Microsoft bot identity Teams setup creates
The docs said only what setup does not create — no Azure subscription, no
Azure Bot resource. That answers nothing for the tenant administrator who has
to account for a new identity in their own directory, and the only way to
learn the answer was to read our CLI source and notice `--teams-managed`.

Names the kind we create and contrasts it with the two alternatives: where the
credentials live, who rotates them, that it is single-tenant, and that nothing
is billable. Also states that the choice is effectively permanent, since the
app ID is the manifest's bot ID.

Kept to one section on the tutorial page, which already carried the
bot-ownership sentence, rather than a new page. It sits after the orientation
links as an `h2` alongside the page's other sections; as an `h3` wedged between
the intro and those links, the links read as part of it.

refs OSS-833

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 20:21:04 -07:00
Benjamin Taylor 1b7d56029c docs(channels): correct the Teams package hand-off
The rewrite claimed the command "installs it to a Team you choose" and that
"there is no package to download". Neither is true. Microsoft exposes no
install API, so `runAutomaticTeamsProvision` writes
`<channel-name>-teams-app.zip`, prints upload steps, and blocks on Enter
before verifying the installation. The old prose and the Teams tutorial's
"upload the complete zip that setup produced" also contradicted each other.

Documents what the command actually hands you: the package path, that the
upload must come from the team's own Apps tab rather than the personal Apps
section — personal scope yields a working DM that cannot be promoted — and
that a tenant disallowing custom apps means Ctrl-C, get an administrator to
install it, and re-run to resume rather than create a second app.

Also covers `--teams-package`, which the wizard adds when the reader
customizes branding: the browser builds that file, the CLI validates it,
builds the app from it, and deletes the local copy. It decides how the app
looks and does not replace the Team upload.

Strikes "no Azure subscription and no Azure Bot resource are involved" from
the Intelligence step. The Teams tutorial still says it, once, where a reader
arriving with Azure expectations actually starts.

The doc test pinned that struck sentence. It now pins the package hand-off
instead, which is the claim that was wrong and would otherwise drift back.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 20:21:04 -07:00
Benjamin Taylor df8ae72069 docs(channels): document the shipped Teams setup flow
The Teams docs described a flow that no longer exists: registering an app
by hand in Microsoft Entra, pointing an Azure Bot at the Intelligence
messaging endpoint, pasting a client ID, tenant ID, and secret into the
wizard, and downloading a package to upload. Setup is now a single CLI
command that creates a Teams-managed bot in the reader's own tenant,
registers the endpoint, and installs the app.

Also corrects the file permission. The manifest requests the read-only
`Files.Read.All`, not `Files.ReadWrite.All`, and it is optional: skipping
it costs only files uploaded to a Team channel, and no longer holds the
connection back from reporting ready.

The doc test pinned the old prose, so it is repointed at the new
contract — the command's flags, both permissions and which is optional,
and that Entra and Azure Bot appear only to say they are not involved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 20:21:04 -07:00
Ben Taylor 983c205feb fix: stale useCoAgent node name, silent content-part drops, and the LangGraph docs gaps (#6520)
Bundles the CopilotKit-side work from **OSS-769**, **OSS-767**
(partial), and the unshipped remainder of **OSS-609**.

## OSS-769 — `useCoAgent().nodeName` never updates

`useAgentNodeName` tracked the current node in a ref and returned
`nodeNameRef.current`. Mutating a ref schedules no render, so a
component reading `useCoAgent().nodeName` kept showing whichever node
was current at its last render and never updated on its own — it only
appeared to work when something unrelated happened to re-render it.

Backing the value with state fixes it. Five lines, no API change.

## OSS-767 (partial) — silent content-part drops (#1748)

`normalizeMessageContent` handles only `text` and `binary` parts;
anything else — the `{"type": "image", ...}` case from the report — maps
to `""` and is filtered out with no signal, so an agent emitting
structured content sees its output vanish silently.

This makes the drop visible, once per unrecognised part type so
streaming doesn't flood the log. Deliberately **not** the schema change:
carrying structured assistant content needs an `AssistantMessage`
decision upstream in `ag-ui`, which stays open on OSS-767.

## OSS-609 — the five docs gaps that never shipped

Gap #2 shipped in #6403; gaps 1, 3, 4, 5 and 6 did not.

| Gap | Where | Closes |
| --- | --- | --- |
| AWS Lambda self-hosting | `docs/deploy/aws-lambda.mdx` | #1151 |
| Per-user thread authorization | `docs/auth.mdx` (new section) | #2241
|
| Thread persistence without the platform |
`docs/threads-self-managed.mdx` | #6090 |
| DIY guardrails / DLP | `docs/integrations/langgraph/guardrails.mdx` |
#3414 |
| When you need an MCP App | `docs/agentic-protocols/mcp.mdx` (new
section) | #5991 |

The Lambda guide leads with the constraint that actually bites —
streaming is opt-in on every front door, so a chat runtime deployed with
the defaults appears to hang for the whole run and then dumps the reply
at once. It documents the Function URL + `RESPONSE_STREAM` path as the
default, and API Gateway REST + `responseTransferMode: STREAM` for
anyone who needs a REST API in front.

`threads-self-managed` follows the existing shared-snippet pattern with
per-framework wrappers, because two nav contracts require it: every
authored framework must publish the page, and every React destination
must map to an Angular one (`ANGULAR_DOC_REDIRECTS`). All nine wrappers
were confirmed necessary by deleting one and watching the suite fail.

## Review corrections

Two blockers from @MikeRyanDev, both verified against primary sources
before changing anything.

**API Gateway REST APIs can stream**
([`91b3e632d5`](https://github.com/CopilotKit/CopilotKit/commit/91b3e632d5)).
The guide was built on the pre-November-2025 limitation and claimed no
API Gateway type supports response streaming, steering readers to a
buffered `serverless-http` setup. REST gained it via
`responseTransferMode: STREAM`, which also lifts the 10 MB cap and
29-second timeout. REST and HTTP are now split; REST is documented as a
streaming front door (payload-format-1.0 event adapter, `AWS_PROXY`
integration on the `2021-11-15/.../response-streaming-invocations` URI,
CLI/CDK/SAM config), and the buffered fallback is scoped to HTTP APIs
and ALB, which still have no streaming path. Added the constraints that
actually matter for chat: the 30-second idle timeout on edge-optimized
endpoints (5 min Regional), and the console Test tab always buffering so
a working config looks broken.

**`identifyUser` is the platform's thread-scoping binding**
([`91b3e632d5`](https://github.com/CopilotKit/CopilotKit/commit/91b3e632d5)).
The section told every reader to build an ownership table and enforce it
in `onBeforeHandler`. On the Intelligence path the runtime already
resolves `identifyUser(request)` server-side and carries that id to the
platform; `listThreads` is scoped by user *and* filtered by `agentId`,
so the "every user of one project sees that project's threads" claim was
wrong. `identifyUser` is now documented as the binding, and the DIY
pattern is scoped to SSE runtimes, custom stores, and the local
in-memory runner.

**Follow-up correction — two routes are genuinely unscoped**
([`240672ff56`](https://github.com/CopilotKit/CopilotKit/commit/240672ff56)).
My rewrite then over-claimed. `handleGetThreadEvents` and
`handleGetThreadState` resolve the caller and discard it, and the
platform client takes no `userId` on either method
(`client.ts:1113`/`1135`) — unlike `getThreadMessages` at `1063`. Both
hit project-authenticated `_inspect` endpoints, so any caller
`identifyUser` accepts can read the event log and agent state of **any
thread in the project** given its id. The blanket guarantee is replaced
by a per-route table marking those two explicitly unscoped, plus an
`onBeforeHandler` guard narrowed to them.

That is a live gap in shipped runtime code, not a docs error, and it is
tracked as **OSS-851** — a platform-side `_inspect` change plus matching
runtime/client work and tests, out of scope for a docs PR. The interim
callout in `auth.mdx` comes out when OSS-851 lands.

## Not in this PR

**OSS-772** and **OSS-773** are already merged in
`oss-path-to-production` (#237, #238). Both are telemetry-sink changes
with no CopilotKit-side component. OSS-773's remaining half — re-keying
runtime `distinct_id` from email to the Clerk subject — is recorded on
the ticket as an open decision, not a task.

## Testing

**OSS-769.** New `use-agent-nodename.test.tsx`, 5 tests. Against
unmodified `origin/main`, **4 of 5 fail**:

```
× re-renders consumers on every node transition
× reports 'end' when a run errors
× resets to 'start' when a new run begins
✓ unsubscribes on unmount
× carries the agent, thread, and current node
  Tests  4 failed | 1 passed (5)
```

With the fix: `Tests 5 passed (5)`. These assert only re-render
behaviour under normal `act()` flushing — no manufactured intra-batch
window.

**Full react-core suite:** `Tests 7 failed | 1496 passed (1503)`. All 7
failures are **pre-existing** `ResizeObserver is not a constructor`
under jsdom, confined to `CopilotChatView.pinToSend` and
`use-pin-to-send` — neither of which this PR touches.

**Typecheck:** `packages/react-core` → `tsc --noEmit` exit 0, no output.

**OSS-767:** 3 new tests covering the warn, warn-once-per-type, and
no-warn-for-supported-types. `src/graphql/message-conversion/` → `Tests
125 passed (125)`.

**Docs:** `showcase/shell-docs` → `Tests 1 failed | 373 passed (374)`.
The single failure (`channels-docs > publishes the Channels overview
only through provider navigation`) is **pre-existing**; baselining with
all changes stashed reproduces it and nothing else. Re-run unchanged
after both review-correction commits.

**Review corrections.** The AWS rewrite was checked against the AWS
sources rather than written from memory — the REST streaming
announcement, `configuration-response-streaming`,
`response-transfer-mode` (endpoint-type idle timeouts, unsupported
buffered-only features), `response-streaming-lambda-configure`
(CLI/OpenAPI shapes), the CFN `Integration` reference, and the CDK
`ResponseTransferMode` enum. Two details corrected in passing:
`InvokeWithResponseStream` authorizes against plain
`lambda:InvokeFunction` (no new grant, contrary to what the streaming
URI suggests), and ALB still has no Lambda streaming path.

The auth corrections were verified by reading the handlers and the
platform client, not the tests — `resolve-intelligence-user.ts`,
`intelligence/threads.ts` (every `resolveIntelligenceUser` call site),
and `intelligence-platform/client.ts`. The existing tests assert the
`threadId`-only call shape, so they pass under the defect and could not
have surfaced it. Also corrected: there is no `threads/delete` route —
delete is `DELETE` on `threads/update` (`fetch-handler.ts:606`).

Both edited pages MDX-compile clean, and all inbound
`#thread-authorization` anchors still resolve after the h3→h4 demotions.

Two nav tests broke during this work and are fixed rather than papered
over — adding a page to the Rich Threads group violated the
cross-framework ordering contract and the React→Angular parity contract:

```
src/lib/__tests__/docs-render.test.ts
src/lib/__tests__/angular-docs-content.test.ts
  Test Files  2 passed (2)
       Tests  33 passed (33)
```

All 15 internal links in the new pages resolve against the content tree.

Closes #1151, #2241, #3414, #5991, #6090
Refs #1748, OSS-851
2026-08-17 19:17:50 -05:00
copilotkit-qa-bot[bot] eb567d44ae fix(docs): address programmatic control review feedback 2026-08-17 16:31:46 -07:00
copilotkit-qa-bot[bot] 1cc34c641a fix(docs): make programmatic control example self-contained 2026-08-17 16:09:35 -07:00
copilotkit-qa-bot[bot] ecaa5c5fd8 fix(docs): validate Claude run input before streaming 2026-08-17 15:47:46 -07:00
Benjamin Taylor 21ab0c6eb6 docs(auth): add agent/stop to the unscoped routes, demote identifyUser
The previous commit claimed every route resolves the caller through
identifyUser. It does not. handleStopAgent never resolves a user at all:
it calls runtime.runner.stop({ threadId }) directly, and
IntelligenceAgentRunner.stop looks the run up by threadId alone. Any
caller who learns an active threadId can abort that run mid-flight, and
an application relying on identifyUser as its authentication backstop is
not covered on this route because the callback is never invoked.

Audited every route on the Intelligence path rather than patching the one
that was reported. agent/stop is the only additional gap: agent/suggest
deliberately skips thread persistence, and threads/clear is a no-op off
the in-memory runner, which is the only runner exposing local thread
endpoints.

Drop the false universal-resolution claim, add agent/stop to the No row
and the targeted guard, and state plainly that onRequest is the
authentication gate while identifyUser only names an already
authenticated caller. The guard uses a switch rather than an array
membership test so route narrows and route.threadId type-checks; the
includes form fails with TS2339, verified against the real RouteInfo.

Refs OSS-851

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:29:17 -05:00
Benjamin Taylor 383c3f697c docs(auth): flag threads/events and threads/state as unscoped
The revised thread-authorization section claimed the Intelligence runtime
scopes every thread-bearing route to the resolved user. It does not.

handleGetThreadEvents and handleGetThreadState resolve the caller through
identifyUser and then discard the result, calling getThreadEvents({
threadId }) / getThreadState({ threadId }). The platform client takes no
userId on either method — both hit project-authenticated _inspect
endpoints — so any caller identifyUser accepts can read the event log and
agent state of any thread in the project given its id.

Replace the blanket guarantee with a per-route table, and document the
onBeforeHandler guard narrowed to those two routes so the Intelligence
path is not told there is nothing to build.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor 9ea276b740 docs: correct API Gateway streaming and Intelligence thread scoping
Two review corrections.

API Gateway REST APIs gained Lambda response streaming in November 2025
via responseTransferMode: STREAM, which also lifts the 10 MB payload cap
and the 29-second integration timeout. The guide claimed no API Gateway
type can stream and steered readers to a buffered serverless-http setup.
Split REST from HTTP, document the REST streaming path (payload format
1.0 adapter, AWS_PROXY integration on the response-streaming-invocations
URI, CLI/CDK/SAM config), and scope the buffered fallback to HTTP APIs
and ALB, which still have no streaming path.

The thread-authorization section told every reader to build an ownership
table and enforce it in onBeforeHandler. On the Intelligence path the
runtime already resolves identifyUser(request) server-side and passes
that user id to run, connect, the thread reads, the mutations, and the
subscription token; listThreads is scoped by user and filtered by
agentId. Document identifyUser as the platform binding and scope the DIY
pattern to SSE runtimes, custom stores, and the local in-memory runner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor 6548d59f40 docs(mcp): distinguish when an MCP App is and is not needed
mcp.mdx treated all non-App MCP servers generically, leaving #5991's
question unanswered: readers could not tell whether their server needed a
UI resource at all.

Separates the three cases — read-only context servers (no renderer needed),
action servers (renderer plus human-in-the-loop approval), and interactive
MCP Apps — with the test for choosing between them.

Closes #5991

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor 98e02e9a4c docs(langgraph): add a guardrails and DLP how-to
Only adjacent coverage existed — the AG-UI middleware guide and a
third-party governance cookbook — so #3414's question about input/output
screening had no first-class answer.

Covers the built-in PIIMiddleware first, then custom AgentMiddleware for
input screening (before_model + jump_to), output and DLP screening
(wrap_model_call), and tool-call screening, plus why guardrails must be
ordered ahead of CopilotKitMiddleware.

Closes #3414

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor e996328f15 docs(threads): answer the bring-your-own-thread-backend question
#6090 asked how to point CopilotKit threads at a different database. There
is no such extension point, and nothing said so — the honest answer is that
Rich Threads are an Enterprise Intelligence Platform capability, and the DIY
path is own-the-threadId plus framework-layer persistence.

Documents that path and what it costs relative to Rich Threads. Body lives
in a shared snippet with the usual per-framework wrappers, since the nav
parity contract requires every authored framework to publish the page and
every React destination to map to an Angular one.

Closes #6090

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00
Benjamin Taylor 0e724231ec docs(auth): document per-user thread authorization
auth.mdx covered token forwarding and the onRequest gate but stopped at
authentication. Nothing tied a threadId to a user, so a caller who learned
another user's thread id could reach it through every thread route.

Adds the ownership-table pattern and the onBeforeHandler enforcement point,
including which routes carry threadId on `route` versus in the request body,
and why the thread list has to be filtered server-side.

Closes #2241

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 17:25:01 -05:00