Commit Graph

1065 Commits

Author SHA1 Message Date
Ben Taylor f2c9a2ecfe docs(react-core): clarify system_prompt requirements for useFrontendTool (#5469)
## What does this PR do?
Adds documentation explaining that `useFrontendTool` may require
explicit `system_prompt` guidance in LangGraph agents to be reliably
called. Includes a working code example showing both a well-described
`useFrontendTool` registration and the matching system prompt
instruction. Addresses the confusion reported in #4950 where users
implement tools with only a `description` and find the agent doesn't
call them.

Changes:
- `docs/integrations/langgraph/frontend-tools.mdx` — new section
"Ensuring your agent reliably calls frontend tools" with a `Callout`,
Python+TypeScript code examples, and a decision table (description vs.
system_prompt)
- `reference/hooks/useFrontendTool.mdx` — added "LangGraph agents:
description vs. system_prompt" subsection linking to the full example
- `docs/troubleshooting/common-issues.mdx` — expanded the "tool listed
but agent never calls it" bullet to cross-link the new guide

## Related PRs and Issues
- Closes #4950

## Checklist
- [x] I have read the Contribution Guide
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] "Allow edits by maintainers" is checked
2026-08-20 14:39:34 -05:00
Ben Taylor 6c955686eb feat(react-core): expose AG-UI raw event to feedback callbacks (#6289)
## Summary

React v2 feedback callbacks receive an assistant message without the
trace metadata carried by the direct AG-UI event that created it. This
slice exposes that metadata to thumbs callbacks without changing
canonical messages or future run inputs.

## Root cause

AG-UI keeps `rawEvent` on events while reducer-created assistant
messages remain protocol-clean. `StateManager` sees the direct start
event but previously discarded its correlation before
`CopilotChatMessageView` forwarded the message to feedback callbacks.

## Changes

- Store defined direct `TEXT_MESSAGE_START.rawEvent` metadata by agent,
thread, and message.
- Replace repeated scoped entries and prune them with message removal
and lifecycle cleanup.
- Return a cloned sidecar value through
`CopilotKitCore.getRawEventForMessage`.
- Enrich only thumbs-up and thumbs-down callback arguments at click time
across flat and virtualized rendering.
- Add production-path regressions and document the callback-only type.

## Out of scope

Canonical messages, future `RunAgentInput.messages`, render props,
message identity, stream ordering, snapshots, transformed chunks,
persistence, GraphQL, legacy React, Vue, Angular, and standardized trace
semantics remain outside this slice.

## Related PRs and Issues

Addresses #3039.

The callback-only scope follows
https://github.com/CopilotKit/CopilotKit/issues/3039#issuecomment-5086936452.
Related trace-correlation contract: #4634.

## Test plan

- [x] StateManager sidecar tests, 10 passed. Covers direct capture,
falsey values, replacement, scope isolation, cleanup, snapshots, and
chunks.
- [x] React v2 feedback tests, 4 passed. Covers real callback routing,
canonical and outbound cleanliness, render identity, and flat/virtual
paths.
- [x] Full package suites, 625 core tests, 1,475 React Core tests, and 2
script tests passed.
- [x] Typecheck, formatting, lint, and whitespace validation passed;
lint reported five pre-existing warnings.
- [ ] CI green (`static / quality`, `test / unit` on Node 20/22/24).

## Notes

The clean-base behavioral half of the reproduction remains unproved
because temporary worktree setup hung behind unrelated Git processes.
The PR makes no base execution claim for that half.
2026-08-20 14:17:24 -05:00
Ben Taylor 27431412e6 fix(react-core): stop the compat CopilotKit wrapper pinning useSingleEndpoint (#6605)
Refs [OSS-888](https://linear.app/copilotkit/issue/OSS-888).

## The failure

A correctly assembled v2 integration 404s on its first browser request
while every static check passes and `GET /info` returns 200.

`packages/react-core/src/v2/index.ts:28` re-exports the **v1-compat**
`CopilotKit` wrapper, so it is the provider most integrations reach for.
That wrapper pinned:

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

which overrode the core's `"auto"` negotiation and forced single-route
transport. But **every** v2 handler defaults to `mode: "multi-route"`
(`endpoints/hono.ts:95`; `createCopilotEndpoint` is an alias at `:90`).
Nothing serves the single-route envelope the client sends, so the
runtime 404s while the provider looks connected.

## What this is *not*

The library defaults do not actually disagree. `CopilotKitProvider` (the
real v2 provider) leaves the flag undefined → `"auto"`, which probes
`GET /info` and falls back to the single-route envelope
(`core/agent-registry.ts` `fetchRuntimeInfoAutoDetect`) — it works
against **either** handler mode. Only the compat wrapper defeated that.

So this is one line of override, not a defaults mismatch needing a
direction chosen.

## Why four onboarding runs hit it, not one

The library bug alone doesn't explain a 100% failure rate. The shipped
`react-core` skill does:

`packages/react-core/skills/react-core/references/provider-setup.md` —
bundled in the npm tarball (`files: ["dist","skills"]`) — **mandated**
the compat wrapper, **forbade** `CopilotKitProvider` as "a subset of the
functionality", and mentioned `useSingleEndpoint` **zero times** across
~10 code samples. An agent following it wrote the 404 configuration
every time.

Meanwhile `skills/copilotkit-setup/SKILL.md` got it right, so the two
shipped skills contradicted each other and nothing gated either against
the code.

## The change

**Commit 1 — the library fix.** The prop already arrives through
`v2Props`, so dropping the override lets it stay `undefined` and inherit
`"auto"`. An explicit `useSingleEndpoint` still wins in both directions.

**Commit 2 — the docs and skills.** Correcting the default made ~15
pages' explanations false. Code samples that pass `{false}` stay valid
(they pin what negotiation would find anyway), so this corrects the
*explanations* rather than the samples — keeping every page true both
before and after release. Includes dropping the now-false causal claim
from the single-route-envelope diagnostic added in #6579.

## Compatibility

Safe for existing v1 apps. A v1 app on a single-route-only handler
(`copilotRuntimeNextJSAppRouterEndpoint` and friends) now does one `GET
/info` that 404s, then falls back to single-route and works. Cost is one
extra request on connect.

One edge case worth a reviewer's eye: if a deployment's `runtimeUrl` +
`/info` returns 200 from something that is *not* a multi-route
CopilotKit runtime (a catch-all proxy serving HTML, say), `"auto"` would
resolve to `rest`. Setting `useSingleEndpoint` explicitly remains the
escape hatch.

Conventional-commit note: this lands as `fix`, but it *does* change a
public default. Flag if you'd rather it carried a minor bump.

## Tests

- New `copilotkit-transport-default.test.tsx` — omitted → `"auto"`,
`{true}` → `"single"`, `{false}` → `"rest"`. Confirmed RED first
(`expected 'single' to be 'auto'`).
- `CopilotChat.readinessGate.test.tsx` depended on the old default to
avoid a REST probe. Single-route transport is a **precondition of that
fixture**, not the behaviour under test, so it now pins the flag
explicitly and its stale comments are corrected. Its coverage (readiness
gate across the real SSE boundary) is unchanged.
- `react-core` 1512 passed · `runtime` 2073 passed · `core` 668 passed.
- `pnpm check:plugin-skills` in sync (`skills/react-core/` is the
generated mirror).

`showcase/shell-docs`'s own vitest suite fails to load 35 files with
`Cannot find package 'react/jsx-dev-runtime'` — reproduced identically
on unmodified `origin/main`, so it is environmental in this checkout and
unrelated. All 183 tests that do run pass.

## Not addressed here

Nothing gates a shipped skill against the code it documents, which is
why `provider-setup.md` could contradict both the library and the
sibling skill indefinitely. Worth its own ticket.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-20 14:09:18 -05:00
Mark 0298616223 docs: add Claude Managed Agents cookbook (#6430)
## Summary

- add an independently runnable Claude Managed Agents finance-assistant
example
- add a cookbook recipe that explains the CopilotKit runtime,
managed-session mapping, and tool rendering flow
- add the recipe to cookbook navigation, the overview grid, sidebar icon
mapping, and render coverage
- use the real Claude vector mark for the cookbook instead of the
text-placeholder SDK asset
- register the example's Vite configuration and managed-agent model with
the repository CI allowlists
- include a compact architecture diagram and links to the relevant
rendering and CopilotKit Intelligence documentation
- disable Claude's complete built-in toolset and expose only the scoped
`show_growth_projection` runtime tool
- make the provisioning model configurable through `ANTHROPIC_MODEL`,
defaulting to `claude-fable-5`
- bound CopilotKit request bodies to 256 KB and managed-agent turns to
90 seconds, while relying on the adapter's per-thread serialization
- cap public run traffic at 20 provider-like attempts per client IP per
minute and 2,000 successful starts per process per 24-hour window
- restrict browser runtime requests with an exact Origin allowlist that
supports same-origin or separately hosted frontends, and restrict iframe
parents with CSP `frame-ancestors`
- validate persisted managed-agent IDs at startup so malformed local
configuration fails immediately
- publish the interactive example on Railway and embed the live
deployment in the cookbook
- align the demo with the existing cookbook chat styling and show the
`Project monthly investing` starter on first load

## Demo

![Claude Managed Agents finance assistant rendering an interactive
growth
projection](https://github.com/CopilotKit/CopilotKit/blob/f36cb2b8eee8084aa6e37a200175532f4ecdca02/examples/showcases/claude-managed-agents/demo.png?raw=1)

## Why

This gives developers a focused example of connecting CopilotKit to
Anthropic Claude Managed Agents without the extra surface area of a
larger analyst application. The recipe follows the existing cookbook
structure and keeps the live demo compact enough for the standard
cookbook pane. Its managed environment has no outbound network or
package-manager access, and its agent cannot use bash, filesystem,
search, or fetch tools.

The request, turn, per-IP, and process-wide limits bound public demo
traffic without adding authentication or user friction. The traffic
counters are intentionally in memory, reset on process restart, and are
not shared across replicas, so the dedicated Anthropic workspace spend
limit remains the durable cost backstop. The exact-Origin browser check
reduces drive-by use but is explicitly documented as a control rather
than authentication. The model override allows operators to select a
lower-cost supported model during provisioning without editing source
code.

## Validation

- scoped formatting: passed
- scoped lint: 0 warnings, 0 errors
- shell-docs typecheck: passed
- standalone example typecheck: passed
- docs render tests: 26/26 passed
- standalone example tests: 23/23 passed
- shell-docs tests: 375/375 passed
- shell-docs production build: passed (222/222 pages)
- standalone example production build: passed
- standalone npm lockfile validation: passed
- build-config allowlist validator: passed
- docs model-name validator: passed
- exact-Origin regression coverage for run requests plus headerless
same-origin runtime discovery: passed
- malformed persisted agent-ID regression coverage: passed
- live Railway root and iframe CSP: passed
- live Railway runtime discovery, exact welcome copy, and first-load
starter pill: passed
- live three-turn AG-UI managed-agent run with `show_growth_projection`:
passed
- cookbook verified in the browser at desktop and narrow widths with no
console errors or horizontal overflow
2026-08-20 12:07:52 -07:00
Mike Ryan b8b19834a2 fix(runtime): unify the Intelligence key name and publish the wiring (refs OSS-881) (#6595)
## What does this PR do?

Closes the naming and documentation half of
[OSS-881](https://linear.app/copilotkit/issue/OSS-881). Paired with
CopilotKit/Intelligence#890, which adds `copilotkit verify` and tightens
the evaluation rubric.

### 1. One name for the Intelligence key

**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:

| Name | Where | Code readers |
| --- | --- | --- |
| `INTELLIGENCE_API_KEY` | what `copilotkit project select` writes; all
34 integration examples; the docs site | 34 |
| `COPILOTKIT_INTELLIGENCE_API_KEY` | 7 Channels package READMEs +
packaged skills | **0** |
| `COPILOTKIT_API_KEY` | `examples/slack`, `examples/teams`, and the
TSDoc on `CopilotKitIntelligence` itself | 2 |

`INTELLIGENCE_API_KEY` wins — 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**. Nothing
ever read it, so there is nothing to keep compatible.
- `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 third name was the worst placed: it was in the TSDoc on
`CopilotKitIntelligence`, which is what an IDE shows on hover.

This was not only untidy. The CLI's own `channels-preflight` accepts
`INTELLIGENCE_API_KEY` or `COPILOTKIT_API_KEY` — **not**
`COPILOTKIT_INTELLIGENCE_API_KEY`, the name the Channels READMEs told
people to set. So following a Channels README verbatim made `copilotkit
channels` warn that no runtime API key was present while the key sat
visibly in `.env`. After this PR the documented name is one preflight
accepts.

> [!NOTE]
> `NEXT_PUBLIC_COPILOTKIT_API_KEY` is a **different value** — the legacy
Copilot Cloud public key — and is deliberately left alone.

### 2. A real defect, not just naming skew

`skills/runtime/references/intelligence-mode.md` documented
`organizationId` as a `CopilotKitIntelligence` option, sourced from two
further env names (`COPILOTKIT_INTELLIGENCE_ORG_ID`,
`COPILOTKIT_ORG_ID`).

`CopilotKitIntelligenceConfig` has no such field — the copy-pasteable
sample it appeared in **would not compile**. Removed from the samples,
and the prose telling readers to fetch a value for it corrected. That
file is the only place those two names ever existed, which is very
likely why the failing validation run reported that "the runtime reads
`COPILOTKIT_INTELLIGENCE_API_KEY` and `COPILOTKIT_INTELLIGENCE_ORG_ID`".

### 3. Publish the Intelligence wiring

The wiring instructions existed only inside
`node_modules/@copilotkit/runtime/skills/`, and the only docs pages
mentioning `CopilotKitIntelligence` at all 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`**: the wiring itself, how to
confirm the credential is actually consumed, the self-hosted
both-URLs-or-neither rule, and a troubleshooting table. Linked into both
navs, and the skills reference now points at the published page.

### 4. A guard so it cannot drift back

`scripts/validate-intelligence-env-names.ts` (`pnpm
check:intelligence-env-names`), wired to lefthook and a new workflow.

The workflow is **intentionally unfiltered**. The two workflows that
would otherwise cover this both filter: `plugin-skills-check` by
`paths:`, and `static/quality` by `paths-ignore: examples/**` — which is
exactly where the deprecated alias lives. Scoping the job would re-open
the hole it exists to close. Legitimate alias sites live in
`ALIAS_ALLOWLIST`.

## Related PRs and Issues

- [OSS-881](https://linear.app/copilotkit/issue/OSS-881) — needs
**both** PRs; neither closes it alone
- CopilotKit/Intelligence#890 — items 1 and 4 (`copilotkit verify` +
rubric contract 1.3.0)

## Verification

- Full lefthook pre-commit ran green: `check-plugin-skills`, `lint-fix`,
the new `check-intelligence-env-names`, and `test`/`publint`/`attw`
across **25 projects**.
- `examples/slack` `managed.test.ts` extended to cover **both** the
canonical name and the alias fallback, and proven non-vacuous — removing
the fallback turns the new test red.
- The drift guard proven non-vacuous the same way: reintroducing a
retired name fails it, exit 1.
- `oxfmt` and `oxlint` clean on every file touched (0 errors).

## Checklist

- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-20 12:00:52 -07:00
Benjamin Taylor f30d3bfae5 docs: correct the useSingleEndpoint default across docs and shipped skills
The compat `<CopilotKit>` wrapper no longer pins `useSingleEndpoint` to `true`,
so every statement that it "defaults to single-route" or that a multi-route
backend "needs `{false}`" is now wrong. Code samples that pass `{false}`
explicitly stay valid — they pin what negotiation would find anyway — so this
corrects the explanations rather than the samples, keeping the pages true both
before and after the release.

The shipped `react-core` skill is the load-bearing one. `provider-setup.md`
mandated the wrapper, forbade `CopilotKitProvider` as "a subset of the
functionality", and never mentioned `useSingleEndpoint` across ~10 samples — so
an agent following it wrote the 404 configuration every time. It now documents
the transport and stops steering readers off the negotiating provider.

Also drops the false causal claim from the runtime's single-route-envelope
diagnostic (added in #6579), which named the wrapper's old default as the cause.

`skills/react-core/` is the generated mirror of `packages/react-core/skills/`,
synced with `pnpm sync:plugin-skills`.

Refs OSS-888.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 13:54:44 -05:00
Mark d50e8d7e7c Merge branch 'main' into codex/claude-managed-agents-cookbook 2026-08-20 11:40:54 -07:00
Mark 7089b3cf53 fix(showcase): harden managed-agent deployment setup 2026-08-20 11:01:06 -07:00
copilotkit-qa-bot[bot] 589239686e make tool-rendering docs layout executable 2026-08-20 10:33:12 -07:00
copilotkit-qa-bot[bot] 1698420360 keep tool-rendering example docs-only 2026-08-20 09:50:13 -07:00
github-actions[bot] cfde633882 style: auto-fix formatting 2026-08-20 16:18:04 +00:00
copilotkit-qa-bot[bot] 43fe5fde9d make tool-rendering docs dependency complete 2026-08-20 09:15:26 -07:00
Benjamin Taylor ed031949ca docs(shell-docs): state the Intelligence wiring steps directly 2026-08-20 10:52:32 -05:00
Benjamin Taylor cba6bad69b docs(shell-docs): confirm Intelligence use without an unreleased command
The page told the reader to run `npx copilotkit verify` and said it "reports
whether the runtime is wired for Intelligence at all". Neither half holds yet:
`verify` is not in the published CLI — `latest` is 4.8.3 and the command landed
after that tag — and the Intelligence-consumption check it referred to is still
in review, so even on `main` the command does not report that.

Publishing it would have documented a seam that does not exist, which is the
class of defect this change set exists to remove.

The dashboard check works today and needs no CLI at all, so it becomes the
instruction: send a message and confirm a thread appears. A runtime in SSE mode
produces none, whatever the browser showed. The `verify` route can be documented
once the command ships with the check in it.
2026-08-20 10:46:23 -05:00
Ben Taylor 9df63beeef fix(runtime): name useSingleEndpoint when a single-route envelope hits a multi-route runtime (#6579)
Closes
[OSS-882](https://linear.app/copilotkit/issue/OSS-882/add-to-existing-journeys-reach-for-the-v1-compat-copilotkit-wrapper).

## The failure

The v1-compatible `<CopilotKit>` provider pins `useSingleEndpoint` to
`true`
([`copilotkit.tsx:108`](https://github.com/CopilotKit/CopilotKit/blob/main/packages/react-core/src/components/copilot-provider/copilotkit.tsx#L108)),
so its startup handshake 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"}`, indistinguishable from a wrong
`basePath` or an unmounted handler.

Two independent onboarding validation runs hit this on their first
browser attempt and each had to guess the cause. Both were
*add-to-existing-app* journeys; the greenfield one reached for
`CopilotKitProvider` and never saw it.

## What changed

**The runtime says what happened.** `detectSingleRouteEnvelope`
recognises a POST whose JSON body carries a `method` the single-route
endpoint accepts, and the multi-route handler uses it at the one point
routing gives up. The 404 now carries a `code` and a message naming the
prop, plus a `logger.warn` so it lands in the dev-server terminal too.
Deliberately conservative — wrong verb, non-JSON, unknown method, or a
JSON POST that isn't an envelope all stay ordinary 404s, unchanged in
status and shape.

**The client stops discarding it.** All four `/info` callers (two in
`agent-registry.ts`, two in `agent.ts`) threw away the response body and
reported only the status, so a server-side diagnosis reached nobody.
They now go through `runtimeInfoError`, which folds a string `message`
from the body into the thrown error. Any future server-side diagnosis
reaches the developer for free.

**Docs.** Five pages paired a v2 multi-route handler with `<CopilotKit>`
and never mentioned the prop. Rather than a warning under a snippet that
is still wrong to copy, the snippets themselves now pass
`useSingleEndpoint={false}`, with a short callout linking to the
provider/handler mapping.

Two pages were deliberately left alone: `backend/runtime-endpoints.mdx`
already documents the pairing in full, and `cookbook/arcade.mdx` uses
`mode: "single-route"` on purpose and already explains it.
`backend/copilot-runtime.mdx` keeps its snippet as-is — it pairs with
the v1 endpoint, where the default is correct — and gains the caveat
only on its "switch to v2 handlers" note.

Option 3 in the issue (reconsidering the compat default) is **not** in
this PR.

## Testing

### Both halves connect, end to end

Real `createCopilotRuntimeHandler` + real `CopilotKitCore` configured
the way the v1 wrapper configures it — no mocks on either side:

```
code   : runtime_info_fetch_failed
message: Runtime info request failed with status 404: Received a single-route
         request envelope ({ method: "..." }) but this runtime is mounted in
         multi-route mode, so the request matched no route. If the frontend uses
         <CopilotKit> from @copilotkit/react-core/v2, pass useSingleEndpoint={false}
         — that provider defaults it to true. Otherwise mount the runtime with
         mode: "single-route" to serve this envelope.

PASS — the diagnostic reached the client
```

The server-side `logger.warn` fired in the same run, carrying `{ url,
path, method: 'info' }`.

### Unit tests

`packages/runtime` — `single-route-envelope-diagnostic.test.ts` (2
positive, 5 control):

```
 ✓ src/v2/runtime/__tests__/single-route-envelope-diagnostic.test.ts (7 tests) 26ms
      Tests  7 passed (7)
```

`packages/core` — `runtime-info-error-detail.test.ts` (2 positive, 5
control):

```
 ✓ src/__tests__/runtime-info-error-detail.test.ts (7 tests) 267ms
      Tests  7 passed (7)
```

### Mutation checks

Every new test was verified to fail when its mechanism is broken, in
both directions.

Detector forced to `return null` — the two positives die, the four
controls hold:

```
   × names useSingleEndpoint when the envelope is an info call
   × diagnoses every method the single-route envelope accepts
   ✓ leaves an ordinary unmatched route as a plain 404
   ✓ leaves a JSON POST that is not an envelope as a plain 404
   ✓ leaves an unrecognized method name as a plain 404
   ✓ does not diagnose a non-JSON POST
```

Detector forced to `return "info"` — the controls die instead, proving
they are not vacuous:

```
   ✓ names useSingleEndpoint when the envelope is an info call
   ✓ diagnoses every method the single-route envelope accepts
   × leaves an ordinary unmatched route as a plain 404
   × leaves a JSON POST that is not an envelope as a plain 404
   × leaves an unrecognized method name as a plain 404
   × does not diagnose a non-JSON POST
```

`runtimeInfoError` with the detail dropped, then with the `typeof
message === "string"` guard removed — each kills a different pair:

```
mutation: detail dropped              → 2 failed | 5 passed
mutation: accept any message field    → 2 failed | 5 passed
restored                              → 7 passed
```

### Full suites, builds, docs

| Check | Result |
|---|---|
| `packages/core` full suite | `Test Files 60 passed (60)` / `Tests 662
passed (662)` |
| `packages/runtime` full suite | `Test Files 142 passed (142)` / `Tests
2067 passed (2067)` |
| `packages/core` `tsc --noEmit` | clean |
| `packages/runtime` `tsdown` | `416 files` — build complete |
| MDX compile, 5 edited pages | all `OK` |
| pre-commit `nx run-many -t test,publint,attw` | passed across affected
projects |
| CI on `f94d1ab0` | 72 pass, 3 skipping, 0 fail |

Both suites are fully green. An earlier revision of this description
reported 6
runtime failures as pre-existing on `main`; they were not. They were
artifacts
of a worktree whose `node_modules` had been assembled by hand, and a
proper
`pnpm install` cleared all of them along with the inspector-metadata
failures
from a stale `@copilotkit/shared` dist. `main` is clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-20 10:37:40 -05:00
Benjamin Taylor f36deaaa61 fix(docs): keep the useSingleEndpoint guidance mode-aware on multi-mode pages
Two pages document both transport modes and carry a single "point your
frontend at it" snippet serving every front door on the page. Baking
`useSingleEndpoint={false}` into those snippets traded one silent mismatch for
its mirror image: correct for the multi-route majority, wrong for anyone who
followed the `mode: "single-route"` example.

Both now state the rule conditionally next to the snippet instead of asserting
one side of it. Pages with a single handler mode (auth, custom-agent) are
unambiguous and keep the prop inline.

Also pins the one path where the diagnostic could have cost more than it gives:
`clone()` throws once a before-request middleware has drained the body, so the
detector must return null and let the plain 404 stand rather than surfacing a
500. The guard existed; nothing held it in place.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 09:39:21 -05:00
Murat Sari ba41a31d7c feat: implement interrupt handling in AgentStore and add injectInterrupt function 2026-08-20 15:37:07 +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
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
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
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
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] 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