Introduction
@threadplane/ag-ui is protocol-first: it consumes the AG-UI event vocabulary rather than any one runtime's SDK. That makes "any AG-UI backend plugs in" a claim that can be tested instead of asserted.
This section documents what happened when it was tested. On 2026-08-31 the adapter was run against three runtimes that have nothing to do with LangGraph, in two languages, with no adapter changes for messages, tool calls, or state. Each runtime has a standalone Angular example, a real backend, and a committed transcript of its wire traffic.
These pages document runtimes as backends measured against the adapter. They are not a substitute for each vendor's own documentation, and Threadplane does not maintain any of the upstream AG-UI bridges described here.
How it fits
The runtimes
Python. Messages, tool calls, and interrupts work. Shared state is snapshot-only and opt-in per tool.
Python. Messages, tool calls, state, and interrupts all work. Azure OpenAI by default.
TypeScript. Messages, tool calls, state, and interrupts all work, against a hand-written Node hosting service.
Measured support
| Runtime | Messages | Tool calls | State | Interrupts | Subagents |
|---|---|---|---|---|---|
| LangGraph (via the AG-UI bridge) | Yes | Yes | Yes | Yes | Yes |
| AWS Strands (Python) | Yes | Yes | Partial | Yes | Yes |
| Microsoft Agent Framework (Python) | Yes | Yes | Yes | Yes | Yes |
| Mastra (TypeScript) | Yes | Yes | Yes | Yes | Yes |
Every gap in that table is caused by an upstream integration, not by the AG-UI protocol and not by a defect in @threadplane/ag-ui. The full cause analysis lives in Choosing an adapter.
What is the same everywhere
The Angular side does not change between these three runtimes. Each example binds through the same two calls, provideAgent() and injectAgent(). In your own application the provider takes the endpoint URL directly:
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideAgent } from '@threadplane/ag-ui';
export const appConfig: ApplicationConfig = {
providers: [
provideAgent({ url: '/agent' }),
],
};import { Component } from '@angular/core';
import { ChatComponent } from '@threadplane/chat';
import { injectAgent } from '@threadplane/ag-ui';
@Component({
selector: 'app-root',
imports: [ChatComponent],
template: `<chat [agent]="agent" />`,
})
export class App {
protected readonly agent = injectAgent();
}The examples in this repository wrap that same provideAgent() call in a factory, because they resolve their endpoint at runtime rather than hard-coding it, and each one renders a shared-state panel and an approval card around <chat>. Neither difference reaches the adapter: the configuration it receives is still a single url.
What changes is the backend, its hosting lane, and the wire conventions it happens to use. The How It Connects page for each runtime records those conventions as they were measured.
What is different everywhere
Three differences turned up repeatedly, and each runtime page returns to them.
Interrupts arrive by two different conventions. AWS Strands and Microsoft Agent Framework signal an interrupt only through the protocol-standard RUN_FINISHED outcome. The LangGraph bridge signals it only through a CUSTOM event named on_interrupt. Mastra emits both. The adapter accepts either, and within a single run the first signal wins.
Resume payloads are not portable. The adapter derives the wire shape from how the interrupt arrived, so application code passes one neutral submit({ resume }) regardless of runtime.
Subagents now stream on every runtime measured here — AWS Strands, Microsoft Agent Framework, and Mastra. Each backend ships a small emitter that translates its native delegation signals into the protocol's SUBAGENT_* events, which @threadplane/ag-ui consumes directly. The per-runtime pages describe the emitter and link the wire capture behind each cell.
Further reading
- Choosing an adapter — the full measured matrix, cause-by-cause.
- AG-UI adapter introduction — the adapter these runtimes bind through.
- What changes when the runtime changes — the argument for measuring portability.
- We measured the runtime swap — the results write-up.
libs/ag-ui/fixtures/runtime-transcripts/— the captured Server-Sent Events, verbatim from the wire, plus one synthetic subagent transcript built to the shape those captures record.