Open-source ยท Angular ยท LangGraph & AG-UI

The AI agent UI framework for Angular.

Chat, threads, approvals, and generative UI on Signals and DI. Your backend stays where it is.

demo.threadplane.ai/hero
Threadplane chat replaying a recorded LangGraph run: a user prompt, a request_approval tool call, and the streamed three-step cleanup plan

MIT ยท Angular 20โ€“22 ยท no account, no cloud

Works withOpenAIAnthropicGeminiBedrockLangGraphAG-UICrewAIMastra+ 4 more

Reliable to the core

Audited, scored, published.

Not self-reported โ€” every number links to its source.

Runtime parity

One Angular UI. Two runtime adapters. The same contract.

@threadplane/chat consumes Agent, not LangGraphAgent or an AG-UI client. Swap the adapter without rewriting the Angular component tree.

What changes app.config.ts

import { ApplicationConfig } from '@angular/core';
import { provideAgent } from '@threadplane/langgraph';

export const appConfig: ApplicationConfig = {
  providers: [
    provideAgent({ apiUrl: 'http://localhost:2024', assistantId: 'agent' }),
  ],
};

What does not same in both

import { Component } from '@angular/core';
import { ChatComponent, type Agent } from '@threadplane/chat';

@Component({
  imports: [ChatComponent],
  template: `<chat [agent]="agent" />`,
})
export class SupportAgentComponent {
  // injectAgent() comes from the adapter you chose above;
  // the component only depends on the runtime-neutral Agent contract.
  protected readonly agent: Agent = injectAgent();
}

Not every backend emits every capability. Interrupts, subagents and checkpoints depend on what the runtime sends. Choose an adapter โ†’

How it works

From agent endpoint to Angular UI in three steps.

  1. Choose an adapter

    Connect LangGraph or an AG-UI endpoint, or start with a fake agent. This is the only file that knows which runtime you run.

    import { ApplicationConfig } from '@angular/core';
    import { provideAgent } from '@threadplane/langgraph';
    
    export const appConfig: ApplicationConfig = {
      providers: [
        provideAgent({ apiUrl: 'http://localhost:2024', assistantId: 'agent' }),
      ],
    };
  2. Inject signal-shaped state

    provideAgent() once, injectAgent() where the UI needs messages, status, errors, tool progress and thread actions.

    import { Component } from '@angular/core';
    import { injectAgent } from '@threadplane/langgraph';
    import { ChatComponent } from '@threadplane/chat';
    
    @Component({
      imports: [ChatComponent],
      template: `<chat [agent]="agent" />`,
    })
    export class SupportAgentComponent {
      protected readonly agent = injectAgent();
    }
  3. Render the experience you own

    Use the chat compositions, the headless primitives, or register your own design-system components for generated UI.

    import { ApplicationConfig } from '@angular/core';
    import { provideViews, views } from '@threadplane/render';
    import { KpiCardComponent } from './kpi-card.component';
    import { DisruptionsTableComponent } from './disruptions-table.component';
    
    export const appConfig: ApplicationConfig = {
      providers: [
        // Generated UI can render these components and nothing else.
        provideViews(views({
          KpiCard: KpiCardComponent,
          DisruptionsTable: DisruptionsTableComponent,
        })),
      ],
    };

Stream

The UI stays reactive through tokens, tools, errors, and state changes.

injectAgent() hands back signals: messages(), status(), error(), isLoading(), and tool progress. Nothing to subscribe to, nothing to tear down.

Signals, not promisesinjectAgent()
Tool progress as it happenstoolProgress()
Same contract on LangGraph and AG-UIAgent
Read the streaming guide โ†’
demo.threadplane.ai

Persist

A user can leave, return, inspect history, and continue.

Thread selection, history, branch and replay UI in the Angular app. Durability itself comes from the runtime and persistence layer you connect โ€” Threadplane exposes it, it does not fake it.

Conversations restore across sessionsthreadId + checkpoints
Branch or replay from any pointbranch / replay
error() / status() / reload() on every agentboundary signals
Persistence patterns โ†’
demo.threadplane.ai

Approve

Irreversible work pauses for a human decision.

interrupt() freezes the run inside the checkpoint. Your UI renders the proposal; submit({ resume }) continues with the decision on the record.

The pause is a checkpoint, not a modalinterrupt()
The proposal renders in your UI<chat-interrupt-panel>
The decision lands beside the action it gatedsubmit({ resume })
Interrupt patterns โ†’
demo.threadplane.ai

Render

Agent output becomes components from your design system.

The agent emits constrained structured output. Angular renders registered components โ€” json-render and A2UI both speak it โ€” with per-component fallback and a readiness gate. No generated code runs.

Your design system, not a chat widget@threadplane/render
Unknown specs degrade per componentfallback + readiness gate
Schema on the server, trust in the clientvalidated specs
See @threadplane/render โ†’
demo.threadplane.ai

Test

Verify UI behavior without a model or backend.

provideFakeAgent() streams canned tokens in-process; mock transports script tool calls and interrupts. Your component specs stay deterministic and fast.

No key, no server, no networkprovideFakeAgent()
Script tool calls and interruptsmockLangGraphAgent()
Same UI code in test and productionAgent
Try without a backend โ†’
import { TestBed } from '@angular/core/testing';
import { provideFakeAgent } from '@threadplane/langgraph';
import { SupportAgentComponent } from './support-agent.component';

