Page actions

injectAgent()

injectAgent() retrieves the AG-UI agent from Angular's dependency injection container. Call it in an Angular injection context — typically as a component field initializer. The returned object exposes Angular Signals for reactive UI state and async methods for user actions.

Configuration is supplied by provideAgent(). The no-argument form resolves the shared agent; pass the same AgentRef supplied to provideAgent(ref, …) to carry the state type through DI.

import { injectAgent } from '@threadplane/ag-ui';
 
readonly chat = injectAgent();
 
await this.chat.submit({ message: 'Hello' });

In practice you rarely call submit() yourself — you hand the agent to the <chat> composition from @threadplane/chat, which drives streaming, tool calls, errors, and submit for you:

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ChatComponent } from '@threadplane/chat';
import { injectAgent } from '@threadplane/ag-ui';
 
@Component({
  selector: 'app-chat',
  standalone: true,
  imports: [ChatComponent],
  template: `<chat [agent]="agent" />`,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ChatPage {
  protected readonly agent = injectAgent();
}

Pair it with provideAgent() at bootstrap to configure the agent endpoint:

import { bootstrapApplication } from '@angular/platform-browser';
import { provideAgent } from '@threadplane/ag-ui';
import { AppComponent } from './app/app.component';
 
bootstrapApplication(AppComponent, {
  providers: [
    provideAgent({ url: 'http://localhost:8000/my-agent' }),
  ],
});

Runtime-neutral surface

These fields are stable across runtime adapters and are what chat components consume.

FieldTypeDescription
messages()Message[]Chat messages with role, content, optional toolCallIds, citations, and reasoning.
status()'idle' | 'running' | 'error'UI lifecycle status.
isLoading()booleanConvenience signal for active streaming.
error()AgentError | undefinedLatest runtime error, when present. An interrupted error also carries recovery and detail.
toolCalls()ToolCall[]Tool calls projected into the chat contract.
state()Record<string, unknown>Latest agent state projected as a plain object.
interrupt()AgentInterrupt | undefinedCurrent interrupt, when the backend pauses for human input.
events$Observable<AgentEvent>Runtime-neutral observable of transient events (state_update / custom). Subscribe for side-effects; not a signal.
submit(input, opts?)Promise<void>Submit a user message or resume payload.
stop()Promise<void>Abort the active run.
retry()Promise<void>Re-run the last submitted input after a failure. No-op while a run is in flight or when there is nothing to retry.
regenerate(index)Promise<void>Remove the assistant message at index and rerun from the preceding user message.
checkStatus?()Promise<void>Read-only reconciliation of an uncertain run outcome, present only when persistence.reconcile is configured. Offered when error().recovery is check; resubmits nothing and appends no message.

AG-UI-specific surface

The AG-UI adapter extends the neutral Agent contract with AG-UI-specific protocol surfaces:

FieldTypeDescription
customEvents()CustomStreamEvent[]Custom events emitted by the backend during a run. Accumulates per run; resets when RUN_STARTED arrives.
clientToolsClientToolsCapabilityBrowser client-tool catalog, pending calls, and result resolution used by <chat [clientTools]>.
readyPromise<void>Resolves after configured persisted state is hydrated.
interruptSession()InterruptSessionSnapshotFull batch, generation, ownership phase, and retained resume attempt.
reconcileInterrupt()Promise<void>Applies authoritative recovery using the application-provided persistence reconciler.
dispose()voidStops local work; providers call it on injector destruction. Does not cancel backend checkpoints.
subagents()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.

injectAgent() returns the AgUiAgent type — the neutral Agent contract plus these AG-UI-specific fields — so they are reachable directly, no cast required:

import { injectAgent } from '@threadplane/ag-ui';
 
const chat = injectAgent();
chat.customEvents(); // CustomStreamEvent[]
chat.subagents(); // Map<string, Subagent>

The chat a2ui bridge reads customEvents to light up live generative-UI streaming when your backend emits a2ui-partial events. The consuming side is documented in chat's A2UI overview. See the Custom Events guide for backend wiring details.

Do not confuse customEvents() with the neutral events$ listed above. Each CUSTOM event is fanned out to both: events$ is the runtime-neutral Observable<AgentEvent> you subscribe to for transient side-effects (telemetry, toasts), while customEvents() is the AG-UI-specific signal that accumulates CustomStreamEvent[] as a per-run snapshot for reactive rendering. See the Event Mapping reference for the full fan-out.

Submit and resume

Use the runtime-neutral submit shape for normal chat input:

await chat.submit({ message: 'Summarize this document' });

Resume a pending single interrupt by passing the payload expected by the backend:

await chat.submit({ resume: { approved: true } });

Native batches require every pending ID exactly once; cancelled entries omit payload. Capture chat.interruptSession().generation when rendering approval controls and pass { interruptGeneration: generation } as the second submit argument to reject stale decisions. For the Mastra integration, configure interruptTransport: 'mastra-command' on the provider.

Await chat.ready before showing restored controls. retry() can resend the retained decision after a proven pre-dispatch failure; uncertain delivery requires chat.reconcileInterrupt() with authoritative backend evidence before another attempt. These extensions do not imply the same recovery API on the LangGraph adapter.

Regenerate semantics

regenerate(assistantMessageIndex) has replace semantics: it keeps the user message before the selected assistant message, removes the selected assistant message and all later messages, syncs the rollback to the AG-UI source, then reruns with no new user message appended.

await chat.regenerate(3);

The method throws when the selected index is not an assistant message, when no preceding user message exists, or while another response is already loading.

Warning: Injection context required

injectAgent() must be called during construction, inside an injection context (e.g. a component constructor, field initializer, or a function passed to runInInjectionContext). Calling it outside an injection context will throw.

What's Next

injectAgentfunction

Injects the AG-UI agent from Angular's dependency injection container. Use this in components or services provided via `provideAgent()` (or `provideFakeAgent()`). Returns an `AgUiAgent` — the runtime-neutral `Agent` contract plus the AG-UI-specific `customEvents` signal — so `customEvents` is reachable directly, without casting. **Typed state via AgentRef.** Pass the same ref that was supplied to `provideAgent(ref, …)` to carry the state type through DI without repeating the generic at every call site. The no-arg form defaults to `AgUiAgent<Record<string, unknown>>`.

injectAgent(): AgUiAgent<>

Returns

AgUiAgent<>

Examples

const agent = injectAgent(TRIP); // AgUiAgent<TripState>

Looking for something specific?