diff --git a/apps/website/content/docs/ag-ui/getting-started/installation.mdx b/apps/website/content/docs/ag-ui/getting-started/installation.mdx
new file mode 100644
index 000000000..9eec4990b
--- /dev/null
+++ b/apps/website/content/docs/ag-ui/getting-started/installation.mdx
@@ -0,0 +1,97 @@
+# Installation
+
+## Prerequisites
+
+- Angular 20 or later
+- Node.js 22+
+- An AG-UI-compatible backend running locally or remotely (CrewAI, Mastra, Microsoft Agent Framework, AG2, Pydantic AI, AWS Strands, CopilotKit runtime, or your own subclass of `AbstractAgent`)
+
+## Install packages
+
+```bash
+npm install @ngaf/chat @ngaf/ag-ui
+```
+
+`@ngaf/chat` provides the chat UI primitives. `@ngaf/ag-ui` provides the adapter that wires an AG-UI backend into the `Agent` contract those primitives consume.
+
+## Configure the provider
+
+In your app config:
+
+```ts
+import { ApplicationConfig } from '@angular/core';
+import { provideAgUiAgent } from '@ngaf/ag-ui';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideAgUiAgent({
+ url: 'http://localhost:3000/agent', // your AG-UI backend
+ }),
+ ],
+};
+```
+
+`provideAgUiAgent` accepts:
+
+| Option | Type | Description |
+|---|---|---|
+| `url` | `string` | **Required.** AG-UI backend HTTP/SSE endpoint. |
+| `agentId` | `string` | Optional. Identifies a specific agent on the backend. |
+| `threadId` | `string` | Optional. Resume an existing conversation thread. |
+| `headers` | `Record` | Optional. Custom request headers (auth, tracing). |
+
+## Use in a component
+
+```ts
+import { Component, inject } from '@angular/core';
+import { ChatComponent } from '@ngaf/chat';
+import { AG_UI_AGENT } from '@ngaf/ag-ui';
+
+@Component({
+ selector: 'app-streaming',
+ standalone: true,
+ imports: [ChatComponent],
+ template: ``,
+})
+export class StreamingComponent {
+ protected readonly agent = inject(AG_UI_AGENT);
+}
+```
+
+## No backend yet?
+
+Use the `FakeAgent` for offline demos:
+
+```ts
+import { provideFakeAgUiAgent } from '@ngaf/ag-ui';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideFakeAgUiAgent({
+ tokens: ['Hello', ' from', ' a', ' fake', ' agent.'],
+ delayMs: 60,
+ }),
+ ],
+};
+```
+
+`FakeAgent` extends `AbstractAgent` and emits a canned `RUN_STARTED → TEXT_MESSAGE_START → TEXT_MESSAGE_CONTENT × N → TEXT_MESSAGE_END → RUN_FINISHED` sequence. Drop-in replacement for `provideAgUiAgent({ url })` while you're prototyping.
+
+## Custom transport
+
+If you have a backend that speaks AG-UI but not over HTTP, subclass `AbstractAgent` directly and feed it to `toAgent`:
+
+```ts
+import { AbstractAgent, type RunAgentInput, type BaseEvent } from '@ag-ui/client';
+import { Observable } from 'rxjs';
+import { toAgent } from '@ngaf/ag-ui';
+
+class MyCustomAgent extends AbstractAgent {
+ protected run(input: RunAgentInput): Observable {
+ // Your custom transport (WebSocket, in-process worker, etc.)
+ // emits BaseEvent events.
+ }
+}
+
+const agent = toAgent(new MyCustomAgent());
+```
diff --git a/apps/website/content/docs/ag-ui/getting-started/introduction.mdx b/apps/website/content/docs/ag-ui/getting-started/introduction.mdx
new file mode 100644
index 000000000..c75891d14
--- /dev/null
+++ b/apps/website/content/docs/ag-ui/getting-started/introduction.mdx
@@ -0,0 +1,52 @@
+# Introduction
+
+`@ngaf/ag-ui` is the runtime adapter that wraps an [AG-UI](https://github.com/ag-ui-protocol/ag-ui) `AbstractAgent` into the runtime-neutral `Agent` contract from `@ngaf/chat`. The chat UI primitives consume the Agent contract; the AG-UI adapter translates between the contract and the AG-UI event protocol.
+
+
+AG-UI is the open agent-to-UI protocol from the CopilotKit ecosystem. It standardizes how agent runtimes stream events (messages, tool calls, state updates) to a frontend. Used by **CrewAI**, **Mastra**, **Microsoft Agent Framework**, **AG2**, **Pydantic AI**, **AWS Strands**, and the **CopilotKit runtime**. One adapter unlocks all of them.
+
+
+## How it fits
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│ @ngaf/chat (UI primitives — runtime-neutral) │
+│ , , , , … │
+└─────────────────────────┬───────────────────────────────────┘
+ │ Agent contract (signals + events$)
+ │
+ ┌───────────┴───────────┐
+ ▼ ▼
+ @ngaf/langgraph @ngaf/ag-ui
+ (toAgent: AgentRef→Agent) (toAgent: AbstractAgent→Agent)
+ │ │
+ ▼ ▼
+ LangGraph Platform Any AG-UI backend
+ (CrewAI, Mastra, MS AF,
+ CopilotKit runtime, …)
+```
+
+## What you get
+
+- **`toAgent(source: AbstractAgent): Agent`** — wraps any `AbstractAgent` subclass (custom transports, mocks).
+- **`provideAgUiAgent({ url })`** — DI convenience that instantiates `HttpAgent` under the hood for the common SSE/HTTP case.
+- **`FakeAgent`** — in-process `AbstractAgent` subclass that emits canned streaming events for offline demos and tests.
+
+## What's covered
+
+Scope of the first release:
+- `messages` (streaming token deltas via `TEXT_MESSAGE_*` events)
+- `status` / `isLoading` / `error` (lifecycle via `RUN_STARTED/FINISHED/ERROR`)
+- `toolCalls` (streaming tool calls via `TOOL_CALL_*` events)
+- `state` (snapshots and JSON-Patch deltas)
+- `events$` (custom events; discriminates `state_update`)
+
+Out of scope for now (use `@ngaf/langgraph` if you need these):
+- Interrupts
+- Subagents
+- History / time-travel
+
+## Next steps
+
+- [Quick Start](/docs/ag-ui/getting-started/quickstart) — bind `` to an AG-UI backend in 5 minutes.
+- [Installation](/docs/ag-ui/getting-started/installation) — npm install + provider setup.
diff --git a/apps/website/content/docs/ag-ui/getting-started/quickstart.mdx b/apps/website/content/docs/ag-ui/getting-started/quickstart.mdx
new file mode 100644
index 000000000..ad2035668
--- /dev/null
+++ b/apps/website/content/docs/ag-ui/getting-started/quickstart.mdx
@@ -0,0 +1,71 @@
+# Quick Start
+
+Bind `` from `@ngaf/chat` to an AG-UI backend in 5 minutes.
+
+
+Angular 20+ project with Node.js 22+. If you need setup help, see the [Installation](/docs/ag-ui/getting-started/installation) guide.
+
+
+
+
+
+```bash
+npm install @ngaf/chat @ngaf/ag-ui
+```
+
+
+
+
+Add `provideAgUiAgent()` to your application config with your AG-UI backend URL.
+
+```ts
+// app.config.ts
+import { ApplicationConfig } from '@angular/core';
+import { provideAgUiAgent } from '@ngaf/ag-ui';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideAgUiAgent({ url: 'http://localhost:3000/agent' }),
+ ],
+};
+```
+
+For offline development without a backend, swap to `provideFakeAgUiAgent({})` — it serves canned streaming responses for UI work.
+
+
+
+
+```ts
+import { Component, inject } from '@angular/core';
+import { ChatComponent } from '@ngaf/chat';
+import { AG_UI_AGENT } from '@ngaf/ag-ui';
+
+@Component({
+ selector: 'app-streaming',
+ standalone: true,
+ imports: [ChatComponent],
+ template: ``,
+})
+export class StreamingComponent {
+ protected readonly agent = inject(AG_UI_AGENT);
+}
+```
+
+That's it. The `` composition handles streaming messages, tool calls, errors, and submit — all bound to the AG-UI backend through the `Agent` contract.
+
+
+
+
+## What to read next
+
+- The [`@ngaf/chat` Components](/docs/chat/components/chat) reference covers the primitives the `` composition uses internally — handy if you want to compose your own layout.
+- Looking for LangGraph instead of AG-UI? See [`@ngaf/langgraph`](/docs/agent/getting-started/quickstart).
+
+## Switching backends without changing UI
+
+The point of the runtime-neutral `Agent` contract is that swapping backends is a one-line change in `app.config.ts`. The component code stays the same:
+
+```diff
+- providers: [provideAgent({ apiUrl: '...' })], // LangGraph
++ providers: [provideAgUiAgent({ url: '...' })], // AG-UI
+```
diff --git a/apps/website/e2e/website.spec.ts b/apps/website/e2e/website.spec.ts
index b0f79690a..d4d20142a 100644
--- a/apps/website/e2e/website.spec.ts
+++ b/apps/website/e2e/website.spec.ts
@@ -14,14 +14,12 @@ test('landing page renders architecture section', async ({ page }) => {
test('landing page renders libraries section', async ({ page }) => {
await page.goto('/');
- await expect(page.getByText('Three libraries. One architecture.').first()).toBeVisible();
+ await expect(page.getByText('Four libraries. One architecture.').first()).toBeVisible();
});
-test('pricing page shows 4 plan cards', async ({ page }) => {
+test('pricing page shows plan cards', async ({ page }) => {
await page.goto('/pricing');
- await expect(page.getByText('Community').first()).toBeVisible();
- await expect(page.getByText('Developer Seat').first()).toBeVisible();
- await expect(page.getByText('App Deployment').first()).toBeVisible();
+ await expect(page.getByText('Open Source').first()).toBeVisible();
await expect(page.getByText('Enterprise').first()).toBeVisible();
});
@@ -42,6 +40,7 @@ test('docs landing page shows library cards', async ({ page }) => {
await expect(page.getByText('Agent').first()).toBeVisible();
await expect(page.getByText('Render').first()).toBeVisible();
await expect(page.getByText('Chat').first()).toBeVisible();
+ await expect(page.getByText('AG-UI').first()).toBeVisible();
});
test('api reference renders in docs', async ({ page }) => {
diff --git a/apps/website/src/app/api/email-preview/route.ts b/apps/website/src/app/api/email-preview/route.ts
index ca2f5f712..f0a51e98f 100644
--- a/apps/website/src/app/api/email-preview/route.ts
+++ b/apps/website/src/app/api/email-preview/route.ts
@@ -22,9 +22,9 @@ const TEMPLATES: Record { subject: string; html: string }> = {
'lead-notification': () => ({
subject: 'New lead: Brian at Cacheplane',
html: leadNotificationHtml({
- name: 'Brian Love',
- email: 'brian@cacheplane.io',
- company: 'Cacheplane',
+ name: 'Sample Lead',
+ email: 'demo@example.com',
+ company: 'Example Corp',
message: 'Interested in the pilot program for our Angular + LangGraph project.',
ts: new Date().toISOString(),
}),
diff --git a/apps/website/src/app/llms-full.txt/route.ts b/apps/website/src/app/llms-full.txt/route.ts
index 08de188b1..a324347b5 100644
--- a/apps/website/src/app/llms-full.txt/route.ts
+++ b/apps/website/src/app/llms-full.txt/route.ts
@@ -38,12 +38,6 @@ export async function GET() {
'Do not mock agent() in tests — use MockAgentTransport.',
'RxJS is an internal implementation detail — do not import rxjs in consumer code.',
].join('\n'),
- [
- '## MCP server',
- '',
- 'npx @ngaf/langgraph-mcp',
- 'Add to Claude Code settings.json, Cursor .cursor/mcp.json, or any MCP-compatible agent.',
- ].join('\n'),
];
return new NextResponse(sections.join('\n\n---\n\n'), {
diff --git a/apps/website/src/app/llms.txt/route.ts b/apps/website/src/app/llms.txt/route.ts
index 50b3f1b8f..a0f2a63bf 100644
--- a/apps/website/src/app/llms.txt/route.ts
+++ b/apps/website/src/app/llms.txt/route.ts
@@ -2,33 +2,51 @@ import { NextResponse } from 'next/server';
// Build compact LLMs summary at request time so version is always current
function buildLlmsTxt(): string {
- // Inline version — updated by publish workflow
- const version = '0.1.0';
+ // Inline version — bump on each release
+ const version = '0.0.1';
return [
`# Angular Agent Framework v${version}`,
'',
- "Angular Agent Framework — the enterprise streaming library for LangChain/LangGraph. Provides agent() — full parity with React's useStream() hook, built on Angular Signals.",
+ "Angular Agent Framework is a runtime-neutral chat UI SDK for Angular. The @ngaf/chat library provides streaming chat primitives bound to a runtime-neutral 'Agent' contract; runtime adapters (@ngaf/langgraph, @ngaf/ag-ui) translate between the contract and the actual backend.",
+ '',
+ '## Packages',
+ '- @ngaf/chat — chat UI primitives (messages, input, tool calls, interrupt, debug, etc.) consuming the Agent contract',
+ '- @ngaf/langgraph — adapter for LangGraph / LangGraph Platform',
+ '- @ngaf/ag-ui — adapter for any AG-UI-compatible backend (CrewAI, Mastra, Microsoft AF, AG2, Pydantic AI, AWS Strands, CopilotKit runtime)',
+ '- @ngaf/render — generative UI runtime (Vercel json-render + Google A2UI)',
+ '- @ngaf/a2ui — A2UI catalog components',
+ '- @ngaf/partial-json — streaming JSON parser',
+ '- @ngaf/licensing — license verification client',
'',
'## Install',
- 'npm install @ngaf/langgraph',
- '',
- '## Key API',
- '- agent(options): AgentRef — call in Angular injection context (constructor or field initializer)',
- '- provideAgent(config): Provider — register in app.config.ts for global defaults',
- "- AgentRef.messages(): Signal — updates token by token",
- '- AgentRef.submit(values): Promise — send a message / trigger a run',
- "- AgentRef.status(): Signal<'idle'|'loading'|'resolved'|'error'>",
- '- AgentRef.threadId signal + onThreadId callback — thread persistence across refreshes',
- '- MockAgentTransport — deterministic unit testing without a real server',
- '',
- '## Minimal example',
- "import { agent } from '@ngaf/langgraph';",
- "const chat = agent({ assistantId: 'chat_agent', apiUrl: 'http://localhost:2024' });",
- '// Template: @for (msg of chat.messages(); track $index) { {{ msg.content }}
}',
- "// Submit: chat.submit({ messages: [{ role: 'human', content: input }] })",
- '',
- '## MCP server',
- 'npx @ngaf/langgraph-mcp',
+ '# LangGraph backend:',
+ 'npm install @ngaf/chat @ngaf/langgraph',
+ '# AG-UI backend:',
+ 'npm install @ngaf/chat @ngaf/ag-ui',
+ '',
+ '## Key API (chat library)',
+ '- Agent — runtime-neutral contract with messages/status/isLoading/error/toolCalls/state signals + events$ observable + submit/stop methods',
+ '- ChatComponent, ChatMessagesComponent, ChatInputComponent — composable Angular components consuming Agent',
+ '- mockAgent — testing utility with a writable signal-backed Agent',
+ '- runAgentConformance / runAgentWithHistoryConformance — conformance suites for adapter authors',
+ '',
+ '## Minimal LangGraph example',
+ "import { agent, toAgent } from '@ngaf/langgraph';",
+ "import { ChatComponent } from '@ngaf/chat';",
+ '// In a component:',
+ "stream = agent({ apiUrl: 'http://localhost:2024', assistantId: 'chat_agent' });",
+ 'chatAgent = toAgent(this.stream);',
+ '// Template: ',
+ '',
+ '## Minimal AG-UI example',
+ "import { provideAgUiAgent, AG_UI_AGENT } from '@ngaf/ag-ui';",
+ "import { ChatComponent } from '@ngaf/chat';",
+ "// app.config.ts: providers: [provideAgUiAgent({ url: 'https://your.endpoint' })]",
+ "// Component: agent = inject(AG_UI_AGENT);",
+ '// Template: ',
+ '',
+ '## License',
+ 'MIT — free for any use, commercial or noncommercial.',
'',
'## Full reference',
'https://cacheplane.ai/llms-full.txt',
diff --git a/apps/website/src/components/landing/HeroTwoCol.tsx b/apps/website/src/components/landing/HeroTwoCol.tsx
index 7a8c0d26f..9e9289a12 100644
--- a/apps/website/src/components/landing/HeroTwoCol.tsx
+++ b/apps/website/src/components/landing/HeroTwoCol.tsx
@@ -2,7 +2,7 @@ import { GenerativeUIFrame } from './GenerativeUIFrame';
import { CopyPromptButton } from '../docs/CopyPromptButton';
import { tokens } from '@ngaf/design-tokens';
-const SETUP_SNIPPET = 'npm install @ngaf/langgraph\n\n// app.config.ts\nprovideAgent({ apiUrl: \'http://localhost:2024\' })';
+const SETUP_SNIPPET = 'npm install @ngaf/chat @ngaf/langgraph\n\n// app.config.ts\nprovideAgent({ apiUrl: \'http://localhost:2024\' })\n\n// or with @ngaf/ag-ui:\nprovideAgUiAgent({ url: \'http://localhost:3000/agent\' })';
function LangChainBadge() {
return (
@@ -25,6 +25,27 @@ function LangChainBadge() {
);
}
+function AgUiBadge() {
+ return (
+
+ AG
+ AG-UI
+
+ );
+}
+
function AngularBadge() {
return (
@@ -86,7 +108,7 @@ export async function HeroTwoCol() {
margin: 0,
marginBottom: 20,
}}>
- The Enterprise Agent Framework for LangChain and{' '}
+ The Enterprise Agent Framework for{' '}
Angular
@@ -100,7 +122,7 @@ export async function HeroTwoCol() {
margin: 0,
marginBottom: 32,
}}>
- Signal-native streaming for LangGraph — production patterns your Angular team can own.
+ Signal-native chat UI for any agent runtime — LangGraph, AG-UI, or your own backend.
@@ -110,7 +132,7 @@ export async function HeroTwoCol() {
fontSize: 12,
color: tokens.colors.textMuted,
}}>
- npm install @ngaf/langgraph
+ npm install @ngaf/chat @ngaf/langgraph
diff --git a/apps/website/src/components/landing/TheStack.tsx b/apps/website/src/components/landing/TheStack.tsx
index aacb4a9ec..cffae0d76 100644
--- a/apps/website/src/components/landing/TheStack.tsx
+++ b/apps/website/src/components/landing/TheStack.tsx
@@ -40,6 +40,18 @@ const LIBRARIES = [
href: '/chat',
ctaLabel: 'Explore Chat',
},
+ {
+ id: 'ag-ui',
+ tag: 'AG-UI',
+ pkg: '@ngaf/ag-ui',
+ color: tokens.colors.accent,
+ rgb: '0,64,144',
+ headline: 'Run any AG-UI compatible backend',
+ description: "AG-UI is the open agent-to-UI protocol used by CrewAI, Mastra, Microsoft Agent Framework, AG2, Pydantic AI, AWS Strands, and the CopilotKit runtime. The @ngaf/ag-ui adapter wraps an AbstractAgent into the same Agent contract @ngaf/chat consumes — same UI, different runtime.",
+ pills: ['CrewAI', 'Mastra', 'Microsoft AF', 'CopilotKit'],
+ href: 'https://github.com/cacheplane/angular-agent-framework/tree/main/libs/ag-ui',
+ ctaLabel: 'Explore AG-UI',
+ },
];
function Connector({ fromRgb, toRgb }: { fromRgb: string; toRgb: string }) {
@@ -90,7 +102,7 @@ export function TheStack() {
color: tokens.colors.textPrimary,
marginBottom: 10,
}}>
- Three libraries. One architecture.
+ Four libraries. One architecture.
Every layer you need.
- Your LangGraph agent already works. These three libraries ship it.
+ Whatever your agent runtime — LangGraph, AG-UI, or your own backend — these libraries ship it.
diff --git a/apps/website/src/components/landing/render/RenderStackSiblings.tsx b/apps/website/src/components/landing/render/RenderStackSiblings.tsx
index a5d5f5dad..fac88f25e 100644
--- a/apps/website/src/components/landing/render/RenderStackSiblings.tsx
+++ b/apps/website/src/components/landing/render/RenderStackSiblings.tsx
@@ -22,6 +22,15 @@ const SIBLINGS = [
href: '/chat',
ctaLabel: 'Explore Chat',
},
+ {
+ tag: 'AG-UI',
+ pkg: '@ngaf/ag-ui',
+ color: tokens.colors.accent,
+ rgb: '0,64,144',
+ headline: 'Run any AG-UI compatible backend',
+ href: 'https://github.com/cacheplane/angular-agent-framework/tree/main/libs/ag-ui',
+ ctaLabel: 'Explore AG-UI',
+ },
];
export function RenderStackSiblings() {
diff --git a/apps/website/src/lib/docs-config.ts b/apps/website/src/lib/docs-config.ts
index ab778e469..7e52925c0 100644
--- a/apps/website/src/lib/docs-config.ts
+++ b/apps/website/src/lib/docs-config.ts
@@ -1,4 +1,4 @@
-export type LibraryId = 'agent' | 'render' | 'chat';
+export type LibraryId = 'agent' | 'render' | 'chat' | 'ag-ui';
export interface DocsPage {
title: string;
@@ -180,6 +180,23 @@ export const docsConfig: DocsLibrary[] = [
},
],
},
+ {
+ id: 'ag-ui',
+ title: 'AG-UI',
+ description: 'Adapter for any AG-UI-compatible backend (CrewAI, Mastra, Microsoft AF, AG2, Pydantic AI, AWS Strands, CopilotKit runtime)',
+ sections: [
+ {
+ title: 'Getting Started',
+ id: 'getting-started',
+ color: 'blue',
+ pages: [
+ { title: 'Introduction', slug: 'introduction', section: 'getting-started' },
+ { title: 'Quick Start', slug: 'quickstart', section: 'getting-started' },
+ { title: 'Installation', slug: 'installation', section: 'getting-started' },
+ ],
+ },
+ ],
+ },
];
export function getLibraryConfig(libraryId: string): DocsLibrary | undefined {