AG-UI ยท API Reference

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 globally via provideAgent() โ€” injectAgent() itself takes no arguments.

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()unknownLatest runtime error, when present.
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.
regenerate(index)Promise<void>Remove the assistant message at index and rerun from the preceding user message.

#AG-UI-specific surface

The AG-UI adapter extends the neutral Agent contract with one additional signal:

FieldTypeDescription
customEvents()CustomStreamEvent[]Custom events emitted by the backend during a run. Accumulates per run; resets on each new submit().

injectAgent() returns the AgUiAgent type โ€” the neutral Agent contract plus customEvents โ€” so the signal is reachable directly, no cast required:

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

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.

Don't 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 an interrupt by passing a resume payload:

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

#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.

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