Quick Start
Send a trip-planning question and render the answer as it arrives. This walkthrough connects an Angular component to a LangGraph server, then explains what changes during the first turn. For the full path from a message to tools and saved state, start with Follow a conversation.
Angular 20–22 project using a Node.js version supported by that Angular major. If you need setup help, see the Installation guide.
Try without a backend renders the same <chat> with a fake agent — no server, no key.
npm install @threadplane/langgraph @threadplane/chat @langchain/core @langchain/langgraph-sdknpm 7 and newer install peer dependencies automatically, so this command also brings in @threadplane/telemetry and the peers @threadplane/chat declares — @threadplane/render, @threadplane/a2ui, zod, @json-render/core, and marked. Listing the LangChain peers explicitly keeps stricter package managers quiet; the full contract is in the Installation guide.
Add provideAgent() to your application config with your LangGraph Platform URL and assistant id.
// app.config.ts
import type { ApplicationConfig } from '@angular/core';
import { provideAgent } from '@threadplane/langgraph';
export const appConfig: ApplicationConfig = {
providers: [
provideAgent({
apiUrl: 'http://localhost:2024',
// 'chat' maps to the key in your langgraph.json "graphs" config
assistantId: 'chat',
}),
],
};Persisting a threadId so conversations survive a page refresh is opt-in — leave it out for the minimal path and add it later. See Persistence.
Now wire up the UI. Call injectAgent() in a component field initializer — read its state through Angular Signals and call its methods to submit or stop a run.
// chat.component.ts
import { Component, ChangeDetectionStrategy, signal, computed } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { messageContent } from '@threadplane/chat';
import { injectAgent } from '@threadplane/langgraph';
@Component({
selector: 'app-chat',
standalone: true,
imports: [FormsModule],
templateUrl: './chat.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ChatComponent {
input = signal('');
protected readonly messageContent = messageContent;
protected readonly chat = injectAgent();
isStreaming = computed(() => this.chat.isLoading());
send() {
const msg = this.input();
if (!msg.trim() || this.chat.isLoading()) return;
this.chat.submit({ message: msg });
this.input.set('');
}
}Make sure your LangGraph agent is running at the URL you configured.
langgraph devng serveOpen http://localhost:4200 and start chatting with your agent.
Follow the first turn
Type “Plan a weekend in Portland” and press Send. The component passes one new user message to submit; it does not replace the transcript. While the backend runs, isLoading() disables another submission and messages() updates as text arrives. messageContent() extracts display text from either supported content shape.
The signal named input holds only the unsent draft. The adapter owns the observed messages. Keeping them separate lets the user type another draft without changing the answer in progress. This small template renders plain text; use the chat composition for Markdown, tool calls, and the standard controls.
- Person → ApplicationAsk for a three-day trip plan.This starts one user turn.
- Application → RuntimeSubmit a message on a confirmed thread.The adapter starts an agent run.
- Runtime → Model / toolsPlan, look up information and continue.One turn can contain several model and tool calls.
- Runtime → Threadplane → UIStream message and state updates.The response is built incrementally; a chunk is not a new turn.
- Runtime → StorageSave state when the backend supports it.LangGraph checkpoints belong to the thread.
- Threadplane → ApplicationShow the final answer and settled status.The next user message starts the next turn.
Read diagram description
Read top to bottom. A person asks for a trip plan. The application submits their message to a confirmed thread. An agent run can invoke a model and tools more than once. Threadplane observes streamed message and state events and the UI updates as they arrive. Persistence depends on the backend: LangGraph can save checkpoints during execution; the AG-UI protocol alone does not provide storage. When the run settles, the UI shows the answer. The next user message starts another turn; a tool result or streamed token does not.
Typed state via AgentRef
By default, injectAgent() returns an agent typed as Record<string, unknown>. Create a typed ref at module scope and pass the same ref to the provider and inject helper to carry your graph's state shape through Angular DI:
import { createAgentRef } from '@threadplane/chat';
import { provideAgent, injectAgent } from '@threadplane/langgraph';
interface TripState {
day: number;
places: string[];
}
export const TRIP = createAgentRef<TripState>('trip');
// app.config.ts providers
provideAgent(TRIP, {
apiUrl: 'http://localhost:2024',
assistantId: 'chat',
});
// In a component field initializer or another Angular injection context:
const agent = injectAgent(TRIP); // LangGraphAgent<TripState>
agent.state().places; // string[]The optional ref name appears in Angular DI error messages. The ref comes from @threadplane/chat, so the same typed handle can be used with either adapter. See the generated provideAgent() reference for its overloads.
Next steps
Skip the hand-rolled template — render this agent with <chat [agent]> from @threadplane/chat.
Learn about token-by-token updates and stream modes
Keep conversations alive across page refreshes
Add human-in-the-loop approval flows
Deep dive into how Signals power agent
Graphs, nodes, edges, and state for Angular developers
Complete injectAgent() function reference