it('renders the streamed reply', async () => {
  TestBed.configureTestingModule({
    imports: [SupportAgentComponent],
    providers: [provideFakeAgent({ tokens: ['Hello', ' from', ' Threadplane'], delayMs: 0 })],
  });
  const fixture = TestBed.createComponent(SupportAgentComponent);
  fixture.detectChanges();

  const textarea: HTMLTextAreaElement = fixture.nativeElement.querySelector('textarea');
  textarea.value = 'What can Threadplane do?';
  textarea.dispatchEvent(new Event('input'));
  fixture.detectChanges();

  const send: HTMLButtonElement = fixture.nativeElement.querySelector('button[aria-label="Send message"]');
  send.click();

  await fixture.whenStable();
  fixture.detectChanges();

  expect(fixture.nativeElement.textContent).toContain('Hello from Threadplane');
});

See it running

One chat UI. Two runtimes. Same code.

The identical Threadplane chat surface, running live against a LangGraph backend and an AG-UI backend. Switch tabs to compare โ€” the front end never changes.

demo.threadplane.ai

Video loops instantly ยท click Launch to open the live, interactive demo ยท no signup

For coding agents

Give your coding agent the Angular agent UI playbook.

Threadplane publishes maintained, machine-readable setup context. Start with a fake agent, verify the Angular surface, then connect LangGraph or AG-UI.

Add Threadplane to this Angular application.

1. Read https://threadplane.ai/AGENTS.md and the current Threadplane quickstart.
2. Inspect this repository's Angular version, application configuration, design
   system, test runner, and existing agent/backend code.
3. Begin with Threadplane's provideFakeAgent() path so the UI can be verified
   without a server or LLM.
4. Render the smallest accessible <chat> experience using the app's existing
   layout and styles.
5. Add a focused test for the integration.
6. After the fake path passes, explain the exact configuration needed for
   either LangGraph or AG-UI. Do not invent credentials, endpoint URLs, or
   backend capabilities.
7. Run the repository's relevant lint, test, and build commands and report
   every changed file.

Why Threadplane

What you start with, and what Threadplane adds.

Starting pointWhat it gives youWhat Threadplane adds
Raw SSE or stream SDKTransport and eventsAngular state model, chat UX, threads, approvals, generated UI, recovery, tests
Backend agent frameworkAgent runtime and orchestrationThe production Angular application and interaction layer
Generative-UI rendererStructured UI renderingFull agent UI, adapters, thread UX, interrupts, testing, and render support
React-first agent UIMature React patternsNative Angular Signals, DI, templates, components, and testing

Field report

The last-mile gap in Angular AI.

Six production-readiness dimensions

18 pages

Error boundaries, fallbacks, observability, deploy

concrete patterns

No vendor pitch โ€” what we learned shipping it

free

Send me the guide and a short, three-email follow-up from Brian about building with Threadplane. Unsubscribe anytime.

Already on the list? Download the PDF directly.

For teams

Shipping inside a large Angular platform?

Bring your backend, security model, and design system. Work directly with Threadplane engineers on architecture, rollout, testing, and production hardening.

A working agent demo on your domain

your data

Hardened error, fallback, observability patterns

production-ready

Deploy-ready integration

your CI/CD

Team trained on the framework

runbook, yours

Discover
Map your stack, surfaces, and the agentic work that earns its keep.
Build
A working demo on your real data, in your real app.
Harden
Observability, error boundaries, deploy paths, on-call patterns.
Train
Your team owns the stack. We leave you with a runbook, not a black box.

Questions

Frequently asked questions.

Is Threadplane a backend agent framework?
No. Threadplane is the Angular UI layer. Your agent runs in LangGraph, in an AG-UI-compatible runtime, or in your own service. Choosing an adapter
Does Threadplane require LangGraph?
No. @threadplane/ag-ui connects any AG-UI-compatible backend, and @threadplane/langgraph is the direct LangGraph adapter. AG-UI on Threadplane
What is the difference between the LangGraph and AG-UI adapters?
Both implement the same Agent contract. LangGraph adds native threads, checkpoints, history, and branch mapping; AG-UI maps the protocol's events and depends on what the backend emits. Choosing an adapter
Where are threads and checkpoints stored?
In your backend's persistence layer. Threadplane exposes thread, history, and resume behavior in the UI; durability comes from the runtime you operate. Persistence guide
Can I use my existing Angular component library and design system?
Yes. The chat compositions are stylable, the primitives are headless, and generated UI renders components you register. Generated UI
Does generated UI execute arbitrary code?
No. The agent emits constrained structured output that is validated against a schema, and Angular renders registered components with a per-component fallback. json-render and A2UI
Can I test the UI without a model or a live backend?
Yes. provideFakeAgent() streams canned tokens in-process, and mock transports script tool calls and interrupts. Try it without a backend
Which Angular versions are supported?
Threadplane supports Angular 20โ€“22. The installation guide lists the peer ranges for every package. Installation
Does Threadplane require a hosted service or an account?
No. Every package is MIT and runs inside your Angular application against a backend you host. Pricing
What does Threadplane report about my application?
Operational facts about how the product is running โ€” activity, not content. Prompts, messages, tool inputs and outputs, application state, and source code are outside what that reporting is designed to carry. Privacy policy
How does Threadplane differ from a raw streaming SDK?
A streaming SDK gives you events. Threadplane gives you the Angular state model, chat UX, threads, approvals, generated UI, recovery, and tests on top of them. Chat
How does Threadplane compare with other Angular agent UI libraries?
Threadplane is the runtime-neutral Angular UI layer: direct LangGraph and AG-UI adapters, a fake-agent test path, design-system-owned generated UI, and no hosted layer in the loop. A dated, sourced comparison page is planned. Choosing an adapter

Prove the Angular UI before you connect the backend.

Start with a fake agent, render a real Threadplane surface, then swap in LangGraph or AG-UI when the integration is ready.

MIT ยท no account, no cloud ยท Talk to an engineer

Blog

Recent articles