The Vue CopilotKitProvider gated all A2UI activation on the runtime
signal (core.a2uiEnabled), so passing an a2ui.catalog to the provider
did nothing: surfaces never rendered locally and the runtime was never
told to inject the render tool. React already supports the
catalog-on-provider path (1.61.2).
Mirror React: a provided catalog now activates A2UI locally and forwards
the a2uiCatalogAvailable property so the runtime injects the render tool
without a runtime-side a2ui config. User-provided properties are
preserved alongside the signal.
Fixes#5774
The chart-chain fixtures looped under multi-step tool execution: langgraph-python
emitted a 2nd tool call (pieChart/barChart/dashboard) with no terminating
toolCallId result fixture, so it fell through to the still-matching userMessage
fixture and re-called query_data. langgraph-js had its toolCallId result fixtures
ordered after the userMessage fixtures (first array match wins -> re-call).
Add the missing terminating result fixtures (langgraph-python) and reorder so all
toolCallId fixtures precede userMessage fixtures (langgraph-js). Verified termination
via the 2-3 step multi-turn repro; mastra fixtures already terminated.
The 6 OpenAI drop-in integration examples enabled for the CLI's keyless
AIMock mock mode shipped fixtures that did not cover the prompts each
starter's own UI suggests, so a keyless first-run user clicking the demo
suggestions mostly hit the generic catch-all. Re-key/extend each
example's fixtures/default.json (substring, most-specific-first,
catch-all last) so the surfaced suggestions return scripted replies.
ENT-1003.
Three snapshot tests (lines 751/771/789) call test() while the file uses
explicit vitest named imports. They pass at runtime via vitest's global
but fail tsc check-types (TS2593). Add test to the import.
Memory, NewMemory, MemoryChanges, MemoryKind, and MemoryScope are the
memory types surfaced by the useMemories / injectMemories hook result
shapes, so export them unprefixed as supported public API instead of
behind the ɵ "internal" marker. Internal memory plumbing (MemoryStore,
the selectMemories* selectors, state/context/event types,
createMemoryStore) keeps the ɵ prefix.
Updates the react-core and angular hook signatures, the web-inspector
Memories tab, and the affected tests to the unprefixed names.
## ⚠️ Draft — stacked on #5563
This builds on #5563 (the `oracle-agent-memory` showcase). Since the
showcase isn't on `main` yet, **this PR's diff currently includes
#5563's files** — once #5563 merges, it auto-reduces to just the
checkpointer change below. Keeping it as a **draft** until then; opening
early to stage the work.
## What this adds
An **optional, flag-gated** durable LangGraph checkpointer for the
showcase agent, using Oracle's
[`langgraph-oracledb`](https://github.com/oracle/langchain-oracle/tree/main/libs/langgraph-oracledb)
`AsyncOracleSaver` — so per-thread LangGraph graph state persists in
**Oracle**, **complementing** (not replacing) `oracleagentmemory`. That
rounds out the "whole stack on Oracle" story: durable *memory* **and**
durable *graph checkpoints*.
**Default-safe:** gated behind `LANGGRAPH_CHECKPOINTER` (default
`memory` → behavior unchanged; `oracle` is opt-in), with graceful
fallback to in-memory on any Oracle error — so CI and the default run
path never touch a DB.
## The actual delta (just these agent files)
- `agent/concierge/checkpointer.py` *(new)* — flag-gated resolver:
builds a dedicated async Oracle pool + `AsyncOracleSaver`, runs `await
setup()`, degrades to `MemorySaver` on failure.
- `agent/concierge/server.py` — an import-time monkeypatch injects the
resolved checkpointer past `ag_ui_agentspec`'s hardcoded `MemorySaver`;
the FastAPI lifespan inits/closes it.
- `agent/pyproject.toml` — adds `langgraph-oracledb>=1.0.1`, bumps
`oracledb>=2.2.0`, adds dev `pytest`/`pytest-asyncio`.
- `agent/.env.example` — documents `LANGGRAPH_CHECKPOINTER`.
- `agent/tests/test_oracle_checkpointer.py` *(new)* — a durability
round-trip test (skipped unless `LANGGRAPH_CHECKPOINTER=oracle`).
Mirrors
[jerelvelarde/oracle-cookbook#4](https://github.com/jerelvelarde/oracle-cookbook/pull/4),
where it's reviewed + verified — the durability round-trip passes
against a live Oracle DB, and 5/5 e2e pass with the flag off (no
regression on the default path).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The opts parameter (not just its fields) must be optional so consumers can
write createBot({ adapters: [intelligenceAdapter()] }). Add a zero-arg
regression test.
Make source/egress optional on intelligenceAdapter(); when omitted it builds
default HTTP transports that talk to a running Intelligence app-api
(heartbeat/claim/lease-fenced ack-fail + idempotent egress), resolved from env
(COPILOTKIT_INTELLIGENCE_URL/COPILOTKIT_API_KEY) and the bot's name. Consumers
now write createBot({ adapters: [intelligenceAdapter()] }).
- http-transports.ts: HttpDeliverySource, HttpEgressSink, resolveTransportConfig
- ir-to-text.ts: flatten BotNode[] -> plain text for the egress first slice
- bot core: PlatformAdapter.start(sink, ctx?) carries botName from createBot
(additive, backwards-compatible); export transports as undocumented fallbacks
- tests: bot-intelligence 36 green, bot 150 green
Relates to OSS-360, OSS-361, OSS-363.
Runnable companion to the #5521 cookbook recipe — a portable Oracle
Agent Spec agent on LangGraph over AG-UI, long-term memory on Oracle AI
Database, and a CopilotKit V2 frontend (generative UI + HITL booking).
Lives beside `daytona-runcode`.
- `agent/` — Python (uv) Agent Spec agent + FastAPI AG-UI server
- `frontend/` — Next.js CopilotKit V2 chat (flight cards, recall chip,
HITL booking)
- `db/` — Oracle AI Database (Free image) + cookbook-user init
- `docker-compose.yml` (local Oracle) + per-service `railway.json`
✅ Live cross-session recall verified working on the hosted demo (a
preference taught in one thread is recalled in a fresh thread).
### Pre-merge follow-ups — resolved ✅
- [x] **Workspace deps** — the frontend builds standalone (`npm ci` +
`next build` ✓ inside the monorepo). It ships its own
`package-lock.json` and is intentionally excluded from the pnpm
workspace (the `daytona-runcode` / `shell-dashboard` convention), so the
published prerelease `@copilotkit/*` resolve and no
`workspace:*`/`catalog:` is needed.
- [x] **Promote SSOT** — the live demo is hosted independently (not part
of CopilotKit's Railway promote fleet), so no
`showcase/scripts/railway-envs.ts` entry is required.
- [x] **`db/build-and-push.sh`** — default image namespace genericized
to an `OWNER` placeholder (still `IMAGE`-overridable).
- [x] **Oracle license** — `db/Dockerfile` and `build-and-push.sh` both
document that the built image must stay in a PRIVATE registry
(re-publishing the Oracle base image violates the license).
> The Vercel preview deploys and `fork-pr-monitor` fail because this is
a cross-fork PR (forks can't access deploy secrets) — not code issues.
`config-allowlist` is fixed.
Docs: CopilotKit#5521.
## Problem
Docs OG image generation was producing unreliable social-preview output
for docs URLs. The route depended on old static OG assets and Inter-era
styling, and the preview did not match the current CopilotKit docs theme
or logo.
## Why
The OG route should render a consistent branded card from page
frontmatter for every docs slug. It also needs local render assets for
request-time reliability: `next/og` does not inherit the app layout
font, and image inputs need to be available as bytes when the route
renders.
## Fix
- Reworked `showcase/shell-docs/src/app/og/[...slug]/route.tsx` to
render a branded 1200x630 card with a tighter layout, CopilotKit theme
colors, Plus Jakarta Sans, and per-page title/description/section
labels.
- Kept `next/font/google` for normal docs pages, and added upstream Plus
Jakarta Sans static TTFs only for the OG renderer. `SOURCE.md` records
the upstream URLs and SHA-256 hashes. The Google Fonts variable TTF was
tested but the bundled `next/og` renderer crashes while parsing its
`fvar` table.
- Added the official CopilotKit full lockup as a real PNG asset. It is
covered by the repo-level `*.png filter=lfs` rule, and the route encodes
the PNG bytes to a data URI only at render time for `ImageResponse`.
- Removed the hardcoded runtime/frontend/agent pills and the yellow
gradient stop from the card.
- Updated the focused OG route test to assert the card dimensions and
bundled Plus Jakarta fonts.
Validation: focused OG test, direct `ImageResponse` render with the
upstream fonts, lint, typecheck, build, and live local OG route checks
passed. Full shell-docs test has unrelated existing failures in public
LFS PNG assets and one docs-render nav expectation.
## What does this PR do?
Follow-up polish on the **OpenBox Governance** cookbook recipe (shipped
in #5686), addressing review feedback from the launch. All changes are
in the single recipe page; no functional/code changes.
| Feedback | Change |
| --- | --- |
| "Make this an actual diagram — hard to read as ASCII" | Replaced the
ASCII flow under **How it works** with a real, color-coded **inline-SVG
architecture diagram** (same self-contained pattern as the Oracle recipe
— no external assets). |
| "Huge, scary warning — condense it" | Cut the wall-of-text
**provisioning** warning down to a few lines while keeping the
essentials (idempotent, which keys it needs, how to verify). |
| "Prompts are unreadable in the chart layout → accordions" | Converted
the **Try it** governance-matrix table into one **accordion per prompt**
(verdict-labeled), so the long prompts are on-demand instead of crammed
into table cells. |
| "Highlight the important stuff — guide the user. Applies to all code."
| Added line highlighting across the bash + TypeScript samples so the
key lines (the runtime wrap, `selfGovernedToolNames`, middleware-first,
the provisioning command, the approval schema) stand out. |
| "Move this to the top top and make it an accordion" | Moved the
**coding-agent prompt** from the bottom to just under the intro,
collapsed in an accordion. |
## Verification
Rendered locally against `shell-docs` (`next dev`) and confirmed
in-browser: the SVG diagram renders, all five accordions expand
correctly, the warning is condensed, and code highlighting shows on both
bash and TS blocks (no leaked `[!code]` markers).
## Related
- Recipe (merged): #5686
- Source-link hotfix (merged): #5767
- Companion showcase (pending): #5685 — once it lands, restore the
direct `tree/main/...` source link in **Get the code**.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Address review feedback on the OpenBox Governance recipe:
- Replace the ASCII flow with a real inline-SVG architecture diagram
- Condense the wall-of-text provisioning warning to a few lines
- Convert the governance-matrix table into per-prompt accordions
- Highlight the key lines across the code samples to guide the reader
- Move the coding-agent prompt to the top in a collapsed accordion
- Revert the v2 useRenderToolCall fallback: when no per-tool or wildcard renderer is
registered, return null instead of auto-painting DefaultToolCallRenderer. Showing the
card is opt-in via useDefaultRenderTool().
- The auto-card default shipped silently in v1.57.2 (commit ba60df5d33, buried in a
showcase per-tool-testids commit, no CHANGELOG entry) and leaked internal tool names +
raw args/result JSON (e.g. generate_a2ui) into every v2 app's chat in production.
- Remove the now-dead defaultToolCallRenderAdapter + __testOnly_ export + unused imports.
- Rewrite the resolver test to assert the 3-state opt-in contract: useDefaultRenderTool()
-> card, useDefaultRenderTool({render}) -> custom, no hook -> nothing.
## What does this PR do?
The **OpenBox Governance** cookbook recipe (#5686) merged to `main`
ahead of its companion showcase (#5685), so the recipe's **"Get the
code"** section linked to:
`https://github.com/CopilotKit/CopilotKit/tree/main/examples/showcases/openbox-governed-copilotkit`
…which **404s** today because that code isn't on `main` yet.
This swaps the broken link for a plain-text **"Full source to follow"**
note (no hyperlink, so nothing 404s) that still describes what the
showcase will contain. The live **upstream reference-repo** link
directly below it is kept.
```diff
- Full source: [`examples/showcases/openbox-governed-copilotkit`](https://github.com/.../tree/main/examples/showcases/openbox-governed-copilotkit) — `agent/` … and `frontend/` …
+ Full source to follow — the runnable showcase (the `agent/` LangGraph service with OpenBox middleware and the `frontend/` CopilotKit V2 chat with the wrapped runtime and approval route) will be published under `examples/showcases/openbox-governed-copilotkit`.
```
**Follow-up:** once the showcase merges to `main`, restore the direct
`tree/main/...` link.
_Note:_ the recipe's run-instructions still `cd` into that path
(expected — the whole "run it yourself" flow assumes the code), so those
steps only work once the showcase lands. Left as-is since they read as
setup instructions, not a clickable link.
## Related PRs and Issues
- Docs recipe (merged): #5686
- Companion showcase (pending): #5685
## Checklist
- [x] I have read the [Contribution
Guide](https://github.com/copilotkit/copilotkit/blob/master/CONTRIBUTING.md)
- [x] If the PR changes or adds functionality, I have updated the
relevant documentation
- [x] "Allow edits by maintainers" is checked
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01Fr5HVeDzDyC4S6DjyhAFWZ
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Fr5HVeDzDyC4S6DjyhAFWZ)_
The OpenBox Governance recipe (#5686) merged ahead of its companion
showcase (#5685), so the "Get the code" link pointed at
github.com/.../tree/main/examples/showcases/openbox-governed-copilotkit,
which 404s while that code is not yet on main.
Replace the broken link with a plain "Full source to follow" note (no
hyperlink, so nothing 404s) that still describes what the showcase will
contain. The live upstream reference-repo link is kept. Swap the link
back in once the showcase merges to main.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fr5HVeDzDyC4S6DjyhAFWZ
## What this adds
A new **"OpenBox Governance"** recipe in the cookbook
(`showcase/shell-docs`), documenting how to add **OpenBox runtime
governance** — guardrails, OPA/Rego policy, redaction, human-in-the-loop
approvals, and halt — to a **CopilotKit + LangGraph** agent, with
decisions rendered as generative UI.
Follows the existing cookbook recipe pattern (Oracle / Arcade /
Daytona):
- `src/content/docs/cookbook/openbox-governed-copilotkit.mdx` — the
recipe (how it works, the stack, prerequisites, run + **provisioning**
steps, the four-verdict governance matrix, the key pieces in code, going
further).
- `meta.json` — registers the recipe in cookbook nav.
- `index.mdx` — overview `<Card>`.
- `src/lib/sidebar-icon.tsx` — `custom/openbox` sidebar icon.
- `public/logos/openbox.png` — brand mark (Git LFS).
The recipe documents the companion showcase **at full parity**: the
provisioning step (`npm run openbox:admin:setup`), the Allow / Constrain
/ Approval / Block / Halt matrix using the demo's real suggestion
prompts, and "key pieces in code" snippets pulled verbatim from the
final showcase source (the LLM-driven governed engine, the
OpenBox-middleware-first agent, and the runtime + approval routes).
## Red → green (TDD)
The cookbook-nav test in `src/lib/__tests__/docs-render.test.ts` is the
red/green hook — it hard-asserts the recipe count, titles, slugs, and
URLs (6 entries incl. `["OpenBox Governance",
"cookbook/openbox-governed-copilotkit"]`).
## Verification
- `docs-render` test suite: **15/15** (nav asserts 6 entries).
- `next build`: ✅ (all cookbook routes, no MDX/link errors).
- The run-steps, four-verdict matrix, and code snippets were verified
against the **final** demo source (companion PR #5685), so the docs and
the runnable code stay in sync.
## Companion demo PR
The runnable showcase this recipe documents:
**https://github.com/CopilotKit/CopilotKit/pull/5685**
> **Ships standalone.** This recipe no longer links the hosted live demo
— that link now lives on the companion demo PR (#5685), so the cookbook
recipe can merge independently of the demo deployment.
## Problem
There is currently no way to intercept an A2UI action before it reaches
the agent when using `createA2UIMessageRenderer`. Every dispatched
action is forwarded to the agent unconditionally:
1. `A2UIMessageRendererOptions` exposed only `{ theme, catalog?,
loadingComponent?, recovery? }` with no `onAction`
(`packages/react-core/src/v2/a2ui/A2UIMessageRenderer.tsx`).
2. `ReactSurfaceHost` mounted `<A2UIProvider onAction={handleAction}>`
and `handleAction` always called `copilotkit.runAgent({ agent })`
unconditionally.
3. Per-component interception fails: `web_core@0.9.0`'s `GenericBinder`
classifies any prop whose Zod schema is a union containing `{ event }`
as `ACTION` and replaces the raw value with a zero-arg dispatching
closure (so `props.action` is a function, `props.action.event` is
undefined).
4. `functionCall` actions are dropped, not a workaround:
`surface-model.js` `dispatchAction` only emits when the payload has
`event`, and `createCatalog` provides no way to register client
functions.
Raised in Discord by a user with a custom catalog + custom Button who
needs a `navigate` event handled client-side. DevRel confirmed
`onAction` was not exposed.
## Change
Add an optional `onAction` interceptor to `createA2UIMessageRenderer`:
```ts
onAction?: (
action: A2UIUserAction,
forward: (action?: A2UIUserAction) => Promise<void>,
) => void | A2UIUserAction | null | Promise<void | A2UIUserAction | null>;
```
- Return `null` to handle the action client-side and stop forwarding
(agent is not run).
- Return an `A2UIUserAction` to forward the (possibly modified) action.
- Return `undefined` / `void` to forward unchanged.
The interceptor is threaded from `createA2UIMessageRenderer` options
through `ReactSurfaceHost` into `handleAction`. The forwarding logic is
extracted into a `runA2UIAction` helper so the three behaviors are
unit-testable. The original finally-block property cleanup is preserved,
and default behavior is byte-identical when `onAction` is not supplied.
New `A2UIActionInterceptor` type is exported from the v2 entrypoint.
## Tests
Added to
`packages/react-core/src/v2/__tests__/A2UIMessageRenderer.test.tsx`:
- `onAction` returning `null` does not run the agent.
- `onAction` returning a modified action forwards the modified payload.
- No `onAction` forwards the original message unchanged.
- `onAction` returning `undefined` forwards unchanged.
## Verify
- `nx test react-core` (1374 passed)
- `nx run-many -t lint build --projects=react-core` (clean)
Ports two fixes from the canonical oracle-cookbook demo into the oracle-agent-memory
showcase agent (server.py was byte-identical to the demo's pre-fix version):
1. Dangling tool-calls: booking conversationally calls the book_flight HITL tool,
which interrupts and emits an assistant tool_call awaiting the UI's Confirm/Cancel.
If the traveler sends another chat message instead, the unanswered tool_call made
the next turn 400 ("tool_call_ids did not have response messages"). _repair_dangling_tool_calls
synthesizes a "not completed" tool result for any dangling call before the history
reaches the graph. (Inverse of the duplicate-tool-block issue the history-replace
already handled — documented in docs/known-issues/agentspec-multiturn-toolcall-correlation.md.)
2. HTML-escaped persistence: the agentspec exporter HTML-escapes streamed deltas
(& < > -> & < >); the SSE generator persisted them raw, so assistant
replies were stored in Oracle Agent Memory as e.g. "fares < $700".
_clean_assistant_text html.unescapes the assembled text before persisting.
Both are reproduced + verified in oracle-cookbook (unit tests + in-browser); the ported
functions are byte-identical to the verified demo code.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up to #5720 (merged). That PR added the **A2UI Error Recovery**
demo (`a2ui-recovery`) across google-adk +
langgraph-{python,fastapi,typescript} + strands{,-typescript}, but the
recovery flow was only exercised by the manual on-demand workflow
(`/test-aimock`). It was NOT covered by the per-PR d5/d6 fleet harness,
so a regression in heal/exhaust would not turn any automatic CI cell
red.
## What this does
Adds a `d5-a2ui-recovery` probe and wires it into the harness so
`a2ui-recovery` runs on every PR like `gen-ui-declarative`:
- **New probe**
`showcase/harness/src/probes/scripts/d5-a2ui-recovery.ts` drives both
pills in one session and asserts the stable end-states:
- **HEAL**: the healed surface paints (>= 2 newly-mounted
`declarative-metric` tiles) and NO "Couldn't generate the UI" card.
- **EXHAUST**: the hard-failure "Couldn't generate the UI" card appears
and NO surface paints.
- Assertions are delta-based against a pre-send baseline so the two
mutually-exclusive negatives stay correct across the shared two-turn
session. The transient "Retrying..." label is not asserted
(timing-flaky).
- **Per-slug prompts**: the recovery prompts are unique per integration
slug (the inner `render_a2ui` calls carry no `x-aimock-context`, so
identical prompts would collide in the shared aimock matcher). The probe
sends each slug's exact `suggestions.ts` message as typed input, which
is byte-identical to the pill dispatch and matches the same fixture.
Heal is sent exactly once (its fixture stages invalid->valid via
`sequenceIndex` 0->1).
- **Wiring**: register `a2ui-recovery` in `d5-registry`, map it in
`d5-feature-mapping` (`"a2ui-recovery": ["a2ui-recovery"]`), add its
representative fixture in `d5-representatives`, and mirror the mapping
in the dashboard `CATALOG_TO_D5_KEY` (kept in lock-step by the drift
test).
## Verification
Local fleet harness, both recovery paths green (heal + exhaust):
- `showcase test langgraph-python:a2ui-recovery --d6 --isolate` -> green
(backend-owned `get_a2ui_tools` path)
- `showcase test strands:a2ui-recovery --d6 --isolate` -> green
(auto-inject middleware path)
Harness unit tests pass (`d5-representatives`, `d5-mapping-drift`,
`starter-mapping-drift`); harness typecheck clean.
## Note (separate, pre-existing)
The on-demand workflow `test_e2e-showcase-on-demand.yml` is currently
broken for all slugs: it installs `@copilotkit/aimock@^1.16.4` then
invokes `aimock --fixtures ...`, but the resolved aimock CLI no longer
accepts `--fixtures` (`Error: Unknown option '--fixtures'`, only
`-c/--config`). aimock dies at the "Start aimock" step before any test
runs. This is unrelated to the recovery demo and is tracked separately.
The Angular CopilotChatInput sends the message on Enter without checking
for IME composition, so confirming a CJK candidate with Enter submits the
half-composed text. The React (react-core v2) and Vue (vue v2) bindings of
the same CopilotChatInput already guard this with isComposing/keyCode 229.