Page actions

Introduction

@threadplane/chat is the Angular UI component library for building chat interfaces on top of a runtime-neutral Agent contract. It is a set of composable, Signal-driven components that render messages, handle user input, display tool calls, manage interrupts, and support generative UI -- all styled with CSS custom properties and built for Angular 20–22.

Note: What this guide covers

This guide explains the library's two-tier architecture, how it relates to the rest of the Threadplane stack, and when to reach for the all-in-one composition versus assembling primitives yourself.

Build one conversation surface

Imagine a trip planner: the traveler enters a destination, watches an answer arrive, opens a weather result, and changes an itinerary. Start with the composition for the ordinary conversation. Reach for individual primitives when the itinerary, tool result, or approval needs a different place in the page.

The component tree does not own the agent's reasoning loop or persistence. It renders the current conversation and dispatches user actions to the adapter. Follow a conversation explains that boundary from the first request to a saved thread.

How it fits

DiagramHow the Threadplane stack fits together
CHAT UI@threadplane/chat<chat> · <chat-message-list> · <chat-input>Agent contract · signals + events$ADAPTER@threadplane/langgraphADAPTER@threadplane/ag-uiLangGraph PlatformCrewAI · Mastra · Agent Fwk · Strands · …
The chat components consume only the Agent contract — the runtime below is swappable.
Read diagram description

Read from top to bottom. The Angular chat composition and its message-list and input primitives consume one Agent contract: signals plus events$. Two adapters implement that contract. @threadplane/langgraph connects to LangGraph Platform. @threadplane/ag-ui connects to AG-UI backends such as CrewAI, Mastra, Microsoft Agent Framework and AWS Strands. Changing the adapter does not require replacing the chat components.

Two-Tier Architecture

The library is organized into two layers: primitives and compositions.

Primitives

Primitives are low-level, headless components that read from an Agent and expose their state through content projection (ng-template). Template primitives let you provide the rendered content. Other primitives, including the input and tool-call controls, include their own interaction and styling. Compose the pieces when you need control over the surrounding layout or message presentation.

PrimitiveSelectorPurpose
ChatMessageListComponentchat-message-listIterates messages and renders via template directives
MessageTemplateDirectiveng-template[chatMessageTemplate]Declares a template for a specific message type
ChatInputComponentchat-inputText input with submit handling and keyboard shortcuts
ChatTypingIndicatorComponentchat-typing-indicatorAnimated dots shown while the agent is streaming
ChatErrorComponentchat-errorDisplays error messages from the agent
ChatInterruptComponentchat-interruptProjects interrupt content via a template
ChatToolCallsComponentchat-tool-callsIterates tool calls and projects each via a template
ChatSubagentsComponentchat-subagentsIterates active subagent streams via a template
ChatThreadListComponentchat-thread-listRenders a list of conversation threads
ChatTimelineComponentchat-timelineIterates checkpoint history via a template

Compositions

Compositions are opinionated, styled components that combine primitives into ready-to-use UI blocks. They apply the --tplane-chat-* token system automatically and include markdown styling where needed.

CompositionSelectorPurpose
ChatComponentchatFull chat UI with messages, input, typing indicator, error, and thread sidebar
ChatInterruptPanelComponentchat-interrupt-panelStyled interrupt card with accept/edit/respond/ignore actions
ChatToolCallCardComponentchat-tool-call-cardExpandable card showing tool name, inputs, and output
ChatSubagentCardComponentchat-subagent-cardExpandable card showing subagent status and messages
ChatDebugComponentchat-debugDebug panel from @threadplane/chat/debug with timeline, state inspector, and diff viewer
ChatTimelineSliderComponentchat-timeline-sliderSlider-based timeline navigation

How the Stack Fits Together

@threadplane/chat sits between your application and the adapters below the Agent-contract seam shown above; alongside it, @threadplane/render turns specs in assistant messages into your components.

  • @threadplane/langgraph provides provideAgent() and injectAgent() returning a LangGraphAgent, which satisfies the Agent contract consumed by @threadplane/chat. The base Agent contract exposes reactive Signals for messages(), status(), isLoading(), error(), toolCalls(), and state(), plus optional interrupt() and subagents(). Adapters can layer on more: LangGraph implements AgentWithHistory, adding history() for checkpoint time-travel.

  • @threadplane/render provides RenderSpecComponent and view registries for rendering JSON UI specs as Angular components. The ChatComponent auto-detects JSON specs in AI messages and renders them through @threadplane/render - pass a view registry via the [views] input. The same [views] input enables A2UI rendering with a2uiBasicCatalog(), which currently maps 18 component types.

When to Use ChatComponent vs. Custom Assembly

Use ChatComponent when you want a complete, styled chat interface with minimal setup. It includes message rendering (with markdown), a text input, typing indicator, error display, and an optional thread sidebar. Interrupt UI is not part of it — compose <chat-interrupt-panel> yourself when your runtime pauses for input. Drop it in, pass an Agent, and you have a working chat.

<chat [agent]="chatRef" />

Assemble primitives when you need to customize layout, add components between sections, change the message rendering logic, or integrate chat into a larger dashboard. Choose headless template primitives where you need custom markup, and styled primitives where their interaction matches your product.

<chat-message-list [agent]="chatRef">
  <ng-template chatMessageTemplate="human" let-message>
    <!-- your custom user message layout -->
  </ng-template>
  <ng-template chatMessageTemplate="ai" let-message>
    <!-- your custom assistant message layout -->
  </ng-template>
</chat-message-list>
 
<chat-input [agent]="chatRef" placeholder="Ask anything..." />

What's Next

Installation

Install the package, check the peer dependencies, and register an adapter.

Quick Start

Get a working chat UI running in under 5 minutes.

Theming

Customize colors, fonts, and spacing with CSS custom properties.

Lifecycle Signals

Subscribe to per-instance lifecycle signals via CHAT_LIFECYCLE.

Looking for something specific?