DocsChatGetting StartedIntroduction

Introduction

@ngaf/chat is the Angular UI component library for building chat interfaces on top of a runtime-neutral Agent contract. It provides a complete 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+.

What you'll learn

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

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). They carry no opinion about layout or styling. Use them when you need full control over how chat elements render.

PrimitiveSelectorPurpose
ChatMessagesComponentchat-messagesIterates 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 include CHAT_THEME_STYLES and CHAT_MARKDOWN_STYLES out of the box.

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-debugFull debug cockpit with timeline, state inspector, and diff viewer
ChatTimelineSliderComponentchat-timeline-sliderSlider-based timeline navigation

How the Stack Fits Together

@ngaf/chat sits between your application and two other Cacheplane libraries:

Your App
  |
  v
@ngaf/chat       <-- UI components (this library)
  |         |
  v         v
@ngaf/langgraph  @ngaf/render
  (streaming state)      (generative UI)
  |
  v
LangGraph Platform
  • @ngaf/langgraph provides the agent() function and returns a LangGraphAgent, which satisfies the Agent contract consumed by @ngaf/chat. It exposes reactive Signals for messages(), isLoading(), error(), interrupt(), toolCalls(), history(), and more.

  • @ngaf/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 @ngaf/render — pass a view registry via the [views] input. The ChatComponent also auto-detects A2UI v0.9 payloads and renders them using a built-in 12-component catalog.

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, interrupt banner, and an optional thread sidebar. 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. Primitives give you building blocks without opinions.

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

What's Next