Page actions

toAgent()

toAgent() is the lower-level adapter function that wraps a raw AG-UI AbstractAgent into the runtime-neutral Agent contract used by @threadplane/chat components.

toAgent(source: AbstractAgent, options?: ToAgentOptions): AgUiAgent

Most applications should use provideAgent() instead — it constructs the HttpAgent source and calls toAgent() internally. Reach for toAgent() directly when you instantiate or customize the AbstractAgent yourself, for example to integrate a non-HTTP AG-UI transport.

import { HttpAgent } from '@ag-ui/client';
import { toAgent } from '@threadplane/ag-ui';
 
const source = new HttpAgent({ url: 'http://localhost:8000/my-agent' });
const agent = toAgent(source, { telemetry: myTelemetrySink });

ToAgentOptions

OptionTypeDescription
interruptTransportInterruptTransportauto (default), protocol, legacy-command, or mastra-command. Native batches take precedence in auto.
persistenceAgUiInterruptPersistenceApplication-owned durable storage and optional authoritative reconciliation. Requires a stable source threadId and scoped namespace.
telemetryAgentRuntimeTelemetrySink | falseOptional app-owned sink. Supply one to receive runtime lifecycle events.
a2uiClientCapabilities{ supportedCatalogIds: string[]; inlineCatalogs?: unknown[] }A2UI catalog negotiation to advertise to the agent. Seeded once into the AG-UI shared state under the a2ui_client_capabilities key, so every RunAgentInput.state carries it. Use a2uiClientCapabilities() from @threadplane/chat for the renderer's standard value.

AgUiAgent

toAgent() returns an AgUiAgent, which extends the neutral Agent contract with AG-UI-specific protocol surfaces:

FieldTypeDescription
readyPromise<void>Resolves after persisted state is hydrated; actions also wait for hydration.
interruptSession()InterruptSessionSnapshotCurrent batch, generation, phase, and retained attempt.
reconcileInterrupt()Promise<void>Applies authoritative recovery through the configured persistence reconciler. An unknown result leaves recovery blocked.
dispose()voidStops local work and unsubscribes. Call when a directly created adapter is no longer needed; it does not cancel backend checkpoints.
customEvents()Signal<CustomStreamEvent[]>Custom events accumulated during a run. Resets at the start of each new run.
clientToolsClientToolsCapabilityBrowser client-tool catalog, pending calls, and result resolution. The chat composition uses this when you pass <chat [clientTools]>.
subagents()Signal<Map<string, Subagent>>Subagent runs from SUBAGENT_* events, keyed by subagentRunId, plus the ACTIVITY_* convention (activityType: 'subagent', keyed by messageId), projected to the neutral subagent contract.

The standard Agent signals (messages, status, isLoading, error, toolCalls, state, interrupt) and actions (submit, retry, stop, regenerate) are all present.

Capture interruptSession().generation when rendering a decision and pass it to submit(input, { interruptGeneration }) to reject stale controls. A proven pre-dispatch failure retains the exact decision for retry(); uncertain delivery requires authoritative reconciliation first. These recovery extensions belong to AgUiAgent, not the neutral Agent contract.

CustomStreamEvent

CustomStreamEvent is the element type of AgUiAgent.customEvents:

interface CustomStreamEvent {
  /** Event name set by the backend (e.g. 'a2ui-partial', 'state_update'). */
  name: string;
  /** Arbitrary payload from the backend (JSON-string values are parsed). */
  data: unknown;
}

Custom events are surfaced from AG-UI CUSTOM protocol events whose name is not on_interrupt. The on_interrupt event is routed to the interrupt signal instead.

Read the accumulated events after a run by calling the signal — inside an effect, it re-runs as new events arrive:

import { effect } from '@angular/core';
import { HttpAgent } from '@ag-ui/client';
import { toAgent } from '@threadplane/ag-ui';
 
const agent = toAgent(new HttpAgent({ url: '/api/agent' }));
 
effect(() => {
  for (const e of agent.customEvents()) {
    console.log(e.name, e.data);
  }
});

Lifecycle note

The returned AgUiAgent does not manage its own lifetime. When using DI via provideAgent(), the provider's destroy hook handles cleanup. When calling toAgent() directly, treat the returned agent's lifecycle as tied to the AbstractAgent instance you constructed.

What's Next

toAgentfunction

Wraps an AG-UI AbstractAgent into the runtime-neutral Agent contract. The adapter subscribes to source.subscribe({ onEvent }) and reduces every event into the produced Agent's signals. submit() optimistically appends the user message to both our signals and the source agent's internal message list, then calls source.runAgent(). stop() calls source.abortRun(). Subscription cleanup: providers dispose the adapter with their injector. Direct callers must call dispose() when they no longer need the adapter.

toAgent(source: AbstractAgent<>, options: ToAgentOptions): AgUiAgent<>

Parameters

ParameterTypeDescription
sourceAbstractAgent<>
options?ToAgentOptions

Returns

AgUiAgent<>

Examples

import { HttpAgent } from '@ag-ui/client';
import { toAgent } from '@threadplane/ag-ui';

const agent = toAgent(new HttpAgent({ url: '/api/agent' }));

Looking for something specific?