showcase/shell-docs/src/content/reference/angular/production-lifecycle.mdx
@copilotkit/angular uses signals and standalone Angular APIs and is compatible
with zoneless Angular. Most UI components use OnPush; RenderToolCalls
currently uses Angular's default change-detection strategy. This page describes
the environment and ownership rules that apply across the public API.
import {
ApplicationConfig,
provideZonelessChangeDetection,
} from "@angular/core";
import { provideClientHydration } from "@angular/platform-browser";
import { provideCopilotKit } from "@copilotkit/angular";
export const appConfig: ApplicationConfig = {
providers: [
provideClientHydration(),
provideZonelessChangeDetection(),
provideCopilotKit({ runtimeUrl: "/api/copilotkit" }),
],
};
Use a same-origin runtime URL where possible. If server and browser origins differ, resolve an absolute URL independently in each environment while keeping the rendered component tree and initial input values identical.
Call injectable helpers from a field initializer, constructor, or another
Angular injection context. They use the owning DestroyRef:
| API family | Owned lifecycle work | Cleanup behavior |
|---|---|---|
injectAgentStore | Agent subscription and signal projection | Replaces the subscription when agentId changes; unsubscribes on destroy |
connectAgentContext | Reactive context registration | Removes the context when the owning effect is destroyed |
registerFrontendTool, registerRenderToolCall, registerHumanInTheLoop | Runtime renderer or tool registration | Removes registrations matching the same name and optional agent ID on destroy |
registerRenderActivityMessage | Activity renderer registration | Removes the exact renderer object on destroy |
injectInterrupt | Agent subscription, pending interrupt state, handler generation | Disconnects and invalidates pending asynchronous handler work on destroy |
injectThreads | Store selectors, realtime lifecycle, runtime registration | Unsubscribes, stops, and unregisters the store on destroy |
injectMemories | RxJS selectors converted to signals | Angular's signal interop owns the subscriptions |
| Popup, sidebar, chat primitives | Media listeners, observers, timers, focus and body layout | Restore listeners, timers, observers, focus, and docked body layout on destroy |
| MCP Apps and Open Generative UI | Iframe listeners, queues, sandbox instances | Cancel renderer-owned work and destroy renderer-owned sandboxes only |
Application-owned work stays application-owned. For example, abort a fetch
started by a frontend tool when the tool's host is destroyed. Do not retain an
injected controller outside its injector. AgentStore.teardown() exists for
manually constructed advanced stores; injected stores clean themselves up.
defaultToolRendering is explicitly enabled.error signal. Expired interrupts produce InterruptExpiredError. Resume
failures are not retried automatically.A2UIRecoveryOptions and may be
overridden by authoritative server lifecycle content.Browser-only behavior is inert during server rendering and activates after hydration. Follow these rules:
runAgent, media capture, sandbox functions, or MCP iframe
operations during server rendering.window, document, observer, media-query, and media
API access behind isPlatformBrowser or afterNextRender.Keep popup and sidebar initial open, mode, and position inputs stable
through hydration so the server and browser produce matching semantics. Treat
their generated dialog IDs as implementation details rather than persisting or
querying them from application code.
The package does not require Zone.js. Signals, signal inputs/models, Angular
outputs, afterNextRender, and explicit observer callbacks drive updates.
Custom renderer components should also be standalone and OnPush- or
zoneless-compatible. When bridging a third-party callback, update an Angular
signal or use Angular's supported scheduling APIs instead of relying on Zone.js
to notice arbitrary mutation.
headers, properties, tool arguments, activity content, and MCP host context
are browser-visible. Never put model-provider credentials or other secrets in
them. Keep model credentials behind Copilot Runtime. Open Generative UI
functions should expose narrow application capabilities, and MCP Apps runtime
traffic should continue through the selected AG-UI agent rather than a
browser-supplied server URL.