@dawn-ai/ag-ui
Use this when
Use this package when a web client speaks AG-UI and your Dawn route emits Dawn stream chunks. Most applications should start with AG-UI and Web Clients; use this reference when you are wiring a custom transport or client adapter.
Install and import
pnpm add @dawn-ai/ag-uiimport { fromRunAgentInput, toAguiEvents } from "@dawn-ai/ag-ui"
import { encodeAgUiSse } from "@dawn-ai/ag-ui/sse"In a React client, and only there, import the renderers from the ./react subpath:
import { dawnActivityRenderers } from "@dawn-ai/ag-ui/react"Compatibility and audience
| Surface | Runtime | Purity | Audience | Stability |
|---|---|---|---|---|
@dawn-ai/ag-ui | edge-safe | not-claimed | integration | supported |
@dawn-ai/ag-ui/sse | edge-safe | not-claimed | integration | supported |
@dawn-ai/ag-ui/react | node-only | not-claimed | application | supported |
@dawn-ai/ag-ui/react/styles.css | n/a | n/a | integration | supported |
The adapter translates protocol data; it does not authenticate a caller or make client-supplied thread, run, state, tool, or context data authoritative.
@dawn-ai/ag-ui/react is the client-side entry: it ships ready-made CopilotKit renderers for Dawn's built-in orchestration activities, and React and @copilotkit/react-core are optional peer dependencies, so a server-only consumer that imports only the root or /sse entry installs neither. Its runtime is recorded as node-only because Dawn's edge guard requires an import graph free of unguarded Node globals, and React's own JSX runtime reaches for process.env.NODE_ENV. The entry is meant for browser bundles, where an application bundler substitutes that value as usual; it simply cannot carry Dawn's stricter edge-safe claim.
Public exports
@dawn-ai/ag-ui
| Export | Responsibility |
|---|---|
createCounterIdFactory | Create deterministic IDs for tests and reproducible adapters. |
createDefaultIdFactory | Create unique runtime event IDs. |
DAWN_PLAN_ACTIVITY_TYPE | Identify Dawn plan activity snapshots as dawn.plan. |
DAWN_SUBAGENT_ACTIVITY_TYPE | Identify Dawn subagent activity snapshots as dawn.subagent. |
DawnPlanActivityContent | Describe the complete public plan snapshot. |
DawnSubagentActivityContent | Describe allowlisted subagent progress. |
IdFactory | Define event-ID generation. |
DawnMessage | Describe a normalized inbound message. |
DawnRunInput | Describe normalized Dawn run input. |
fromRunAgentInput | Translate AG-UI run input to Dawn input. |
DawnInterruptEnvelope | Describe a Dawn interrupt payload. |
DawnResumeRequest | Describe one resume decision. |
AguiOutboundEvent | Name events emitted by the outbound mapper. |
ToAguiOptions | Configure outbound event IDs. |
toAguiEvents | Translate a Dawn stream into AG-UI events. |
DawnAgentStreamChunk | Describe accepted Dawn stream chunks. |
RunContext | Supply thread and run IDs for outbound events. |
@dawn-ai/ag-ui/sse
| Export | Responsibility |
|---|---|
encodeAgUiSse | Encode one AG-UI event as an SSE frame. |
@dawn-ai/ag-ui/react
| Export | Responsibility |
|---|---|
dawnActivityRenderers | Register both built-in Dawn activity renderers with CopilotKit's renderActivityMessages. |
dawnPlanActivityRenderer | Register only the plan activity renderer. |
dawnSubagentActivityRenderer | Register only the subagent activity renderer. |
PlanActivityCard | Present one plan snapshot from its content. |
SubagentActivityCard | Present one subagent snapshot from its content. |
ActivityChecklist | Present a todo list from todos, truncated at limit. |
planActivityContentSchema | Validate plan activity content in a custom renderer. |
subagentActivityContentSchema | Validate subagent activity content in a custom renderer. |
SubagentActivityContentOutput | Describe parsed subagent content, which admits an explicit undefined todos. |
DawnActivityClassNames | Name the per-part classes a card appends to its defaults (customization rung 2). |
DawnActivityComponents | Name the leaf slots (TodoRow, ToolRow) a card lets a consumer replace (customization rung 3). |
DawnTodoRowProps | Describe the props passed to a replacement TodoRow. |
DawnToolRowProps | Describe the props passed to a replacement ToolRow. |
cx | Join a package default class with an optional consumer class (customization rung 4: what an ejected card imports in place of its internal ./parts.js path). |
dawnActivityRenderers is the drop-in default; the two individual renderers exist for clients that register only one of them or mix them with their own. The cards are plain React components and need no CopilotKit. SubagentActivityContentOutput is wider than the published DawnSubagentActivityContent in exactly one way: this package compiles with exactOptionalPropertyTypes and zod does not, so a parsed value can carry an explicit todos: undefined. ActivityChecklist, PlanActivityCard, and SubagentActivityCard all accept optional classNames and components props built from these two types; see @dawn-ai/ag-ui/react/styles.css below for rung 1 and the package README for a runnable example of every rung.
@dawn-ai/ag-ui/react/styles.css
This subpath exposes the activity cards' default appearance as a stylesheet asset. It has no TypeScript export inventory, runtime compatibility classification, or purity claim; a bundler resolves it and it is never evaluated as JavaScript. Import it once, wherever your application imports its global CSS:
import "@dawn-ai/ag-ui/react/styles.css"The sheet is optional — the cards render without it — and every rule that styles an element is scoped to the dawn-activity prefix, so it cannot restyle the rest of an application; it additionally declares --dawn-activity-* custom properties on :root. Restyle it by overriding its custom properties in your own CSS: --dawn-activity-surface, --dawn-activity-border, --dawn-activity-text, --dawn-activity-muted, --dawn-activity-running, --dawn-activity-complete, --dawn-activity-failed, --dawn-activity-radius, --dawn-activity-gap, and --dawn-activity-font-size. A dark palette applies under prefers-color-scheme: dark; setting data-dawn-theme="light" or data-dawn-theme="dark" on the root element pins one explicitly (the selectors match only :root, not an arbitrary ancestor).
Key contracts
Activity identifiers and payloads
export declare const DAWN_PLAN_ACTIVITY_TYPE: "dawn.plan"export declare const DAWN_SUBAGENT_ACTIVITY_TYPE: "dawn.subagent"export interface DawnPlanActivityContent {
readonly todos: ReadonlyArray<{
readonly content: string
readonly status: "pending" | "in_progress" | "completed"
}>
}export interface DawnSubagentActivityContent {
readonly name: string
readonly depth: number
readonly status: "running" | "completed" | "failed"
readonly todos?: DawnPlanActivityContent["todos"]
readonly tools: ReadonlyArray<{
readonly name: string
readonly status: "running" | "completed" | "incomplete"
}>
readonly totalToolCount: number
readonly error?: string
}Behavior contract ag-ui.activities.plan-snapshot
A valid plan update becomes a complete replacement snapshot with activity type dawn.plan and the stable message ID dawn:plan:<runId> without breaking an open assistant text message.
Behavior contract ag-ui.activities.subagent-privacy
A subagent snapshot exposes allowlisted progress only: name, depth, status, optional todos, at most five tool name/status summaries, the total tool count, and an error capped at 400 characters. It never includes child prompts, prose, tool inputs, tool outputs, final answers, route IDs, call IDs, or raw runtime IDs.
ToAguiOptions
Supply an IdFactory when emitted IDs must be deterministic. Production integrations normally accept the default factory.
export interface ToAguiOptions {
readonly idFactory?: IdFactory
}Fields: @dawn-ai/ag-ui#.:ToAguiOptions
| Field | Type | Required | Description |
|---|---|---|---|
readonly idFactory | IdFactory | no | Override outbound event-ID generation. |
Inbound and outbound calls
export interface DawnRunInput {
readonly messages: DawnMessage[]
readonly resume?: DawnResumeRequest[]
readonly raw: RunAgentInput
}Fields: @dawn-ai/ag-ui#.:DawnRunInput
| Field | Type | Required | Description |
|---|---|---|---|
readonly messages | DawnMessage[] | yes | Supply normalized messages. |
readonly resume | DawnResumeRequest[] | no | Supply normalized resume decisions. |
readonly raw | RunAgentInput | yes | Preserve the untouched AG-UI input. |
export interface RunContext {
readonly threadId: string
readonly runId: string
}export declare function fromRunAgentInput(input: RunAgentInput): DawnRunInputexport declare function toAguiEvents(
chunks: AsyncIterable<DawnAgentStreamChunk>,
ctx: RunContext,
options?: ToAguiOptions,
): AsyncGenerator<AguiOutboundEvent>export declare function encodeAgUiSse(event: BaseEvent, accept?: string): stringBehavior contract ag-ui.outbound.errors-as-events
toAguiEvents turns an upstream throw into a final RUN_ERROR event and closes an open text frame instead of throwing to the consumer.
Behavior contract ag-ui.inbound.lossless-input
fromRunAgentInput maps supported messages and resume entries into Dawn shapes, omits resume for an empty array, and preserves the untouched AG-UI input under raw for tools, state, and context.
Stream boundaries
Unknown chunk kinds are ignored after closing an open text frame. A stream that ends without done still finishes successfully. Interrupts are accumulated in the RUN_FINISHED outcome; after an interrupt, later non-interrupt chunks are suppressed until the outcome. A malformed interrupt terminates with RUN_ERROR.
fromRunAgentInput() normalizes messages and resume entries. It preserves the original input as raw, leaving tools, state, and context for application-owned validation and policy.
Examples and related guides
import { type DawnAgentStreamChunk, toAguiEvents } from "@dawn-ai/ag-ui"
import { encodeAgUiSse } from "@dawn-ai/ag-ui/sse"
async function* aguiFrames(chunks: AsyncIterable<DawnAgentStreamChunk>) {
for await (const event of toAguiEvents(chunks, { threadId: "thread-1", runId: "run-1" })) {
yield encodeAgUiSse(event)
}
}Continue with AG-UI and Web Clients, Embed the Runtime, and Security Architecture.