Agent UI primitives and LangGraph streaming adapters for Angular
agent() is the Angular equivalent of LangGraph's React useStream() hook, projected into a runtime-neutral Agent contract consumed by @ngaf/chat. Drop it into any Angular 20+ component, point it at your LangGraph Platform endpoint, and get signal-driven access to messages, status, tool calls, interrupts, subagents, regenerate, and thread history.
npm install @ngaf/langgraph @ngaf/chatPeer dependencies: @angular/core ^20.0.0 || ^21.0.0, @langchain/core ^1.1.0, @langchain/langgraph-sdk ^1.7.0, rxjs ~7.8.0
import { Component } from '@angular/core';
import { ChatComponent as NgafChatComponent } from '@ngaf/chat';
import { agent } from '@ngaf/langgraph';
@Component({
selector: 'app-support-chat',
imports: [NgafChatComponent],
template: `
<chat [agent]="chat" />
@if (chat.isLoading()) {
<span>Streaming…</span>
}
<button (click)="send()">Send</button>
`,
})
export class SupportChatComponent {
chat = agent({
apiUrl: 'https://your-langgraph-platform.com',
assistantId: 'my-agent',
});
send() {
void this.chat.submit({ message: 'Hello' });
}
}That's it. chat.messages() and chat.status() are Angular Signals. Bind them directly in your template — no subscriptions, no async pipe, no zone.js required.
| Feature | agent() (Angular) |
useStream() (React) |
|---|---|---|
| Streaming state as reactive primitives | Angular Signals | React state |
| Messages signal | messages() |
messages |
| Loading state | isLoading() |
isLoading |
| Error state | error() |
— |
| Runtime-neutral status | status() — 'idle' | 'running' | 'error' |
partial |
| Interrupt / human-in-the-loop | interrupt() / interrupts() |
interrupt / interrupts |
| Tool call progress | toolCalls() |
toolCalls |
| Tool calls with results | toolCalls() |
toolCalls |
| Branch / history | branch() / history() / experimentalBranchTree() |
branch / history / experimental_branchTree |
| Pending run queue | queue() |
queue |
| Subagent streaming and lookup helpers | subagents() / getSubagent() |
subagents / helper methods |
| Reactive thread switching | Signal<string | null> input |
prop |
| Submit | submit(values, opts?) |
submit(values, opts?) |
| Stop | stop() |
stop() |
| Regenerate response | regenerate(assistantMessageIndex) |
— |
| Reload last submission | reload() |
— |
| Custom transport (for testing) | MockAgentTransport |
mock fetch |
Angular ResourceRef<T> compatibility |
Full duck-type parity | N/A |
| Angular 20+ Signals API | Native | N/A |
| SSR / Server Components | Client-side only | React Server Components (React) |
agent() creates its internal BehaviorSubjects at injection-context time — once, at component construction. The StreamManager bridge (the only file that touches @langchain/langgraph-sdk internals) pushes stream events into those subjects. toSignal() converts each subject to an Angular Signal, also at construction time. Dynamic actions (submit, stop, switchThread) push into the existing subjects — no new subjects are ever created after construction. This architecture is required because toSignal() must be called in an injection context and cannot be called again later.
- Agent Quickstart
- agent() API
- Chat Introduction
- Human-in-the-Loop / Interrupts
- Subgraph and Subagent Streaming
MIT — free for any use. See LICENSE.
@ngaf/langgraph and all libraries in this repository are released under the MIT License. You are free to use, modify, and distribute them in both commercial and noncommercial projects without restriction.