The Angular Agent Framework for LangChain
agent() is the Angular equivalent of LangGraph's React useStream() hook, built on Angular Signals and the Angular Resource API. It gives enterprise Angular teams production-grade streaming primitives for LangChain. Drop it into any Angular 20+ component, point it at your LangGraph Platform endpoint, and get reactive, signal-driven access to streaming state, messages, tool calls, interrupts, and thread history.
npm install @ngaf/langgraphPeer 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 { agent } from '@ngaf/langgraph';
import type { BaseMessage } from '@langchain/core/messages';
@Component({
selector: 'app-chat',
template: `
<ul>
@for (msg of chat.messages(); track $index) {
<li>{{ msg.content }}</li>
}
</ul>
@if (chat.isLoading()) {
<span>Streaming…</span>
}
<button (click)="send()">Send</button>
`,
})
export class ChatComponent {
chat = agent<{ messages: BaseMessage[] }>({
apiUrl: 'https://your-langgraph-platform.com',
assistantId: 'my-agent',
messagesKey: 'messages',
});
send() {
this.chat.submit({ messages: [{ role: 'human', content: 'Hello' }] });
}
}That's it. chat.messages() is an Angular Signal. Bind it 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() |
— |
| Resource status (idle/loading/resolved/error) | status() — full ResourceStatus |
partial |
| Interrupt / human-in-the-loop | interrupt() / interrupts() |
interrupt / interrupts |
| Tool call progress | toolProgress() |
toolProgress |
| 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() / activeSubagents() / getSubagent() |
subagents / activeSubagents / helper methods |
| Reactive thread switching | Signal<string | null> input |
prop |
| Submit | submit(values, opts?) |
submit(values, opts?) |
| Stop | stop() |
stop() |
| Reload last submission | reload() |
— |
| Custom transport (for testing) | MockStreamTransport |
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.
- Getting Started
- API Reference
- Testing with MockStreamTransport
- Human-in-the-Loop / Interrupts
- 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.