Page actions

Installation

Supported Angular majors: 20, 21, and 22.

Use a Node.js version supported by the selected Angular major. Angular 22 supports Node.js ^22.22.3, ^24.15.0, or ^26.0.0. See the Angular compatibility matrix.

Prerequisites

  • Angular 20, 21, or 22
  • An AG-UI-compatible backend running locally or remotely (CrewAI, Mastra, Microsoft Agent Framework, AG2, Pydantic AI, AWS Strands, or your own subclass of AbstractAgent)

Install packages

npm install @threadplane/chat @threadplane/ag-ui @ag-ui/client @ag-ui/core marked

@threadplane/chat provides the chat UI primitives. @threadplane/ag-ui provides the adapter that wires an AG-UI backend into the Agent contract those primitives consume. marked is the required markdown parser peer used by @threadplane/chat when assistant messages render through <chat>.

Peer Dependencies

@threadplane/ag-ui declares the following peer dependencies:

PackageVersion
@threadplane/chat0.0.66
@threadplane/telemetry^0.0.66
@angular/core^20.0.0 || ^21.0.0 || ^22.0.0
@ag-ui/client^1.0.1
@ag-ui/core^1.0.1
rxjs~7.8.0

Configure the provider

In your app config:

import { ApplicationConfig } from '@angular/core';
import { provideAgent } from '@threadplane/ag-ui';
 
export const appConfig: ApplicationConfig = {
  providers: [
    provideAgent({
      url: 'http://localhost:3000/agent', // your AG-UI backend
    }),
  ],
};

provideAgent accepts:

OptionTypeDescription
urlstringRequired. AG-UI backend HTTP/SSE endpoint.
agentIdstringOptional. Identifies a specific agent on the backend.
threadIdstringOptional. Resume an existing conversation thread.
headersRecord<string, string>Optional. Custom request headers (auth, tracing).
telemetryAgentRuntimeTelemetrySink | falseOptional. App-owned sink for runtime lifecycle events.

Use in a component

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

No backend yet?

Use the FakeAgent for offline demos:

import { provideFakeAgent } from '@threadplane/ag-ui';
 
export const appConfig: ApplicationConfig = {
  providers: [
    provideFakeAgent({
      tokens: ['Hello', ' from', ' a', ' fake', ' agent.'],
      reasoningTokens: ['Thinking', ' it', ' over...'],
      delayMs: 60,
    }),
  ],
};

FakeAgent extends AbstractAgent and emits a canned RUN_STARTED -> TEXT_MESSAGE_START -> TEXT_MESSAGE_CONTENT x N -> TEXT_MESSAGE_END -> RUN_FINISHED sequence. It is a drop-in replacement for the ref-less provideAgent({ url }) while you are prototyping.

provideFakeAgent accepts:

OptionTypeDescription
tokensstring[]Optional. Tokens streamed back as the assistant reply.
reasoningTokensstring[]Optional. Reasoning chunks emitted before the text reply (defaults to []).
delayMsnumberOptional. Milliseconds between successive token emissions (defaults to 60).

Custom transport

If you have a backend that speaks AG-UI but not over HTTP, subclass AbstractAgent directly and feed it to toAgent:

import {
  AbstractAgent,
  type RunAgentInput,
  type BaseEvent,
} from '@ag-ui/client';
import { Observable } from 'rxjs';
import { toAgent } from '@threadplane/ag-ui';
 
class MyCustomAgent extends AbstractAgent {
  run(input: RunAgentInput): Observable<BaseEvent> {
    // Your custom transport (WebSocket, in-process worker, etc.)
    // emits BaseEvent events.
    return new Observable<BaseEvent>((observer) => {
      observer.complete();
    });
  }
}
 
const agent = toAgent(new MyCustomAgent());

Looking for something specific?