@b4run/ag-ui
Use this whenCopy link to section: Use this when
Use this package when a web client speaks AG-UI and your route emits B4.run stream chunks. Most applications should start with AG-UI and Web Clients. This reference is for wiring a custom transport or client adapter.
Install and importCopy link to section: Install and import
npm install @b4run/ag-uiimport { fromRunAgentInput, toAguiEvents } from "@b4run/ag-ui"
import { encodeAgUiEvent } from "@b4run/ag-ui/sse"A client that runs a B4.run route over HTTP, such as a CopilotKit runtime, imports the agent from the ./client subpath:
import { B4HttpAgent } from "@b4run/ag-ui/client"A client in any framework folds the event stream into turns with the reducers from the ./view subpath:
import { reduceTurns } from "@b4run/ag-ui/view"In a React client, and only there, import the activity kit from the ./react subpath:
import { ApprovalCard, TurnActivity } from "@b4run/ag-ui/react"A React CopilotKit chat connects the kit through the ./react/copilotkit subpath, which is the only entry that imports @copilotkit/react-core:
import { B4Activity, useB4ChatSlots } from "@b4run/ag-ui/react/copilotkit"In an Angular client, import the activity kit from the ./angular subpath, and connect it to a thread's events with ./angular/events or to CopilotKit's <copilot-chat> with ./angular/copilotkit, the only Angular entry that imports @copilotkit/angular:
import { TurnActivityComponent } from "@b4run/ag-ui/angular"
import { MessageActivityComponent, provideB4Turns } from "@b4run/ag-ui/angular/events"
import { provideB4Activity } from "@b4run/ag-ui/angular/copilotkit"Both kits share one stylesheet, @b4run/ag-ui/styles.css.
A CopilotKit runtime route restores a conversation from B4's storage with createB4AgentRunner from the ./copilotkit-runtime subpath. The entry never imports @copilotkit/runtime: the route passes CopilotKit's InMemoryAgentRunner class in, so the runner extends whichever copy the route resolves, wherever the package manager placed it. It depends on rxjs, which installs with the package:
import { InMemoryAgentRunner } from "@copilotkit/runtime/v2"
import { createB4AgentRunner } from "@b4run/ag-ui/copilotkit-runtime"
const runner = createB4AgentRunner(InMemoryAgentRunner, { url, fetch })Compatibility and audienceCopy link to section: Compatibility and audience
| Surface | Runtime | Purity | Audience | Stability |
|---|---|---|---|---|
@b4run/ag-ui | edge-safe | not-claimed | integration | supported |
@b4run/ag-ui/sse | edge-safe | not-claimed | integration | supported |
@b4run/ag-ui/client | edge-safe | not-claimed | integration | supported |
@b4run/ag-ui/view | edge-safe | not-claimed | integration | supported |
@b4run/ag-ui/react | node-only | not-claimed | application | supported |
@b4run/ag-ui/react/copilotkit | browser-only | not-claimed | application | supported |
@b4run/ag-ui/angular | browser-only | not-claimed | application | supported |
@b4run/ag-ui/angular/events | browser-only | not-claimed | application | supported |
@b4run/ag-ui/angular/copilotkit | browser-only | not-claimed | application | supported |
@b4run/ag-ui/styles.css | n/a | n/a | integration | supported |
@ag-ui/client >=1.0.1 <2.0.0 is an optional peer. Runtime validators (RunAgentInputSchema, AgentCapabilitiesSchema, *EventSchema) live at @ag-ui/core/schemas in 1.0; import types from @ag-ui/core.
The adapter only translates protocol data, so it neither authenticates a caller nor makes client-supplied thread, run, state, tool, or context data authoritative.
@b4run/ag-ui/view is the framework-free client entry: pure reducers over AG-UI events with no React dependency. @b4run/ag-ui/react is the React activity kit built on it: TurnActivity, ApprovalCard and the step rows take the view core's props and render one turn in plain language. @b4run/ag-ui/react/copilotkit connects the kit to a stock CopilotKit chat. React and @copilotkit/react-core are optional peer dependencies, so a server that imports only the root or /sse entry installs neither; only ./react/copilotkit imports CopilotKit's React package. @ag-ui/client is the same kind of optional peer, needed only by ./client. The ./react entry is recorded as node-only because B4.run's edge guard requires an import graph free of unguarded Node globals, and React's JSX runtime reads process.env.NODE_ENV. It is meant for browser bundles, where your bundler substitutes that value. The ./react/copilotkit entry is recorded as browser-only: CopilotKit's bundle imports its own CSS, so plain Node cannot load it either. Browser bundles only: import it from a bundled React app, not from Node or an edge runtime.
@b4run/ag-ui/angular is the Angular activity kit, built on the same view core and rendering the same DOM contract as ./react; ./angular/events and ./angular/copilotkit connect it to a chat. @angular/core, @angular/common, @angular/platform-browser (^22.0.0) and @copilotkit/angular (>=0.5.3) are optional peer dependencies, and only ./angular/copilotkit imports CopilotKit's Angular package. The three Angular entries ship in Angular's partial compilation format, which your Angular build's linker finishes, so they are recorded as browser-only: import them from an Angular application built with the Angular CLI (@angular/build), not from Node or an edge runtime, where a plain import fails for want of Angular's JIT compiler.
Public exportsCopy link to section: Public exports
@b4run/ag-uiCopy link to section: @b4run/ag-ui
| Export | Responsibility |
|---|---|
createCounterIdFactory | Create deterministic IDs for tests and reproducible adapters. |
createDefaultIdFactory | Create unique runtime event IDs. |
B4_PLAN_ACTIVITY_TYPE | Identify B4.run plan activity snapshots as b4.plan. |
B4PlanActivityContent | Describe the complete public plan snapshot. |
IdFactory | Define event-ID generation. |
B4Message | Describe a normalized inbound message; content is text or AG-UI content parts. |
B4RunInput | Describe normalized B4.run run input. |
fromRunAgentInput | Translate AG-UI run input to B4.run input. |
B4InterruptEnvelope | Describe a B4.run interrupt payload. |
B4AguiInterrupt | AG-UI's interrupt as B4.run emits it: the gated toolCallId, subagentRunId for a child's gate, a permission prompt's responseSchema, and the approval grant at metadata.grant. |
B4ResumeRequest | Describe one resume decision. |
AguiOutboundEvent | Name events emitted by the outbound mapper. |
ToAguiOptions | Configure outbound event IDs, the cancelled outcome, and pending client tool calls. |
toAguiEvents | Translate a B4.run stream into AG-UI events. |
B4_CONTENT_PARTS_DROPPED_EVENT | The CUSTOM event name (b4.content_parts_dropped) that announces parts the model could not use. |
B4AgentStreamChunk | Describe accepted B4.run stream chunks. |
B4UsageData | Describe one model call's token usage as the usage chunk carries it. |
RunContext | Supply thread and run IDs for outbound events. |
@b4run/ag-ui/sseCopy link to section: @b4run/ag-ui/sse
| Export | Responsibility |
|---|---|
encodeAgUiEvent | Encode one AG-UI event as the bytes of the binding accept selects: an SSE frame, or a length-prefixed protobuf frame. |
agUiContentType | The content-type of the binding accept selects. |
@b4run/ag-ui/clientCopy link to section: @b4run/ag-ui/client
| Export | Responsibility |
|---|---|
B4HttpAgent | An @ag-ui/client HttpAgent whose getCapabilities() reads the route's capabilities from GET on the same URL. |
@b4run/ag-ui/viewCopy link to section: @b4run/ag-ui/view
The framework-free half of the client: pure reducers and selectors over AG-UI events, with no React and no CopilotKit. ./react builds on it; so can any other framework. The runtime uses the same entry to serve GET /threads/:thread_id/turns, so a restored thread folds into the same TurnsView a live stream builds. It also holds the activity kit's framework-free rules (wording, durations, the open/closed rule, the clocks, the glyphs), so every kit words, times and draws a turn the same way.
| Export | Responsibility |
|---|---|
reduceTurns | Fold one AG-UI event into the turns of a thread: steps in order, nested subagent turns, the plan, reasoning, prose, and approvals attached to the calls they gate. Pure given now; an event that changes nothing returns the same state. |
EMPTY_TURNS | The initial turns state. |
turnsFromState | Rebuild a thread's turns from its checkpoint history and parked interrupts: the AG-UI events the stream would have carried are synthesised and folded through reduceTurns, so a restored view matches a live one. Never throws; ignored or missing stamps are named in warnings. |
eventsFromState | The thread as the AG-UI events its live runs would have carried, synthesised from the same input as turnsFromState: each turn's RUN_STARTED carries the user message (as content parts when it had media), a tool result that kept parts replays them as live sends them, a parked turn ends with RUN_FINISHED { outcome: interrupt }. What GET /threads/:id/events serves. Never throws. |
blocksToParts | A checkpointed message's LangChain content blocks mapped back to AG-UI content parts (text, image, audio, video, document; the legacy image_url block too), the reverse of what the runtime hands the model. eventsFromState uses it so a restored user attachment replays as parts. Never throws. |
EventsFromStateResult | What eventsFromState returns: events (each with timestamp) and warnings. |
ThreadStateForTurns | What GET /threads/:id/turns assembles: thread id and status, the root namespace's history, child namespaces, and parked interrupts. |
CheckpointForTurns | One decoded checkpoint: id, timestamp, metadata, and values.messages/values.todos as serialized LangChain envelopes. |
PendingInterruptForTurns | A parked interrupt as /pending_interrupts returns it, with its grant. |
TurnsFromStateResult | The rebuilt TurnsView plus warnings. |
TurnsView | The thread id and its turns. |
TurnView | One turn: its run id, status, timing, steps, prose, unattached approvals, error and failure count (nested subagents included). |
StepView | A tool, plan, reasoning or subagent step. |
ToolStep | One tool call with its streamed args, result text, non-text result parts (an image a tool rendered, live or restored), b4.step icon, label and sources, timing and approval. |
PlanStep | The plan as its latest snapshot of todos. |
ReasoningStep | One reasoning span and its text, streaming or done. |
SubagentStep | A subagent invocation holding its nested turn. |
ApprovalView | A parked interrupt as a chat shows it: kind, detail, message, the grant to echo on resume, and whether "Always allow" is offered. |
StepSource | A source a step cites; an alias of the SDK's ToolDisplaySource, as b4.step carries it. |
StepStatus | pending, running, done, failed or awaiting. |
TurnStatus | working, awaiting, done, failed or stopped. |
ReduceTurnsOptions | Inject the clock, name tools whose frames the view drops, and say whether a same-thread run resumes the awaiting turn (resuming). |
stepLabel | The sentence for a tool step: the app's override for that tool, else the server's b4.step label, else "Using X…"/"Used X"; never throws, never echoes raw arguments, at most 120 characters. |
groupSteps | Fold two or more consecutive done calls of one tool into a group with a summary label; pending, running, failed and awaiting steps never join, nor do task and writeTodos. |
StepLabelOverride | Client-side wording for one tool: reword, localize, or label a group. |
StepLabelOverrides | Overrides keyed by tool name. |
StepGroup | A run of merged tool steps and its label. |
GroupedStep | A step or a group. |
BUILT_IN_GROUP_LABELS | Group wording for B4.run's built-in tools; apps extend it through overrides. |
B4_STEP_EVENT_NAME | The AG-UI CUSTOM event name a tool call's human-readable step travels as (b4.step). |
B4_STEP_STATUSES | The statuses a step can carry; the one source for every validator. |
B4StepEventValue | A b4.step event's value: toolCallId, status, icon, label, sources. |
B4StepStatus | running, completed, failed or denied. |
readStepEvent | The b4.step value an event carries, or undefined for any other event or a malformed one; invalid optional fields are dropped. |
isSubagentMessage | Narrow a transcript message to one a subagent produced. |
turnForToolCalls | The turn that owns any of these tool call ids, nested subagent calls included. |
turnForMessage | The turn an assistant message belongs to, by the tool calls of its run of messages, else by position from the end of the thread; first marks the run's first assistant message, where a chat with one slot per message renders the turn's activity. |
TranscriptMessage | What turnForMessage reads of a message: id, role and the assistant's tool calls. AG-UI's Message fits. |
MessageTurn | A message's turn and whether the message is the turn's first assistant message. |
approvalFromInterrupt | A parked AG-UI interrupt as an ApprovalView: kind, detail, message, grant, and whether "Always allow" is offered. |
approvalPrompt | The card's title, {agent} wants to {label}, for a parked interrupt: the gated step's running label and the subagent it sits in, else "The agent" and "continue". |
approvalLabel | A gated step's running label, lower-cased, as it follows "wants to"; "use X" when the step has none. |
ApprovalPrompt | An approval card's agent and label. |
pendingApprovals | The approval cards an awaiting thread shows, read from its turns alone: every awaiting step's approval in the last turn and its paused subagents, then the interrupts that named no step. |
PendingApproval | One card to show: the ApprovalView and its prompt. |
summaryLine | The summary sentence and meta for a turn at a given time. |
nestedSummaryLine | The summary of a subagent's own turn: like any turn while it runs, then "researcher · paused", "researcher finished · 5 steps" or "researcher failed · boom". |
NestedTurn | A subagent's name and status, as its nested turn's summary needs them. |
SummaryLine | A summary line: its text, its muted meta, and whether it shows the running treatment. |
formatDuration | <1s, Ns, Nm Ms; undefined for an unknown duration. |
countSteps | Steps in a turn and its nested subagent turns; a subagent counts as one step too. |
countSources | Sources cited by a turn's tool steps and its nested subagent turns. |
stepMeta | A tool step's muted tail: awaiting approval, denied, or failed with no error text. |
groupMeta | A merged group's muted tail: how many sources its calls cite. |
ownEntry | An own-key lookup in a per-tool table, so a wire name like toString never finds Object.prototype. |
planProgress | How many plan items are done, of how many. |
todoStatusLabel | A plan item's status as the visually hidden text after it. |
reasoningLabel | "Thinking…", "Thought for 4s", or "Show reasoning" when the duration is unknown. |
subagentRowState | A subagent row's data-state; a paused subagent reads as awaiting. |
isSubagentLive | Whether a subagent is running or paused on an approval. |
subagentSettledText | A settled subagent row's sentence: "researcher finished" or "researcher failed". |
subagentMeta | A subagent row's muted tail: the error once failed, the step count once done. |
stepDetailText | A step's input and result pretty-printed and capped, the text "Show raw" opens, and whether both are empty. |
stepDetailView | A step's input and result as the detail panel shows them: rows for an object (one nested level as dotted keys), a group of rows per object in a short list, plain text for a string or scalar, pretty JSON for anything deeper, plus the raw original of each side shown as rows. |
StepDetailView | What stepDetailView returns: the input and result blocks, the raw originals, and whether both are empty. |
DetailBlock | One side of a step's detail: fields, records, text or code. |
DetailField | One key/value row of a fields block. |
MAX_FIELD_CHARS | The longest field value a row shows (80 characters) before it is cut to its first line with its full length. |
prettyValue | JSON pretty-printed with two spaces; any other text as-is. Never throws. |
capDetail | A detail text cut at MAX_DETAIL_CHARS with a "… (truncated)" line. |
MAX_DETAIL_CHARS | The longest inputs or output a detail panel shows, 20,000 characters. |
isSafeHref | Whether a source's link may render as a link: web, mail and same-origin paths only. |
approvalPayload | The payload an approval card shows: args preview, command, a subagent gate's name, input and reason, or detail JSON. |
scopeLine | What "Always allow" covers, from the interrupt's kind and pattern. |
approvalErrorLine | The line an approval card shows when its decision could not be sent. |
dispatchDecision | Run an approval decision on the click itself and report a throw or a rejection as a message. |
ApprovalDecision | once, always or deny. |
DisclosureMemory | What the open/closed rule remembers: the user's choice, whether the item was live, and the key it was last live under. |
initialDisclosure | The memory of a disclosure when it first renders. |
observeDisclosure | The open/closed rule: automation decides until the user toggles; the user wins until the item is live again under a new key. |
toggleDisclosure | The memory after the user toggles. |
isDisclosureOpen | Whether a disclosure is open: the user's choice, else automation's. |
NO_FLASH_MS | A step that settles within this many milliseconds (300) never shows its running treatment. |
noFlashRemaining | Milliseconds until a running step may show its running treatment. |
ELAPSED_TICK_MS | How often a live turn's elapsed time is re-sampled (1000 ms). |
sampleElapsed | Sample a clock now and once a second until stopped. |
STEP_GLYPHS | Each step icon as SVG shapes: one per ToolDisplayIcon name plus alert and check. |
stepGlyph | A step's glyph by icon name; unknown names draw the generic tool glyph. |
CHEVRON_GLYPH | The disclosure chevron's shapes. |
checklistBox | A plan item's checkbox shape, filled once done. |
CHECKLIST_TICK | The tick drawn over a done plan item's box. |
Glyph | A glyph: a list of shapes. |
GlyphShape | One SVG shape: its element name and DOM attributes. |
@b4run/ag-ui/reactCopy link to section: @b4run/ag-ui/react
The React activity kit. Components are pure functions of the TurnView/StepView props @b4run/ag-ui/view builds; interaction state (open/closed, elapsed time, the 300 ms no-flash rule) lives in the hooks next to them.
| Export | Responsibility |
|---|---|
TurnActivity | The summary line plus the step list for one turn, nested for subagents: working, awaiting, done, failed or stopped. |
TurnActivityProps | Props for TurnActivity: the turn, label overrides, step renderers, the clock, and whether it is a subagent's turn. |
Step | One tool call as a sentence with its icon and meta; opens to StepDetail. |
StepProps | Props for Step: the tool step, label overrides, step renderers and the clock. |
StepRenderer | A per-tool replacement for a step's detail panel (the StepDetail it opens to), given the ToolStep; the sentence line stays. |
StepRenderers | Step renderers keyed by tool name. |
StepGroup | Consecutive done calls of one tool, merged; opens to the individual steps. |
StepGroupProps | Props for StepGroup: the group, label overrides, step renderers and the clock. |
StepDetail | A step's input and result, readable first: rows for an object, a group of rows per object in a short list, plain text for a string, pretty JSON for anything deeper, and a "Show raw" toggle for a side shown as rows. |
StepDetailProps | Props for StepDetail: the args text and the optional result text. |
PlanStep | "Made a plan · 2 of 4 done" with the checklist; updates in place. |
PlanStepProps | Props for PlanStep: the plan step and whether the owning turn is live. |
ReasoningStep | "Thinking…", "Thought for 4s" or "Show reasoning"; opens to the text. |
SubagentStep | "Asked researcher", its description as a muted line beneath, with the child's own activity nested; folds to "researcher finished · N steps". |
SubagentStepProps | Props for SubagentStep: the subagent step, label overrides, step renderers and the clock. |
ApprovalCard | A parked interrupt: who wants what, why, the payload, Allow once / Always allow / Deny on one row, and the scope line. |
ApprovalCardProps | Props for ApprovalCard: the approval, the agent's name, the gated step's label and the decision callback. |
ApprovalDecision | once, always or deny. |
SourceChips | File or URL chips from a step's sources, with "+N" overflow. |
SourceChipsProps | Props for SourceChips: the sources and the chip limit before overflow. |
Disclosure | A button[aria-expanded] and its panel, following the open/closed rule. |
DisclosureProps | Props for Disclosure: open state, toggle, the button class, the summary and the panel. |
useDisclosure | The open/closed rule: automation decides until the user toggles; the user wins until the item is live again. |
StepIcon | The glyph for a ToolDisplayIcon name (16px, currentColor). |
Chevron | The disclosure chevron. |
StatusText | The muted "· meta" fragment after a sentence. |
Checklist | The plan's SVG checklist. |
summaryLine | The summary sentence and meta for a turn at a given time. |
SummaryLine | A summary line: its text, its muted meta, and whether it shows the running treatment. |
formatDuration | <1s, Ns, Nm Ms; undefined for an unknown duration. |
approvalPayload | The payload an approval card shows: args preview, command, a subagent gate's name, input and reason, or detail JSON. |
scopeLine | What "Always allow" covers, from the interrupt's kind and pattern. |
useLive | Whether a running step shows its running treatment (after 300 ms). |
useElapsed | A clock re-sampled once a second while active. |
TurnActivity is the drop-in: give it a TurnView from reduceTurns and it renders the turn. The kit components are plain React and don't need CopilotKit; the CopilotKit connector is @b4run/ag-ui/react/copilotkit.
@b4run/ag-ui/react/copilotkitCopy link to section: @b4run/ag-ui/react/copilotkit
The CopilotKit (React) connector: it drives a stock <CopilotChat> with the activity kit.
| Export | Responsibility |
|---|---|
B4Activity | Provider around your chat: hides CopilotKit's generic tool rows, renders one ApprovalCard per parked interrupt (in the chat by default; renderInChat={false} renders them after its children for a host with its own transcript), and keeps the thread's turns current from the agent's events. Supports approvals.grants: "off" today. |
B4ActivityProps | Props for B4Activity: the agent id, per-tool labels, hiddenTools, per-tool renderStep, renderInChat, the clock and children. |
useB4ActivityContext | The turns, labels and renderStep B4Activity provides, for host UI outside the chat (a map, a sheet); throws outside B4Activity. |
B4ActivityContextValue | What useB4ActivityContext returns: the TurnsView, the labels and renderStep passed to B4Activity, and its clock. |
useB4ChatSlots | Props to spread onto <CopilotChat>: one tool row per turn rendered as TurnActivity, no toolbar under tool-only rows. |
B4ChatSlots | The messageView slots useB4ChatSlots returns: transformMessages and assistantMessage. |
useB4Turns | The agent's thread as turns (reduceTurns), plus markResuming() to call before sending a resume and clearResuming() to forget it when the resume request failed. |
UseB4TurnsOptions | Options for useB4Turns: the clock and the tools whose frames the view drops. |
UseB4TurnsResult | What useB4Turns returns: the TurnsView, markResuming and clearResuming. |
mergeTurnMessages | The transformMessages function useB4ChatSlots installs: one tool-only assistant row per turn, the kept row carrying the union of the turn's tool-call ids, subagent messages dropped. |
@b4run/ag-ui/angularCopy link to section: @b4run/ag-ui/angular
The Angular activity kit: standalone, OnPush components with signal inputs that render the same DOM contract (classes, data-* and aria-* attributes, text) as the React kit, from the TurnView/StepView values @b4run/ag-ui/view builds. Element hosts are display: contents; the step rows attach to the list item itself (<li b4-step>).
| Export | Responsibility |
|---|---|
TurnActivityComponent | <b4-turn-activity [turn]>: the summary line plus the step list for one turn, nested for subagents. Inputs: turn, labels, renderStep, now, nested. |
ApprovalCardComponent | <b4-approval-card [approval] [agent] [label] [onDecide]>: a parked interrupt with Allow once / Always allow / Deny and the scope line; a throw or rejection from onDecide shows inline and re-enables the buttons. |
StepComponent | <li b4-step [step]>: one tool call as a sentence; opens to its inputs and output. |
StepRenderers | Per-tool components keyed by tool name that replace a step's detail panel; each receives the step as its step input. |
StepGroupComponent | <li b4-step-group [group]>: consecutive done calls of one tool, merged. |
PlanStepComponent | <li b4-plan-step [step] [live]>: "Made a plan · 2 of 4 done" with the checklist. |
ReasoningStepComponent | <li b4-reasoning-step [step]>: "Thinking…", "Thought for 4s" or "Show reasoning". |
SubagentStepComponent | <li b4-subagent-step [step]>: "Asked researcher" with the child's activity nested. |
StepDetailComponent | <b4-step-detail [args] [result]>: a step's input and result: rows, a group of rows per object, plain text or pretty JSON, with "Show raw" for a side shown as rows. |
SourceChipsComponent | <b4-source-chips [sources] [limit]>: file or URL chips with "+N" overflow. |
DisclosureComponent | <b4-disclosure [open] [className] (toggle)>: a button[aria-expanded] and its panel, for custom steps. |
StepIconComponent | <b4-step-icon [name]>: the glyph for a ToolDisplayIcon name. |
ChecklistComponent | <b4-checklist [todos]>: the plan's SVG checklist. |
SvgAttrsDirective | [b4SvgAttrs]: sets an SVG shape's attributes from a shared glyph. |
disclosure | The open/closed rule over signals: automation decides until the user toggles; the user's choice holds until the item is live again. |
DisclosureState | What disclosure returns: the open state and its toggle. |
elapsedSignal | A clock re-sampled once a second while active; call in an injection context. |
liveSignal | Whether a running step shows its running treatment (after 300 ms); call in an injection context. |
@b4run/ag-ui/angular/eventsCopy link to section: @b4run/ag-ui/angular/events
The Angular kit's connector for any chat, with no chat framework: give it the thread's AG-UI events.
| Export | Responsibility |
|---|---|
B4TurnsStore | The thread as a turns signal, folded by reduceTurns: connect(events$), apply(event), reset(turns?) for a restored view, markResuming()/clearResuming(), destroy(). An event with a numeric timestamp (a replay) is folded at that time. |
createB4Turns | A store that stops following its stream when the calling injection context is destroyed (or pass injector). |
provideB4Turns | Provides a store to a subtree, from options or a function run in the injection context. |
B4TurnsOptions | The store's options: events$, hiddenTools, labels, renderStep and the clock. |
B4EventStream | A stream of AG-UI events: an RxJS Observable<BaseEvent>, or anything with the same subscribe. |
B4TurnEvent | One AG-UI event, as reduceTurns folds it. |
MessageActivityComponent | <b4-message-activity [messageId] [messages]>: the turn's <b4-turn-activity> on its first assistant message, nothing on the others. |
ApprovalsComponent | <b4-approvals [resume]? (decide)>: one approval card per parked interrupt; a click marks the resume, then emits and awaits the decision. |
B4ApprovalDecision | A decision on one parked interrupt: its id and once, always or deny. |
@b4run/ag-ui/angular/copilotkitCopy link to section: @b4run/ag-ui/angular/copilotkit
The CopilotKit (Angular) connector, on @copilotkit/angular: it drives a stock <copilot-chat> with the activity kit.
| Export | Responsibility |
|---|---|
provideB4Activity | Provides a B4ActivityStore to the subtree, also as B4TurnsStore; inject it in the providing component so it sees every event. |
B4ActivityOptions | Options for provideB4Activity: the agent id, per-tool labels, hiddenTools, per-tool renderStep and the clock. |
B4ActivityStore | Follows the chat's agent into turns and CopilotKit's parked interrupts into interrupts; decide(interruptId, decision) marks the resume, then resolves or cancels through CopilotKit. Supports approvals.grants: "off" today. |
B4Interrupt | A parked interrupt, as CopilotKit's interrupt controller holds it. |
B4ActivityAssistantMessageComponent | <copilot-chat>'s assistant message: the message's text through CopilotKit's own assistant message, then the turn's <b4-turn-activity> on the turn's first assistant message. |
B4ActivityApprovalsComponent | One approval card per interrupt CopilotKit holds open, as <copilot-chat>'s [messageViewChildrenComponent] or anywhere under provideB4Activity. |
@b4run/ag-ui/copilotkit-runtimeCopy link to section: @b4run/ag-ui/copilotkit-runtime
The server half of the CopilotKit connector, for the CopilotKit runtime route in your app. It uses only fetch and rxjs, so it runs in a Node or an edge runtime route.
| Export | Responsibility |
|---|---|
createB4AgentRunner | createB4AgentRunner(Base, options) builds a CopilotKit runtime runner (new CopilotRuntime({ agents, runner })) from Base, CopilotKit's InMemoryAgentRunner class: an instance of a subclass that overrides only connect, so runs, stop, isRunning and the local-thread endpoints are the base runner's; connect replays GET /threads/:id/events from the B4 server, and while a run is live in this process it continues with that run's events, so a reload or a new instance restores the chat, its activity and a parked approval. |
B4AgentRunnerBase | The shape createB4AgentRunner extends: a class whose instances have connect (returning an observable of events) and isRunning. CopilotKit's InMemoryAgentRunner fits it; the returned runner has the base class's type. |
B4AgentRunnerOptions | The B4 server's url, the fetch to read with, and onWarnings for replays that carried warnings. The read carries only the headers that fetch adds, never the browser request's, so it must carry the current caller's identity, derived per request (for example from an AsyncLocalStorage), never a fixed service credential, which would let any browser restore any thread whose id it knows. A read the thread gate refuses (404) restores as an empty chat, with no error. |
@b4run/ag-ui/styles.cssCopy link to section: @b4run/ag-ui/styles.css
This subpath is the activity kits' default stylesheet, one sheet for the React and Angular kits. It has no TypeScript exports, runtime 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 "@b4run/ag-ui/styles.css"In an Angular application, list it in angular.json's styles ("@b4run/ag-ui/styles.css") or @import it from a global stylesheet.
The sheet is optional, and the components render without it. Every rule sits in @layer b4-activity, so any unlayered app CSS wins, and every rule that styles an element is scoped to the b4- prefix, so it can't restyle the rest of your application.
The sheet also declares --b4-activity-* design tokens on :root. To restyle the kit, override these properties in your own CSS:
--b4-activity-surface,--b4-activity-surface-alt,--b4-activity-border,--b4-activity-text,--b4-activity-muted--b4-activity-running,--b4-activity-running-bg,--b4-activity-complete,--b4-activity-failed,--b4-activity-failed-bg,--b4-activity-primary,--b4-activity-on-primary--b4-activity-radius,--b4-activity-radius-card,--b4-activity-radius-pill, and--b4-activity-font-mono
Put the overrides in plain, unlayered CSS. A Tailwind @theme block won't work, because token values declared there lose to this sheet. Dark mode follows the host, not the OS: the dark palette applies under a .dark or [data-theme="dark"] ancestor, or when data-b4-theme="dark" is set on the root element. data-b4-theme="light" pins light, and data-b4-theme="auto" follows prefers-color-scheme instead. The token blocks are wrapped in :where(), so your own :root override wins in every theme.
Key contractsCopy link to section: Key contracts
Activity identifiers and payloadsCopy link to section: Activity identifiers and payloads
export declare const B4_PLAN_ACTIVITY_TYPE: "b4.plan"export interface B4PlanActivityContent {
readonly todos: ReadonlyArray<{
readonly content: string
readonly status: "pending" | "in_progress" | "completed"
}>
}Behavior contract ag-ui.activities.plan-snapshot
A valid plan update becomes a complete replacement snapshot with activity type b4.plan and the stable message ID b4:plan:<runId> without breaking an open assistant text message.
Behavior contract ag-ui.subagents.lifecycle
A subagent is announced with SUBAGENT_STARTED before any event is attributed to it, every event it produces carries its subagentRunId, and every announced invocation closes before RUN_FINISHED: with SUBAGENT_FINISHED on its result, suspended at an interrupt, or SUBAGENT_ERROR on failure, cancel, or a stream that ended first.
ToAguiOptionsCopy link to section: ToAguiOptions
Supply an IdFactory when emitted IDs must be deterministic. Production integrations use the default factory.
export interface ToAguiOptions {
readonly idFactory?: IdFactory
readonly cancelled?: () => boolean
readonly pendingToolCallIds?: () => readonly string[] | Promise<readonly string[]>
}Fields: @b4run/ag-ui#.:ToAguiOptions
| Field | Type | Required | Description |
|---|---|---|---|
readonly idFactory | IdFactory | no | Override outbound event-ID generation. |
readonly cancelled | () => boolean | no | Asked once when the upstream stream throws; true ends the run with RUN_FINISHED and outcome.type: "cancelled" instead of RUN_ERROR. |
readonly pendingToolCallIds | () => readonly string[] | Promise<readonly string[]> | no | Asked when the run succeeds, and may return a Promise; a non-empty list becomes outcome.pendingToolCallIds. A rejection ends the run as RUN_ERROR. |
Inbound and outbound callsCopy link to section: Inbound and outbound calls
export interface B4RunInput {
readonly messages: B4Message[]
readonly resume?: B4ResumeRequest[]
readonly raw: RunAgentInput
}Fields: @b4run/ag-ui#.:B4RunInput
| Field | Type | Required | Description |
|---|---|---|---|
readonly messages | B4Message[] | yes | Supply normalized messages. |
readonly resume | B4ResumeRequest[] | no | Supply normalized resume decisions. |
readonly raw | RunAgentInput | yes | Preserve the untouched AG-UI input. |
export interface B4Message {
readonly role: "user" | "assistant" | "system" | "developer" | "tool"
/** Plain text, or the ordered content parts the client sent (AG-UI 1.0). */
readonly content: string | readonly B4ContentPart[]
readonly id?: string
readonly toolCallId?: string
}B4ContentPart is exported by @b4run/sdk and is structurally AG-UI's ContentPart.
export interface RunContext {
readonly threadId: string
readonly runId: string
}export interface B4UsageData {
readonly provider?: string | undefined
readonly model?: string | undefined
readonly usage_metadata: Readonly<Record<string, unknown>>
}Fields: @b4run/ag-ui#.:B4UsageData
| Field | Type | Required | Description |
|---|---|---|---|
readonly provider | string | undefined | no | Name the provider, lower-cased from LangChain's ls_provider. |
readonly model | string | undefined | no | Name the model, from LangChain's ls_model_name. |
readonly usage_metadata | Readonly<Record<string, unknown>> | yes | Carry the provider's LangChain usage_metadata untouched; the mapper applies the protocol's accounting. |
export declare function fromRunAgentInput(input: RunAgentInput): B4RunInputexport declare function toAguiEvents(
chunks: AsyncIterable<B4AgentStreamChunk>,
ctx: RunContext,
options?: ToAguiOptions,
): AsyncGenerator<AguiOutboundEvent>export declare function encodeAgUiEvent(event: BaseEvent, accept?: string): Uint8Array<ArrayBuffer>export declare function agUiContentType(accept?: string): stringexport declare class B4HttpAgent extends HttpAgent {
getCapabilities(): Promise<AgentCapabilities>
}getCapabilities() sends GET to the agent's url with its headers and fetch, and parses the answer with AG-UI's AgentCapabilitiesSchema. It throws on a non-2xx answer.
Behavior 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 B4.run shapes, omits resume for an empty array, and preserves the untouched AG-UI input under raw for tools, state, and context.
Stream edge casesCopy link to section: Stream edge cases
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. A step chunk becomes a CUSTOM event named b4.step; a malformed one is ignored.
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 guidesCopy link to section: Examples and related guides
import { type B4AgentStreamChunk, toAguiEvents } from "@b4run/ag-ui"
import { encodeAgUiEvent } from "@b4run/ag-ui/sse"
async function* aguiFrames(chunks: AsyncIterable<B4AgentStreamChunk>) {
for await (const event of toAguiEvents(chunks, { threadId: "thread-1", runId: "run-1" })) {
yield encodeAgUiEvent(event)
}
}Continue with AG-UI and Web Clients, Embed the Runtime, and Security Architecture.