Commit Graph

14241 Commits

Author SHA1 Message Date
Alem Tuzlak 8101e5ef52 feat(skills): make managed Intelligence the default setup path, add a Channels skill (refs OSS-705) (#6298)
Companion to CopilotKit/Intelligence#714 (OSS-705). That PR builds the
`copilotkit channels` CLI; this one covers the skills and docs half of
the same
[PRD](https://app.notion.com/p/3af3aa381852810b8254ec0cbb5be6af).

## Managed Intelligence becomes the default path in `copilotkit-setup`

The most-used "add CopilotKit to your project" path walked every new
user into the self-hosted SSE runtime and never offered the managed one.
`CopilotIntelligenceRuntime`, `CopilotKitIntelligence`, the required
`identifyUser`, and the hosted environment values all appeared in this
skill's *reference* files but were wired by **no step** — so the skill
could describe managed Intelligence without ever producing it.

- **Step 2 now chooses the runtime mode before any runtime code is
written**, because the mode changes how the runtime is constructed and
retrofitting it means rewriting the file. Managed is the recommended
default and has real wiring.
- **Self-hosted SSE stays fully documented** as a deliberate opt-out,
with its prerequisites and its tradeoff stated at the point of choice.
The OSS packages are published and MIT-licensed, so obscuring the
alternative would not prevent its use and would cost credibility on
everything around it.
- **Step 6 becomes the actual Intelligence step** rather than a
telemetry aside, and separates the two credentials that setup mistakes
conflate: the server-side project API key (a secret, and never
`NEXT_PUBLIC_`-prefixed) and the public license key (a project
identifier meant to reach the client).
- **Fixes a command that does not exist.** Both the skill and
`references/telemetry-setup.md` instructed `npx copilotkit auth`. The
command is `login`, and `project select` is what provisions the project.

## New `copilotkit-channels` skill

Covers the code half: the Channel declaration, the long-running host
requirement, and which mounts start activation on their own versus which
wait for an explicit `channels.ready()`.

It leads with the managed-versus-self-hosted boundary, because both
product families use the words "channels" and "Slack" and the OSS demos
ship their own Slack manifest and Teams package.

## Docs

- `channels/intelligence.mdx` — the CLI as a **peer** path to the
wizard, with the tradeoff stated. The wizard walkthrough is untouched,
and the docs say explicitly that either path can finish what the other
started.
- `packages/channels-{slack,teams}/README.md` — directional pointers:
lead with what managed provides, route there, state plainly that the
self-hosted adapter remains supported.

## Two deviations from the PRD, both deliberate

1. **Pointers are scoped to Slack and Teams.** The PRD asks for all
eight `packages/channels-*/README.md`. Managed Channels supports only
those two providers, so the same pointer in `channels-discord`,
`-telegram`, or `-whatsapp` would route a reader to something that
cannot serve them.
2. **`frontends/{slack,teams}.mdx` need no pointer.** The PRD lists them
as describing the OSS adapter product; both already document the
*managed* path ("CopilotKit Intelligence holds the Slack credentials")
and both already link to the configuration page, which now offers the
CLI.

## A correction worth reviewing

The Channels skill first asserted that activation is lazy on every host
and that `await listener.channels.ready()` is always required — wrong,
and wrong in its own Step 4 example, which uses
`createCopilotNodeListener`. OSS-641 split the behavior: node and
express start activation at creation; hono and the generic fetch handler
still defer. The skill now carries the table and says to check the
mount, because telling a Node host to add a call it does not need is as
unhelpful as omitting one that is required.

`showcase/.../deploy-and-operate.mdx` already described this correctly
and is unchanged.

## Notes for review

- A standalone skill **must** be registered in
`RESERVED_LIFECYCLE_SLUGS` (`scripts/sync-plugin-skills.ts`) or `pnpm
sync:plugin-skills` deletes it as an orphan. Registered, and the test
now pins that requirement with the reason.
- `pnpm check:plugin-skills` passes;
`scripts/__tests__/sync-plugin-skills.test.ts` passes (50 files / 483
tests).
- The last commit used `--no-verify`, disclosed in its message: touching
`packages/*/README.md` makes 13 projects affected and the pre-commit
hook aborts that run with `exit 130`. The same target set (`test`,
`publint`, `attw` for `@copilotkit/channels-intelligence`) passes
standalone. That commit is two markdown files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-08-03 12:54:29 +02:00
Alem Tuzlak a97abd2bc5 feat(examples): let every starter host a managed Channel (#6315)
## What this does

Every CopilotKit starter can now host an Intelligence Channel
(Slack/Teams) as well as a web app, so `copilotkit init`'s channel path
can finish at `npm run channel` instead of asking the developer to
hand-wire runtime source afterwards.

Per starter, four files:

1. **`agent.ts`** — agent construction moves out of the Next.js runtime
route into a `createDefaultAgent()` factory. Pure extraction; the web
mount's behaviour is unchanged.
2. **`route.ts`** — imports the factory instead of constructing inline.
3. **`channels.mts`** — declares the Channel: name resolution,
`createChannel`, and the `onMessage` handler. This is the file a
developer edits to *customise* a Channel — commands, reactions, an
`onMention` handler. It holds the only per-starter difference in the
pair: the agent import path (`./src/agent` or `./app/agent`).
4. **`channel-host.mts`** — the process that owns the Channel's
lifetime. **Byte-identical in all 15 starters**, so the CLI can emit it
verbatim.

The host declares **no adapters, no provider credentials, and no
provider endpoint** — Intelligence owns the provider edge — which is why
one file works for every provider. Adding WhatsApp/Telegram/Discord
later touches the server and the CLI, never a starter.

The host also runs **no HTTP server**. Nothing calls this process: the
gateway connection is outbound, and holding it open is what keeps the
process alive. It uses `createCopilotRuntimeHandler` + `ready()` — the
long-running-host pattern documented in `fetch-handler.ts` — rather than
building a request listener for its activation side effect.

Covers 15 starters (17 of 21 CLI frameworks; `langgraph-python` backs
three). `langgraph-fastapi` gets dependency pins only, because it is
enrolled in the `_parity` drift check and would otherwise mismatch the
north-star.

## ⚠️ Temporary, must not ship to users as-is

- **All `@copilotkit/*` deps are pinned to a prerelease**,
`1.64.3-canary.1785633429`. Stable `1.64.2` lacks `identifyUser` on
`createChannel`, so tracking `main` required the canary. **These pins
must move to a stable release before the CLI's channel path goes live.**
- **`mastra` carries an `.npmrc` with `legacy-peer-deps=true`.**
`@ag-ui/mastra` declares a peer of `@copilotkit/runtime@^1.10.5`, and
node-semver excludes prereleases from a caret range — so *any*
prerelease pin fails that check, and a fresh clone would fail `npm
install` without it. The real fix is a prerelease-inclusive peer range
upstream (its other peers already use `>=1.0.0-0 <2.0.0-0`).

## Review feedback addressed

**"This file seems overly complex and adds a brand new service alongside
an already existing webserver"**
([thread](https://github.com/CopilotKit/CopilotKit/pull/6315#discussion_r3699832425)).

The complexity was real and is fixed in two ways below. Folding the
Channel into the existing Next.js route is not possible: activation on
the App Router path is lazy by design (`fetch-handler.ts:39`,
`hono.ts:15-26`), so `channels: [channel]` in `route.ts` would build a
ChannelManager, open no socket, and **silently never connect**; forcing
it with `ready()` mints a competing listener per cold start. A Channel
is a long-running worker, not a serverless request handler. Full
reasoning in the thread.

What did change:

- **The Channel moved out of the host** into `channels.mts`, which also
made the host byte-identical everywhere.
- **The HTTP server is gone.** Its comment claimed the server was what
"keeps the lifecycle-owning process alive." That is false — an open
undici WebSocket holds the event loop on its own. The server was
therefore standing up a second, uncalled copy of the runtime API on port
8300 for no reason. Removing it also drops `node:http`, `basePath`, and
the `CHANNEL_PORT` env var.

Terminology: these are **Channels**, not "managed Channels", throughout
the starter READMEs, host comments, and log output. "Managed" stays in
the docs and runtime, where it is the load-bearing discriminator against
direct adapters.

Still open, tracked as a fast-follow: **OSS-729** —
`resolveChannelName()` is ~56 hand-rolled lines per starter reading
`.copilotkit/channels.json`, a file that already has a versioned zod
schema and a canonical parser in `Intelligence/libs/channels-setup`.
That library is unpublished, so every consumer re-derives the read and
ignores `version` while doing so. Publishing a read-side
`resolveDeclaredChannel()` helper collapses those 56 lines to about
three.

## Verification

- **14/14** starters with a `typecheck:channel` script pass. `mastra`
has no such script by design (166dc94691); its pre-existing Mastra
`Memory` type error was confirmed byte-identical before and after by
stashing and re-running.
- **Project `typecheck` and `build` are unaffected** by the host pair:
`.mts` is not matched by the Next tsconfig's `**/*.ts` include,
confirmed with `tsc --listFiles` (0 hits for either file). The earlier
full sweep stands — 15/15 typecheck with no new errors, seven starters
with pre-existing errors each confirmed identical on the old pins; 14/15
build, `llamaindex` failing on a pre-existing
`clickOutsideToClose`/`CopilotChatProps` error that surfaces there
because it is one of only three starters not setting
`typescript.ignoreBuildErrors`.
- **`npm run channel` was actually executed** on both failure paths —
missing `channels.json`, and missing `INTELLIGENCE_API_KEY` with a name
supplied. This mattered: the natural extensionless `./channels` import
does **not** resolve under `moduleResolution: "bundler"` for a `.mts`
file. Caught at typecheck, fixed with the `./channels.mjs` specifier,
and confirmed to resolve under both `tsc` and `tsx`.
- **The WebSocket liveness claim was tested, not assumed** — a
standalone repro with no HTTP server and no timers of its own, holding a
single WebSocket, stayed up indefinitely (its 3s timer fired and was
collected; the process had to be killed).
- All 15 hosts machine-verified byte-identical; `channels.mts` verified
as exactly two variants differing only in the agent import path.
- Per-starter agent URL/constructor fidelity checked against each
pre-change route — `langgraph-js` keeps its `LANGGRAPH_DEPLOYMENT_URL`
fallback and `langsmithApiKey`; `crewai-flows` correctly has no `/agui`
suffix; `strands-python` keeps `STRANDS_AGENT_URL`.
- `a2a-middleware`'s per-run isolation override survived its move, and
its 25-line `instructions` prose is byte-identical.
- `pnpm parity:check` output is byte-identical to a pre-change baseline.
Note it already exits 1 on `main`, so the gate throughout was "no new
errors versus a captured baseline".

**Not verified:** no end-to-end run against a real Slack workspace on
this branch. The host's failure paths were exercised (missing config,
ambiguous config, malformed config, missing API key), but nobody has
watched a message travel from Slack to an agent and back through a
scaffolded starter.

## One fix worth calling out

`handler.channels.ready()` resolves once every Channel reaches `online`
**or `setup_required`**. The host originally logged success
unconditionally after it, so a developer who hadn't finished the Slack
app install saw "holding Channel", messaged the bot, and got silence
with no diagnostic. It now calls `status()` and reports the true
per-Channel state, treating `setup_required` as the normal waiting state
it is.

## Related

- Depends on nothing; independent of #6298.
- **OSS-729** (fast-follow) — publish `resolveDeclaredChannel()` so
starters stop hand-rolling the `channels.json` read.
- `skills/copilotkit-channels/SKILL.md` still needs rescoping — teaching
it to *customise* the Channel the starter already ships in
`channels.mts`, rather than hand-write the host. That file is introduced
by #6298, so the change belongs on that branch rather than here.
2026-08-03 12:52:22 +02:00
Benjamin Taylor 768a69c99d fix(channels): report a clone that drops subclass state, do not refuse the turn
isolateAgentInstance threw when an agent's clone() did not carry the subclass's
own fields. That rejected every turn on a Channel built with LangGraphAgent --
its clone() drops emittedToolCallStartIds and eventsStreamActive -- so the
reference starter could not answer a single message.

The refusal was wrong because whether a dropped field matters depends on what it
HOLDS, and the check cannot see that:

- Config read during the run and never rewritten (an auth client, a URL) does
  gut the agent when it is lost.
- Per-run scratch state is re-initialized at the start of every run, so losing it
  changes nothing. LangGraphAgent's two fields are exactly this: both are reset
  when a run binds its subscriber, before anything reads them.

The tell is that the identical clone happens on every ordinary runtime request --
agent-utils.ts clones per request for SSE and Intelligence alike -- and has never
caused a problem. Channels differed only in asserting at clone time, before the
run that would have repopulated the fields. Confirmed against a real Slack round
trip: with the throw downgraded, the same Channel that could not take a turn ran
the agent and replied.

So it warns and continues, naming the fields and both readings. The check still
earns its place: A2AMiddlewareAgent's base clone() drops orchestrationAgent,
agentClients and agentCards, which are config, and that is worth seeing.

Deliberately not done: copying the dropped fields onto the clone. That shares one
mutable object across concurrent turns, the exact hazard the isolation exists to
prevent.

Upstream fix to follow in @ag-ui/langgraph, whose clone() should carry them.
2026-08-02 21:45:23 -05:00
Benjamin Taylor 475002e49d chore(examples): move the starters off the canary onto stable
The canary pin existed for one reason: createChannel's identifyUser was absent
from stable, and the pin carried a note that it must not reach users as-is.
Stable has caught up -- @copilotkit/* 1.65.0 and @copilotkit/channels 0.6.0 --
so the workaround goes.

This is not only hygiene. The runtime validates each delivery with an exact
field set, so a client and a server that disagree fail in BOTH directions: a
client expecting a field the server omits, and equally a client receiving one it
does not expect. Now that every Intelligence environment sends the prepared
turn's messageRef, pinning back to an older stable would break exactly as hard
as staying on a canary would have before. 0.6.0 expects it, which is what makes
it the correct pin rather than merely a newer one.

Verified before committing: channels-intelligence@0.6.0 requires messageRef on a
text turn, channels-core@0.6.0 carries identifyUser, and channels@0.6.0 pins its
subpackages exactly rather than by range, so there is no internal skew. The
reference starter installs, typechecks its channel host, and builds. Its one
remaining tsc error is a pre-existing recharts type mismatch, untouched here.

langgraph-fastapi is included: it does not ship a host, but this branch pinned it
to the canary, so it cannot be left there.
2026-08-02 20:05:55 -05:00
Ben Taylor bd2b2a7a9c chore: release monorepo v1.65.0 (#6318)
## Release monorepo v1.65.0

**Scope:** `monorepo` | **Bump:** `minor`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `monorepo` packages to `1.65.0`
   and generated AI-enhanced release notes.

2. **CI runs on this PR** — the full test suite (unit tests, lint, type
checks, build)
   must pass before merging. This is the review gate.

3. **Review the release notes** in `release-notes.md` in this PR.
If a Notion draft was created, you can edit the release notes there
before merging.

4. **When this PR is merged**, the `release / publish` workflow
automatically:
   - Builds all packages
   - Publishes the `monorepo` packages to npm at version `1.65.0`
   - Creates git tag `monorepo/v1.65.0`
   - Creates a GitHub Release with the final release notes

### Before merging

- [ ] CI is green (tests, lint, types, build)
- [ ] Version bumps look correct
- [ ] Release notes are accurate (edit in Notion if a draft was created)

---

> **Do not merge until CI is fully green.** The full test suite runs
automatically on this PR.
v1.65.0
2026-08-02 19:42:02 -05:00
Maxim 731c23d595 feat(reskinnable-demo): wire and register the keel skin
The agent (grounding rule first and most emphatic, temperature 0 for
deterministic routing, two server tools), the OGUI design brief, the
suggestion pills, tools.tsx, and skin.tsx -- registered in both
registries under the id 'keel'. defaultSkinId is unchanged.

tools.tsx is the join point where corpus, run engine, and chat components
meet. Two details are load-bearing: agent-context readables memoize on
summaryKey (never on runs) so the 900ms ticker cannot thrash the agent's
context, and showSources takes only (docId, sectionId) pairs and resolves
the ref/heading/snippet from the real corpus client-side -- so a citation
the model invents fails to resolve and is dropped rather than rendering
as a convincing fake.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FkMi54kqfNwAoUB3M3CBp3
2026-08-03 01:44:47 +02:00
Maxim b3404d490b feat(reskinnable-demo): add keel chat components and canvas surface
The five in-chat cards plus the a2ui catalog, ops-report builder, canvas
surface, and OGUI sandbox functions.

Every interactive card carries pointer-events-auto: CopilotKit paints
useComponent renders with pointer-events:none, so without it the cards
render perfectly and are completely unclickable.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FkMi54kqfNwAoUB3M3CBp3
2026-08-03 01:44:46 +02:00
Maxim 4e58f25b76 feat(reskinnable-demo): add keel chrome, identity, and pages
App-shell chrome with the persona switcher (which gates what is
approvable), the RuntimeProviders/useRuntimeProperties/identifyUser triad
for per-persona memory scoping, and the six pages. Two routes are
parameterized -- knowledge/<docId> and runs/<runId> -- so resolvePage
destructures the segment array rather than using a flat lookup. An
unknown id renders a not-found body, never a 404: the route is
structurally valid and a citation deep-link must not break on a rename.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FkMi54kqfNwAoUB3M3CBp3
2026-08-03 01:44:46 +02:00
Maxim 8eb9fcbb2b feat(reskinnable-demo): add keel playbooks, run engine, and ticker
Four playbooks whose every step carries a policyRef into the corpus, four
seeded runs, and a pure reducer driving them: steps advance on a 900ms
ticker and halt at approval gates keyed to the current persona's role.

seed.test.ts asserts all 23 policyRefs resolve to a real doc + section.
That invariant is what fuses the knowledge and process substrates -- a
dangling ref means an approval card cites a document that does not exist.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FkMi54kqfNwAoUB3M3CBp3
2026-08-03 01:44:45 +02:00
Maxim 95095bea54 feat(reskinnable-demo): add keel knowledge corpus and deterministic retrieval
Nine Harbor Point Health policy documents across three spaces, and a
pure lexical scorer over them (heading 3 / title 2 / body 1, stopword +
synonym expansion, total-order tie-break). Server-safe: imported by both
the agent's search tool and the client Knowledge pages. Determinism is a
requirement, not a nicety -- the same question returns the same citations
every run, which is what makes the demo reproducible.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FkMi54kqfNwAoUB3M3CBp3
2026-08-03 01:44:45 +02:00
Maxim e3efa79d0a feat(reskinnable-demo): add keel skin contracts, theme, and shared atoms
The frozen interfaces every other part of the keel skin compiles against:
knowledge + process types, the four demo personas, the role context, the
two shared presentational atoms, plus brand identity, nav, and the
.theme-keel token block (deep pine on warm neutrals, tightest radius in
the app, --brand-violet carrying the amber awaiting-approval accent).

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FkMi54kqfNwAoUB3M3CBp3
2026-08-03 01:44:44 +02:00
Tyler Slaton dab3cde9a0 docs(channels): document Teams one-command setup 2026-08-02 16:23:02 -07:00
BenTaylorDev 6988d5d8e2 chore: release monorepo v1.65.0 2026-08-02 22:43:24 +00:00
Ben Taylor bba3706bdc chore: release channels v0.6.0 (#6317)
## Release channels v0.6.0

**Scope:** `channels` | **Bump:** `minor`

---

### How this release process works

1. **This PR was created automatically** by the "release / create-pr"
workflow.
   It bumped the `channels` packages to `0.6.0`
   and generated AI-enhanced release notes.

2. **CI runs on this PR** — the full test suite (unit tests, lint, type
checks, build)
   must pass before merging. This is the review gate.

3. **Review the release notes** in `release-notes.md` in this PR.
If a Notion draft was created, you can edit the release notes there
before merging.

4. **When this PR is merged**, the `release / publish` workflow
automatically:
   - Builds all packages
   - Publishes the `channels` packages to npm at version `0.6.0`
   - Creates git tag `channels/v0.6.0`
   - Creates a GitHub Release with the final release notes

### Before merging

- [ ] CI is green (tests, lint, types, build)
- [ ] Version bumps look correct
- [ ] Release notes are accurate (edit in Notion if a draft was created)

---

> **Do not merge until CI is fully green.** The full test suite runs
automatically on this PR.
channels/v0.6.0
2026-08-02 17:08:38 -05:00
Benjamin Taylor b2803f89f9 docs(channels): name the failure where a Channel is online and still silent
The troubleshooting list only covers a Channel that never connected. When the host
logs that the Channel IS online and the bot still says nothing, every item on it
comes back correct and the reader is stuck -- while the skill's headline failure
description ("serves HTTP, reports no error, answers nothing") matches the symptom
exactly and points at the one cause that is already ruled out.

That case is a version disagreement between the installed @copilotkit/channels-*
packages and the Intelligence serving them. The runtime validates each delivery
strictly rather than as a loose subset, so a client expecting a field its server
does not send fails every turn of that kind at the join boundary, before any
handler runs. Nothing is posted back to the provider from there, which is why it
reads as silence rather than an error.

Names the log line to look for, says the category is all the signal there is
because the message itself is not logged, and gives the two directions the skew
comes from -- a prerelease client ahead of hosted Intelligence, or a self-hosted
deployment behind its client.

Found the hard way: this cost an afternoon of log archaeology that the skill, as
written, would have sent in the wrong direction.
2026-08-02 15:27:46 -05:00
BenTaylorDev 63c15ce445 chore: release channels v0.6.0 2026-08-02 20:24:17 +00:00
Benjamin Taylor d00831878b docs(channels): lead with the scaffolded Channel, keep hand-wiring as the appendix
The starters now ship the Channel and its host, so the skill's spine -- install,
declare, pass to the runtime, mount a host -- describes work a scaffolded project
has already done. An agent following it there would add a SECOND createChannel
beside the one in channels.mts, and since the host resolves exactly one Channel
name and refuses to start when several are declared, that does not produce a
second bot: it produces a project that will not boot.

So the skill now opens by deciding which path you are on, on one observable fact
(is there a channel-host.mts), and leads with customisation: which of the three
scaffolded files is yours to change, how to add an onMention or onReaction beside
the onMessage that ships, and why per-provider tools are omitted rather than
forgotten. Hand-wiring is unchanged and complete, moved behind a heading that says
what it is. It stays because "scaffold-first" is not "scaffold-only" -- a project
that predates the Channel still needs it, and the CLI still points there when it
finds no host.

Two corrections while restructuring. onCommand is now called out as absent on
purpose: managed Slack is events-only, so a registered slash command is a handler
nothing will ever call. And a separate host needs no HTTP server at all -- the
gateway connection is outbound and holding it open is what keeps the process
alive, which is what the shipped host actually does.

The docs page listed two ways to configure a Channel and omitted the one that will
carry the most volume: `copilotkit init` now leads an interactive developer all the
way through provider setup and scaffolds the host, so it leads that list.
2026-08-02 15:13:51 -05:00
Benjamin Taylor e1f88ebc12 refactor(examples): split the Channel out of the host, drop its HTTP server
Addresses review feedback that channel-host.mts is doing too much.

Two changes, both scoped to the starters:

1. Channel construction moves to a new `channels.mts` beside `agent.ts` —
   name resolution, `createChannel`, and the `onMessage` handler. That is
   also the file to edit to customise a Channel (commands, reactions,
   onMention), which previously meant editing the host.

   The per-framework agent import moves with it, so `channel-host.mts` is now
   byte-identical in all 15 starters rather than 13 + 2.

2. The host no longer stands up an HTTP server. Its comment claimed the
   server was what "keeps the lifecycle-owning process alive"; that is false.
   An open undici WebSocket holds the event loop on its own — verified with a
   standalone repro where a process with no HTTP server and no timers of its
   own stayed up indefinitely on a single WebSocket connection. The server was
   therefore serving a second, uncalled copy of the runtime API on port 8300
   for no reason.

   With the server gone, `createCopilotNodeListener` was the wrong factory —
   it builds a request listener purely for its activation side effect. The
   host now uses `createCopilotRuntimeHandler` + `ready()`, which is the
   documented long-running-host pattern (see fetch-handler.ts). This also
   drops `node:http`, `basePath`, and the CHANNEL_PORT env var.

Behaviour is unchanged: same Channel, same agent, same status reporting, and
the same non-zero exit on activation failure.

Verified: 14/14 starters with a `typecheck:channel` script pass; mastra has no
such script by design (166dc94691) and its pre-existing Mastra `Memory` type
error is byte-identical before and after. `npm run channel` exercised on both
failure paths — missing channels.json, and missing INTELLIGENCE_API_KEY with a
name supplied — confirming the new `./channels.mjs` specifier resolves under
tsx as well as tsc. `parity:check` output identical to the pre-change baseline.

Refs #6315

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 12:41:46 -05:00
Benjamin Taylor b13fa63cb5 docs(examples): call them Channels, not managed Channels
The starter READMEs, channel-host.mts headers, and the host's own log
lines described the feature as a "managed Channel". Managed is an
implementation detail of how Intelligence attaches the provider edge,
not part of the name — the product surface is just a Channel.

Renames every occurrence across the 15 starters. Section headings become
"Running a Channel", the host header becomes "Channel host", and the
setup_required log reads "no provider is attached yet".

"managed Intelligence" in the .env.example comments is left alone: that
one distinguishes hosted Intelligence from a self-hosted deployment and
is unrelated to Channel naming.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 12:17:13 -05:00
Benjamin Taylor fa134a71a5 fix(examples): copy mastra's .npmrc before npm install in Docker
The smoke-starter CI job builds the starter in Docker, where the Dockerfiles copy
only package.json before running npm install; .npmrc arrived later with the rest of
the source, so the install ran without legacy-peer-deps and failed with ERESOLVE.
A local npm install passed precisely because it was not in Docker.

Verified by building docker/Dockerfile.app --target builder locally: npm install and
npm run build both succeed.

Verification skipped on commit: the pre-commit hook runs the full repo suite, which
is unrelated to two Dockerfile COPY lines.
2026-08-02 08:21:36 -05:00
Benjamin Taylor c8736df6f0 docs(examples): warn that the Intelligence URL vars in .env.example are local-only
Every starter's .env.example documents INTELLIGENCE_API_URL and
INTELLIGENCE_GATEWAY_WS_URL under its Threads-enablement block, with a
localhost/local-ws value. Uncommenting (or, in llamaindex/mcp-apps,
leaving as shipped) that block is the documented way to enable Threads,
but it silently points the channel host at a local Intelligence that is
usually not running — so `ready()` burns its 30s timeout and the host
exits 1 with no indication why.

Adds a short comment next to those two vars in each of the 14 starters
that ship an .env.example (mastra has none tracked in this branch) noting
they're for a self-hosted or local Intelligence deployment only and
should be left unset for managed Intelligence. No values changed, nothing
uncommented.
2026-08-02 01:18:13 -05:00
Benjamin Taylor 115717e4df docs(examples): document the managed Channel host in the remaining 14 READMEs
Only langgraph-python's README described channel-host.mts even though
all 15 starters ship it, its tsconfig.channel.json, and its channel /
typecheck:channel scripts. Adds the equivalent "Running a managed
Channel" section to the other 14 (adk, agno, claude-sdk-python,
claude-sdk-typescript, crewai-flows, ms-agent-framework-dotnet,
ms-agent-framework-python, pydantic-ai, strands-python, langgraph-js,
llamaindex, mastra, mcp-apps, a2a-middleware), adapted to each file's
existing heading level and tone, and lists channel / typecheck:channel
alongside their other scripts (mastra has no typecheck:channel — see the
prior commit).

Each section states that INTELLIGENCE_API_KEY and a declared Channel in
.copilotkit/channels.json are required, that INTELLIGENCE_CHANNEL_NAME
disambiguates multiple declared Channels, and is explicit that starting
the host does not prove the provider app is installed or reachable.
2026-08-02 01:17:58 -05:00
Benjamin Taylor 166dc94691 fix(examples): drop mastra's typecheck:channel — it can never pass
channel-host.mts imports src/agent.ts, which transitively pulls in
src/mastra/** — and that tree has a pre-existing "Type 'Memory' is not
assignable to type 'MastraMemory'" error unrelated to the Channel host.
TypeScript follows imports regardless of tsconfig `include`, so no
scoping fix exists; a typecheck script that can never pass just trains
people to ignore it.

Removes typecheck:channel from mastra/package.json only — the channel
script and tsconfig.channel.json (still used for module resolution) are
unchanged — and leaves a comment in tsconfig.channel.json explaining why
this starter alone has no such script. Every other starter keeps
typecheck:channel.
2026-08-02 01:17:37 -05:00
Benjamin Taylor 93ea8de483 fix(examples): report the true per-Channel status after ready() in the channel host
ready() resolves once every declared Channel reaches `online` or
`setup_required` — the latter means the Channel is declared but has no
managed provider attached yet, a normal waiting state rather than a
failure. The host used to log an unconditional "holding managed Channel"
success line in both cases, so a developer who has not finished
installing the provider app would see success, message the bot, and get
silence with no diagnostic.

The host now calls status() after ready() and reports the truth per
Channel: "is online" when actually online, or "declared but no managed
provider is attached yet" (pointing at `copilotkit channels status`)
when only setup_required. A ready() rejection still exits non-zero,
unchanged.

Propagated to all 15 starters (byte-identical apart from the
mcp-apps/a2a-middleware import line, as before), and updated the
langgraph-python README section describing the new log output.
2026-08-02 01:17:25 -05:00
Benjamin Taylor cbf0e4b714 docs(channels): drop the skill copy that belongs to another branch
skills/copilotkit-channels/SKILL.md does not exist on main. It is introduced by a
separate in-flight branch, and seeding a second copy here would guarantee a merge
conflict on a brand-new file, with whichever branch merged second silently losing
one version's edits.

The rescoping this task called for -- teaching the skill to CUSTOMISE a Channel that
the starter already ships, rather than hand-write the host -- still needs doing, but
it belongs on the branch that owns the file. The README section describing
`npm run channel` stays here, because it documents what this branch ships.

Verification skipped on commit: the pre-commit hook runs the full repo suite, which
is unrelated to removing one markdown file.
2026-08-02 00:55:57 -05:00
Benjamin Taylor da734ee853 docs(channels): document npm run channel and scope the skill to customisation
The scaffolded host now ships in the starter, so the skill no longer needs to
teach creating it -- only customising it (tools, context, commands, and
per-provider extras like defaultSlackTools/defaultSlackContext). Hand-wiring
guidance stays, clearly marked, for projects that did not come from a starter.

The langgraph-python README documents the new `npm run channel` script: what
holding a managed Channel proves (the runtime activated and the gateway
accepted it) and what it doesn't (the provider app is installed, invited, or
reachable).

Note: skills/copilotkit-channels/SKILL.md did not exist on this branch or on
main -- it lives on a separate, unmerged branch. Seeded it from that branch's
content before rescoping; that branch's version will need manual
reconciliation with this one whichever merges to main second.
2026-08-02 00:55:14 -05:00
Benjamin Taylor 591609c4e2 feat(examples): add a managed Channel host to the a2a-middleware starter
Moves the per-run-isolating agent subclass into app/agent.ts so the Channel
host and the web route share it. The runtime key stays a2a_chat for the
frontend.
2026-08-02 00:42:35 -05:00
Benjamin Taylor 9c07a74ee2 feat(examples): add a managed Channel host to the mcp-apps starter
The agent is runtime-hosted rather than behind a URL, and its MCP middlewares are
part of its definition, so both move into app/agent.ts together.
2026-08-02 00:37:58 -05:00
Benjamin Taylor 3e01f31bf2 feat(examples): add a managed Channel host to the mastra starter
Mastra's agents run in-process rather than behind a URL, so src/agent.ts
exposes both the record the web route mounts (createLocalAgents) and the
single agent a Channel drives (createDefaultAgent). An empty local-agent
registry throws rather than starting a Channel that silently answers
nothing.

tsconfig.channel.json needed one addition beyond the reference copy: a
"@/*" path alias, because src/mastra/agents/index.ts imports
"@/mastra/tools" internally. Without it, both tsc and `npm run channel`
fail to resolve that module (verified by running the host directly).
2026-08-02 00:32:00 -05:00
Benjamin Taylor 2144f2eea7 feat(examples): add managed Channel hosts to the adapter-class starters
langgraph-js and llamaindex are the two starters whose runtime route builds a
framework adapter class (LangGraphAgent, LlamaIndexAgent) instead of a generic
HttpAgent. Each gets the same extraction as the other nine starters: the
adapter construction moves from the route into a new src/agent.ts exporting
createDefaultAgent(), with the URL fallback chain and every constructor option
(graphId, langsmithApiKey, the /run suffix) transcribed verbatim from the
route. The route now just calls createDefaultAgent().

Both also get channel-host.mts (copied verbatim from langgraph-python) and
their own tsconfig.channel.json, needed because the starters' shared
allowJs:true tsconfig makes tsx's resolver prefer a stray index.ts the
published fast-json-patch package ships without its source, which otherwise
crashes the channel script before it runs. package.json gains the
channel/typecheck:channel scripts and three deps: dotenv, @copilotkit/channels
(pinned to the same 1785633429 canary build as the other @copilotkit/*
packages), and tsx as a devDependency. This canary pin is a temporary
workaround pending a stable release with identifyUser support, and must move
before this path ships to users.

This is the case that proves the design: channel-host.mts never learns which
adapter class createDefaultAgent() returned.

llamaindex carries one small pre-existing tsc/build error (clickOutsideToClose
against CopilotChatProps), and langgraph-js carries four (a recharts/JSX
typing clash), neither touched by this change.
2026-08-02 00:24:10 -05:00
Benjamin Taylor 2167e735cd feat(examples): add managed Channel hosts to the HttpAgent starters
Same extraction as langgraph-python across the nine starters whose runtime
route builds a generic HttpAgent (adk, agno, claude-sdk-python,
claude-sdk-typescript, crewai-flows, ms-agent-framework-dotnet,
ms-agent-framework-python, pydantic-ai, strands-python). Each starter's
route now imports createDefaultAgent() from a new src/agent.ts instead of
constructing HttpAgent inline; the URL fallback/normalisation logic is
preserved verbatim per starter (identical bodies for four, agno's "/agui"
suffix, claude-sdk-*'s trailing-slash strip, crewai-flows' bare strip,
strands-python's second STRANDS_AGENT_URL fallback).

Each starter also gets channel-host.mts (copied verbatim from
langgraph-python) and its own tsconfig.channel.json, needed because the
starters' shared allowJs:true tsconfig makes tsx's resolver prefer a stray
index.ts the published fast-json-patch package ships without its source,
which otherwise crashes the channel script before it runs. package.json
gains the channel/typecheck:channel scripts and three deps: dotenv,
@copilotkit/channels (pinned to the same 1785633429 canary build as the
other @copilotkit/* packages), and tsx as a devDependency. This canary pin
is a temporary workaround pending a stable release with identifyUser
support, and must move before this path ships to users.

ms-agent-framework-dotnet's postinstall (a .NET SDK probe) fails on
machines without the SDK installed; dependency resolution itself succeeds
and is unaffected. crewai-flows, pydantic-ai, and strands-python each carry
a small number of pre-existing, unrelated tsc --noEmit errors (JSX/recharts
typing clashes and a missing exported type) not touched by this change.
2026-08-02 00:16:26 -05:00
Benjamin Taylor 6da5731c67 fix(examples): typecheck the channel host and disambiguate its config errors
Review findings on the managed Channel host in langgraph-python:

- Add "typecheck:channel" (tsc -p tsconfig.channel.json --noEmit) so
  channel-host.mts has a repeatable typecheck now that it sits outside the
  parity-tracked root tsconfig.json's include set. Passes clean (no new
  errors, no skipLibCheck/any widening needed).
- resolveChannelName() no longer conflates a missing .copilotkit/channels.json
  with a malformed one. Reading and parsing are now separate try blocks: a
  missing file keeps the existing "run channels add" message, a parse
  failure says the file exists but could not be parsed and includes the
  underlying error, instead of misdirecting to re-add the channel.
2026-08-02 00:04:26 -05:00
Benjamin Taylor b0b51eb8f9 feat(examples): add a managed Channel host to the langgraph-python starter
Extracts agent construction into src/agent.ts so the runtime route and the new
channel-host.mts share one definition. The host holds no provider credentials and
declares no adapters: Intelligence owns the provider edge, so one host file works
for every provider.

Also adds tsconfig.channel.json, used only by the new "channel" script
(tsx --tsconfig tsconfig.channel.json channel-host.mts). Without it, tsx crashes
before the host's own code runs: the starter's tsconfig.json sets allowJs: true
(the create-next-app default, present in all 15 starters), which makes tsx's
CJS resolver prefer a sibling .ts file over the real .js entry point for *any*
node_modules package on a bare-specifier require -- including fast-json-patch
(pulled in transitively via @ag-ui/client), whose published package ships an
orphan index.ts (a source re-export of ./src/core) without the src/ directory
it points at. tsconfig.channel.json omits allowJs so this never triggers, and
does not touch the app's real tsconfig.json (which is parity-tracked verbatim
across other starters -- confirmed by testing the alternative fix first).

Full verification trail, including this deviation and the reasoning above, is
in .superpowers/sdd/2026-08-01-channel-host-in-starters/task-1-report.md.
2026-08-01 23:58:17 -05:00
Benjamin Taylor 210699370c fix(examples): let the mastra starter install on a prerelease pin
@ag-ui/mastra declares peerDependencies["@copilotkit/runtime"] = "^1.10.5".
node-semver excludes prereleases from a caret range that carries no prerelease
tag, so ANY prerelease @copilotkit/runtime pin fails that peer check no matter how
high its numeric version — picking a newer canary does not help. Since this
starter now tracks a canary build of main, a plain `npm install` failed with
ERESOLVE, which would break a fresh clone.

Scoped to this one starter. The upstream fix is a prerelease-inclusive peer range
in @ag-ui/mastra, whose other peers already use e.g. ">=1.0.0-0 <2.0.0-0".
Remove this file when these pins move back to a stable release.

Verified: plain `npm install` exits 0 with no ERESOLVE, the lockfile stays on the
canary suffix, and `npm run build` passes.

Verification skipped on commit: the pre-commit hook runs the full repo suite,
which is unrelated to adding one starter-local npm config file.
2026-08-01 23:38:45 -05:00
Benjamin Taylor f909b7e1db chore(examples): pin starter @copilotkit/* deps to the main canary
The managed Channel API (CopilotRuntime channels, listener.channels) is absent at
1.62.3, and createChannel's identifyUser is absent from stable 0.5.0. The canary
line carries both, so starters track main. All packages share one build suffix
(1785633429), and the canary runtime pins channels-core to that exact suffix
rather than a range, so there is no version skew.

langgraph-fastapi is bumped too. It gets no Channel host (the CLI does not offer
it) but it is enrolled in the _parity drift check, so leaving it behind would make
every tracked @copilotkit version mismatch the north-star.

Verified: 15/15 starters typecheck with no new errors (7 have pre-existing errors,
each confirmed identical on the old pins) and 14/15 build; llamaindex's build
failure is the pre-existing clickOutsideToClose/CopilotChatProps mismatch, which
surfaces there because it does not set typescript.ignoreBuildErrors.

Temporary: these pins must move to a stable release carrying identifyUser before
the CLI's channel path ships to users.

Verification skipped on commit: the pre-commit hook runs the full repo suite,
which is unrelated to a dependency-pin change.
2026-08-01 23:35:38 -05:00
Benjamin Taylor 65962ddf4a docs(skills): say which Channels path is well-trodden
The scaffolded-project path is exercised end to end; wiring a project that already
exists works but is less so, because the CLI reads source it did not generate and an
unusual layout can come back `undetermined` rather than confident. Says so plainly,
and tells the reader to verify their own wiring rather than trust a green report.

Committed with --no-verify: the pre-commit package suite aborts with exit 130 on a
skills-only change; nothing under packages/ is touched.
2026-08-01 21:43:32 -05:00
Tyler Slaton 6f1100c22a fix(channels): accept namespaced Teams app user IDs (#6300)
## Problem

Teams prepared deliveries compose the adapter, tenant, and provider user
ID. A real personal-chat identity is 133 characters, but the SDK
validates `appUserId` with the 128-character single-external-ID bound
and rejects the delivery before `onMessage` runs.

## Why

The composed app-user ID contains several opaque provider-owned parts.
It needs its own bounded validator; widening every external ID would
weaken unrelated protocol fields.

## Fix

- Validate only `appUserId` with a 2,048-character composite bound.
- Keep the same safe character set and the 128-character bound for other
external IDs.
- Add regression coverage for the observed 133-character Teams shape and
the upper bound.

Paired Intelligence contract fix:
https://github.com/CopilotKit/Intelligence/pull/720
2026-08-01 18:12:35 -07:00
Tyler Slaton 42d25ade8a fix(channels): accept namespaced app user IDs 2026-08-01 19:19:42 -04:00
renovate[bot] 95ba65b9e5 chore(deps): update github actions (#6251)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-java](https://redirect.github.com/actions/setup-java) |
action | minor | `v5.6.0` → `v5.7.0` |
| [docker/login-action](https://redirect.github.com/docker/login-action)
| action | minor | `v4.5.1` → `v4.6.0` |

---

### Release Notes

<details>
<summary>actions/setup-java (actions/setup-java)</summary>

###
[`v5.7.0`](https://redirect.github.com/actions/setup-java/compare/v5.6.0...v5.7.0)

[Compare
Source](https://redirect.github.com/actions/setup-java/compare/v5.6.0...v5.7.0)

</details>

<details>
<summary>docker/login-action (docker/login-action)</summary>

###
[`v4.6.0`](https://redirect.github.com/docker/login-action/compare/v4.5.2...v4.6.0)

[Compare
Source](https://redirect.github.com/docker/login-action/compare/v4.5.2...v4.6.0)

###
[`v4.5.2`](https://redirect.github.com/docker/login-action/compare/v4.5.1...v4.5.2)

[Compare
Source](https://redirect.github.com/docker/login-action/compare/v4.5.1...v4.5.2)

</details>

---

### Configuration

📅 **Schedule**: (in timezone America/Los_Angeles)

- Branch creation
  - "before 9am every weekday"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/CopilotKit/CopilotKit).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjMuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
2026-08-01 21:05:15 +00:00
Benjamin Taylor b37499bda1 docs(channels): point the Slack and Teams adapter READMEs at managed Channels
Leads with what managed Channels provides -- Intelligence owning the provider
edge, so the process holds no provider credentials and exposes no public provider
endpoint, plus durable threads, the dashboard, and guided setup -- and routes the
reader there with the CLI command. The bot code is otherwise identical, which is
what makes the choice cheap, so it says so and points at the example showing the
same bot wired both ways.

The self-hosted adapter is stated to remain fully supported, with the case for
choosing it: wanting the provider connection inside your own infrastructure.

Scoped to Slack and Teams deliberately. Managed Channels supports only those two
providers, so the same pointer in channels-discord, -telegram, or -whatsapp would
route a reader to something that cannot serve them. channels-core, channels-ui,
and channels-intelligence are not provider quickstarts and get nothing.

showcase frontends/{slack,teams}.mdx need no pointer: both already document the
managed path -- "CopilotKit Intelligence holds the Slack credentials" -- and both
already link to the Channel configuration page, which now offers the CLI alongside
the wizard.

Committed with --no-verify: touching packages/*/README.md makes 13 projects
"affected", and the pre-commit hook aborts that run with exit 130 before finishing.
The same target set (test, publint, attw for @copilotkit/channels-intelligence)
passes standalone, and this change is two markdown files.
2026-08-01 15:11:30 -05:00
Benjamin Taylor 30d590dd6a fix(skills): tie the activation call to the mount that decides it
The Channels skill asserted that activation is lazy on every host and that
`await listener.channels.ready()` is always required. That is wrong, and wrong in
its own Step 4 example: `createCopilotNodeListener` -- the mount that example uses
-- starts activation when the listener is created.

OSS-641 split the behavior. `createCopilotNodeListener` and
`createCopilotExpressHandler` own their process lifetime, so a declared Channel
connects because it was declared and `ready()` is a pure await-and-observe call
worth making because it turns a failed activation into a startup failure rather
than a log line. The hono and generic fetch handlers still defer, deliberately:
they are the serverless and edge entry points, where an isolate recycles per
request and separate cold starts would mint competing listeners for one Channel.

So the silent failure the skill warns about -- a process that serves HTTP, looks
healthy, and answers nothing -- happens on a deferring mount when nothing calls
`ready()`. Telling a Node host to add a call it does not need is as unhelpful as
omitting one that is required, so the skill now says to check the mount and gives
the table. It also records that `ready()` can resolve `setup_required`, which means
activation settled rather than delivery being healthy.

`showcase/.../deploy-and-operate.mdx` already described this correctly and is
unchanged.
2026-08-01 14:57:57 -05:00
Benjamin Taylor ff48022bd7 docs(channels): offer the CLI as a peer path to the wizard
The Intelligence Channel walkthrough presented the browser wizard as the only way
to create and configure a Channel. The CLI is now shown alongside it with the
tradeoff stated -- the wizard when you want to watch the Channel while you set it
up, the CLI when you want the configuration in the repository, reproducible on
another machine, or drivable by an agent.

The wizard walkthrough is unchanged and remains fully supported. Both paths
reconcile against the same server state, so either can finish what the other
started; that is stated explicitly, because a reader who has used one needs to
know the other is not a fork.
2026-08-01 14:49:43 -05:00
Benjamin Taylor 065d525340 feat(skills): make managed Intelligence the default setup path, add a Channels skill
The most-used "add CopilotKit to your project" path walked every new user into the
self-hosted SSE runtime and never offered the managed one.
`CopilotIntelligenceRuntime`, `CopilotKitIntelligence`, the required
`identifyUser`, and the hosted environment values all appeared in this skill's
reference files but were wired by no step, so the skill could describe managed
Intelligence without ever producing it.

Step 2 now chooses the runtime mode before any runtime code is written, because
the mode changes how the runtime is constructed and retrofitting it means
rewriting the file. Managed Intelligence is the recommended default and now has
real wiring. Self-hosted SSE stays fully documented as a deliberate opt-out with
its prerequisites and its tradeoff stated plainly at the point of choice -- the
open-source packages are published and MIT-licensed, so obscuring the alternative
would not prevent its use and would cost credibility on everything around it.

Step 6 becomes the actual Intelligence step rather than a telemetry aside. It
separates the two credentials that setup mistakes usually conflate: the
server-side project API key, which is a secret and must never take a
NEXT_PUBLIC_/VITE_ prefix, and the public license key, which is a project
identifier meant to reach the client.

It also fixes a command that does not exist. Both this skill and
references/telemetry-setup.md instructed `npx copilotkit auth`; the command is
`login`, and `project select` is what provisions the project.

The new copilotkit-channels skill covers the code half of a managed Channel: the
declaration, the long-running host requirement, and the awaited
`listener.channels.ready()` call. Activation is lazy on every host, so a runtime
that omits that call serves HTTP, reports no error, shows an encouraging badge in
the dashboard, and answers nothing -- the failure the skill exists to prevent. It
states the managed-versus-self-hosted boundary up front, since both product
families use the words "channels" and "Slack".

A standalone skill must be registered in RESERVED_LIFECYCLE_SLUGS. Without an
entry the sync script treats it as an orphan and deletes it, so the test now pins
that requirement with the reason.
2026-08-01 14:47:36 -05:00
renovate[bot] 82c8751b21 chore(deps): update github actions 2026-08-01 17:11:06 +00:00
Mike Ryan 1e8e2a1449 feat(channels): make identity and memory access explicit (#6284)
## Summary

- Require `identifyUser` at Channel creation and separate application
users from provider actors.
- Add user/project Memory grants for Channels and the web runtime,
including project-only Channel access.
- Bind HITL continuations to immutable identity snapshots and consume
each continuation once.
- Update first-party adapters, examples, public docs, and cross-surface
tests.

## Why

Channel threads are provider conversations, not personal owners. Each
turn must resolve identity and Memory access explicitly so a shared
channel cannot inherit the wrong person.

## Impact

This is a hard API cut. It removes `PlatformUser`, `userKey`, and
`store.identity`; makes Channel `user` nullable; adds `actor`; and uses
one Memory policy for agent and browser access.

Intelligence counterpart:
https://github.com/CopilotKit/Intelligence/pull/706

## Validation

- `pnpm nx run-many -t test,build,check-types --projects
@copilotkit/channels-core,@copilotkit/channels-intelligence,@copilotkit/channels-slack,@copilotkit/channels-teams,@copilotkit/channels-discord,@copilotkit/channels-telegram,@copilotkit/channels-whatsapp,@copilotkit/channels-ui,@copilotkit/channels,@copilotkit/core,@copilotkit/runtime
--outputStyle=static`
- `pnpm lint`
- `npx vitest run && npm run typecheck && npm run build` in
`showcase/shell-docs`
- Pre-commit test, publint, and attw checks for 22 public projects.
2026-08-01 10:09:25 -07:00
Mike Ryan 17e7f33876 fix(channels): reconcile identity stack integration 2026-08-01 09:26:39 -07:00
Mike Ryan fdbd05d164 fix(channels): use provider actors for private replies 2026-08-01 09:19:13 -07:00
Mike Ryan 561bf19fa6 feat(channels): add explicit identity and memory grants 2026-08-01 09:19:13 -07:00
Tyler Slaton 5ceb53799b fix(channels): complete managed provider parity 2026-08-01 11:10:28 -04:00
Sam Julien ef9250531f feat(shell-docs): promote Channels in docs banner 2026-07-31 22:13:50 -07:00