## File: README.md

#  AG-UI: The Agent-User Interaction Protocol


AG-UI is an open, lightweight, event-based protocol that standardizes how AI agents connect to user-facing applications.
Built for simplicity and flexibility, it enables seamless integration between AI agents, real time user context, and user interfaces.

---





[](https://www.npmjs.com/package/@ag-ui/core)



[ Join our Discord → ](https://discord.gg/Jd3FzfdJa8) &nbsp;&nbsp;&nbsp; [ Read the Docs → ](https://ag-ui.com/) &nbsp;&nbsp;&nbsp; [ Go to the AG-UI Dojo → ](https://dojo.ag-ui.com/) &nbsp;&nbsp;&nbsp; [ Follow us → ](https://x.com/CopilotKit)





## 🚀 Getting Started
Create a new AG-UI application in seconds:
```bash
npx create-ag-ui-app my-agent-app
```

<h3> Useful Links:</h3>

- [The AG-UI Dojo](https://dojo.ag-ui.com/)
- [Build AG-UI-powered applications(Quickstart)](https://docs.ag-ui.com/quickstart/applications)
- [Build new AG-UI framework integrations (Quickstart)](https://go.copilotkit.ai/agui-contribute)
- [Book a call to discuss an AG-UI integration with a new framework](https://calendly.com/markus-copilotkit/ag-ui)
- [Join the Discord Community](https://discord.gg/Jd3FzfdJa8)

## What is AG-UI?

AG-UI is an open, lightweight, event-based protocol for agent-human interaction, designed for simplicity & flexibility:

- During agent executions, agent backends **emit events _compatible_ with one of AG-UI's ~16 standard event types**
- Agent backends can **accept one of a few simple AG-UI compatible inputs** as arguments

**AG-UI includes a flexible middleware layer** that ensures compatibility across diverse environments:

- Works with **any event transport** (SSE, WebSockets, webhooks, etc.)
- Allows for **loose event format matching**, enabling broad agent and app interoperability

It also ships with a **reference HTTP implementation** and **default connector** to help teams get started fast.


[Learn more about the specs →](https://go.copilotkit.ai/ag-ui-introduction)


## Why AG-UI?

AG-UI was developed based on real-world requirements and practical experience building in-app agent interactions.


## Where does AGUI fit in the agentic protocol stack?
AG-UI is complementary to the other 2 top agentic protocols
- MCP gives agents tools
- A2A allows agents to communicate with other agents
- AG-UI brings agents into user-facing applications



## 🚀 Features

- 💬 Real-time agentic chat with streaming
- 🔄 Bi-directional state synchronization
- 🧩 Generative UI and structured messages
- 🧠 Real-time context enrichment
- 🛠️ Frontend tool integration
- 🧑‍💻 Human-in-the-loop collaboration


## 🛠 Supported Integrations

AG-UI was born from CopilotKit's initial **partnership** with LangChain and CrewAI - and brings the incredibly popular agent-user-interactivity infrastructure to the wider agentic ecosystem.

**1st party** = the platforms that have AG‑UI built in and provide documentation for guidance.

## Frameworks

| Framework                                                          | Status                   | AG-UI Resources                                                                 |
| ------------------------------------------------------------------ | ------------------------ | -------------------------------------------------------------------------------- |
| Built-in Agent                                                | ✅ Supported             | ➡️ [Docs](https://docs.copilotkit.ai/direct-to-llm)  |

### 🤝 Partnerships
| Framework | Status | AG-UI Resources |
| ---------- | ------- | ---------------- |
| [LangChain](https://www.langchain.com/langgraph) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/langgraph/) 🎮 [Demos](https://dojo.ag-ui.com/langgraph-fastapi/feature/shared_state) |
| [CrewAI](https://crewai.com/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/crewai-flows) 🎮 [Demos](https://dojo.ag-ui.com/crewai/feature/shared_state) |

### 🧩 1st Party
| Framework | Status | AG-UI Resources |
| ---------- | ------- | ---------------- |
| [Microsoft Agent Framework](https://azure.microsoft.com/en-us/blog/introducing-microsoft-agent-framework/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/microsoft-agent-framework) 🎮 [Demos](https://dojo.ag-ui.com/microsoft-agent-framework-dotnet/feature/shared_state) |
| [Google ADK](https://google.github.io/adk-docs/get-started/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/adk) 🎮 [Demos](https://dojo.ag-ui.com/adk-middleware/feature/shared_state?openCopilot=true) |
| [AWS Strands Agents](https://github.com/strands-agents/sdk-python) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/aws-strands) 🎮 [Demos](https://dojo.ag-ui.com/aws-strands/feature/shared_state) |
| [Mastra](https://mastra.ai/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/mastra/) 🎮 [Demos](https://dojo.ag-ui.com/mastra/feature/tool_based_generative_ui) |
| [Pydantic AI](https://github.com/pydantic/pydantic-ai) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/pydantic-ai/) 🎮 [Demos](https://dojo.ag-ui.com/pydantic-ai/feature/shared_state) |
| [Agno](https://github.com/agno-agi/agno) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/agno/) 🎮 [Demos](https://dojo.ag-ui.com/agno/feature/tool_based_generative_ui) |
| [LlamaIndex](https://github.com/run-llama/llama_index) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/llamaindex/) 🎮 [Demos](https://dojo.ag-ui.com/llamaindex/feature/shared_state) |
| [AG2](https://ag2.ai/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/ag2/)  🎮 [Demos](https://dojo.ag-ui.com/ag2/feature/shared_state) |
| [AWS Bedrock Agents](https://aws.amazon.com/bedrock/agents/) | 🛠️ In Progress | – |



### 🌐 Community
| Framework | Status | AG-UI Resources |
| ---------- | ------- | ---------------- |
| [Claude Agent SDK](https://github.com/ag-ui-protocol/ag-ui/tree/main/integrations/claude-agent-sdk) | ✅ Supported | 🎮 [Demos](https://dojo.ag-ui.com/claude-agent-sdk-python/feature/shared_state) |
| [Claude Managed Agents SDK](https://github.com/ag-ui-protocol/ag-ui/tree/main/integrations/claude-managed-agents) | ✅ Supported | 🎮 [Demos](https://dojo.ag-ui.com/claude-managed-agents-python/feature/tool_based_generative_ui) |
| [Langroid](https://github.com/ag-ui-protocol/ag-ui/tree/main/integrations/langroid) | ✅ Supported | 🎮 [Demos](https://dojo.ag-ui.com/langroid/feature/shared_state) |
| [OpenAI Agent SDK](https://openai.github.io/openai-agents-python/) | 🛠️ In Progress | – |
| [Cloudflare Agents](https://developers.cloudflare.com/agents/) | 🛠️ In Progress | – |


## Agent Interaction Protocols

| Protocols | Status | AG-UI Resources | Integrations |
| ---------- | ------- | ---------------- | ------------- |
| [A2A](https://a2a-protocol.org/latest/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/a2a-protocol) | Partnership |


## Infrastructure / Deployment
| Platform | Status | AG-UI Resources | Integrations |
| ---------- | ------- | ---------------- | ------------- |
| [Amazon Bedrock AgentCore](https://aws.amazon.com/bedrock/agentcore/) | ✅ Supported | ➡️ [Docs](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-agui.html) | 1st Party |


## Specification (standard)
| Framework | Status | AG-UI Resources |
| ---------- | ------- | ---------------- |
| [Oracle Agent Spec](http://oracle.github.io/agent-spec/) | ✅ Supported | ➡️ [Docs](https://go.copilotkit.ai/copilotkit-oracle-docs) 🎮 [Demos](https://dojo.ag-ui.com/agent-spec-langgraph/feature/tool_based_generative_ui) |

## Generative UI
| Framework | Status | AG-UI Resources |
| ---------- | ------- | ---------------- |
| [MCP Apps](https://blog.modelcontextprotocol.io/posts/2025-11-21-mcp-apps/) | ✅ Supported | ➡️ [Docs](https://docs.copilotkit.ai/generative-ui-specs/mcp-apps) 🎮 [Demos]() |


## SDKs

| SDK | Status | AG-UI Resources | Integrations |
| --- | ------- | ---------------- | ------------- |
| [Kotlin]() | ✅ Supported | ➡️ [Getting Started](https://github.com/ag-ui-protocol/ag-ui/blob/main/docs/sdk/kotlin/overview.mdx) | Community |
| [Golang]() | ✅ Supported | ➡️ [Getting Started](https://github.com/ag-ui-protocol/ag-ui/blob/main/docs/sdk/go/overview.mdx) | Community |
| [Dart]() | ✅ Supported | ➡️ [Getting Started](https://github.com/ag-ui-protocol/ag-ui/tree/main/sdks/community/dart) | Community |
| [Java]() | ✅ Supported | ➡️ [Getting Started](https://github.com/ag-ui-protocol/ag-ui/blob/main/docs/sdk/java/overview.mdx) | Community |
| [Rust]() | ✅ Supported | ➡️ [Getting Started](https://github.com/ag-ui-protocol/ag-ui/tree/main/sdks/community/rust/crates/ag-ui-client) | Community |
| [Ruby]() | ✅ Supported | ➡️ [Getting Started](https://github.com/ag-ui-protocol/ag-ui/tree/main/sdks/community/ruby) | Community |
| [C++]() | ✅ Supported | ➡️ [GitHub Source](https://github.com/ag-ui-protocol/ag-ui/tree/main/sdks/community/c%2B%2B) | Community |
| [.NET]() | ✅ Supported | ➡️ [Getting Started](https://github.com/ag-ui-protocol/ag-ui/tree/main/sdks/dotnet/samples/GettingStarted) | Community |
| [Nim]() | 🛠️ In Progress | ➡️ [PR](https://github.com/ag-ui-protocol/ag-ui/pull/29) | Community |
| [Flowise]() | 🛠️ In Progress | ➡️ [GitHub Source](https://github.com/ag-ui-protocol/ag-ui/issues/367) | Community |
| [Langflow]() | 🛠️ In Progress | ➡️ [GitHub Source](https://github.com/ag-ui-protocol/ag-ui/issues/366) | Community |

## Clients

| Client | Status | AG-UI Resources | Integrations |
| --- | ------- | ---------------- | ------------- |
| [CopilotKit](https://github.com/CopilotKit/CopilotKit) | ✅ Supported | ➡️ [Getting Started](https://docs.copilotkit.ai/direct-to-llm/guides/quickstart) | 1st Party |
| Terminal + Agent | ✅ Supported | ➡️ [Getting Started](https://docs.ag-ui.com/quickstart/clients) | Community |
| Chat platforms (Slack, Microsoft Teams) | ✅ Supported | ➡️ [Channels SDK](https://github.com/CopilotKit/channels-sdk) 🎮 [OpenTag example](https://github.com/CopilotKit/OpenTag) | 1st Party |
| [React Native](https://reactnative.dev/) | ✅ Supported | ➡️ [Example](https://github.com/CopilotKit/CopilotKit/tree/main/examples/v2/react-native/demo) | 1st Party |

[View all supported integrations →](https://docs.ag-ui.com/introduction#supported-integrations)

## Examples
### Hello World App

Video:

https://github.com/user-attachments/assets/18c03330-1ebc-4863-b2b8-cc6c3a4c7bae

https://agui-demo.vercel.app/



## The AG-UI Dojo (Building-Blocks Viewer)
The AG-UI Dojo demonstrates AG-UI's core building blocks through simple, focused examples—each just 50-200 lines of code.

View the source code for the Dojo and all framework integrations [here](https://github.com/ag-ui-protocol/ag-ui/tree/main/apps/dojo).

https://github.com/user-attachments/assets/c298eea8-3f39-4a94-b968-7712429b0c49



## 🙋🏽‍♂️ Contributing to AG-UI

Check out the [Contributing guide](https://github.com/ag-ui-protocol/ag-ui/blob/main/CONTRIBUTING.md)

- **[Biweekly AG-UI Working Group](https://lu.ma/CopilotKit?k=c)**
  📅 Follow the CopilotKit Luma Events Calendar

## Roadmap

Check out the [AG-UI Roadmap](https://github.com/orgs/ag-ui-protocol/projects/1) to see what's being built and where you can jump in.


## 📄 License

AG-UI is open source software [licensed as MIT](https://opensource.org/licenses/MIT).

---

## File: apps/dojo/e2e/README.md

# CopilotKit Demo Smoke Tests

This repository houses Playwright-based smoke tests that run on a 6-hour schedule to make sure CopilotKit demo apps remain live and functional.

## 🔧 Local development

```bash
# Install deps
npm install

# Install browsers once
npx playwright install --with-deps

# Run the full suite
npm test
```

Playwright HTML reports are saved to `./playwright-report`.

## ➕ Adding a new smoke test

1. Duplicate an existing file in `tests/` or create `tests/<demo>.spec.ts`.
2. Use Playwright's `test` API—keep the test short (<30 s).
3. Commit and push—GitHub Actions will pick it up on the next scheduled run.

## 🚦 CI / CD

- `.github/workflows/scheduled-tests.yml` executes the suite every 6 hours and on manual trigger.
- Failing runs surface in the Actions tab; the HTML report is uploaded as an artifact.
- (Optional) Slack notifications can be wired by adding a step after the tests.
- Slack alert on failure is baked into the workflow. Just add `SLACK_WEBHOOK_URL` (Incoming Webhook) in repo secrets.

---

## File: apps/dojo/README.md

# AG-UI Protocol Dojo

A modern, interactive viewer for exploring CopilotKit agent demos with a clean, responsive UI and dark/light theme support.

## Overview

The Demo Viewer provides a centralized interface for browsing, viewing, and exploring the source code of various CopilotKit agent demos. It features:

- Clean, modern UI with dark/light theme support
- Interactive demo previews
- Source code exploration with syntax highlighting
- Organized demo listing with tags and descriptions
- LLM provider selection

## Development Setup

To run the Demo Viewer locally for development, follow these steps:

### Install dependencies

```bash
brew install protobuf
```

Note that running the dojo currently requires the use of `pnpm` (vs `yarn` or `npm`) do to how we handle  workspace dependencies.
```bash
curl -fsSL https://get.pnpm.io/install.sh | sh -
```

The first time you want to run, you need to build all of the dojos dependencies throught the repository.
```
# from the ag-ui repository root
pnpm i
pnpm build --projects=demo-viewer
```

### Run the Demo Viewer

There are 3 ways to run the demo viewer

- Run just the demo viewer, and run the agent(s) separately
- Run the dev script for the entire repo, and run the agent(s) separately
- use the `dojo-everything` scripts

#### Run just the demo viewer, and run the agent(s) separately.

In one terminal, you can `cd` into the dojo directory and run `pnpm dev` to just run the dojo
This will not capture updates to dependencies of the dojo
In another terminal, you'll need to run any other agents you want to test separately, see "Run Agents" below.
The dojo will start on port 3000 by default

Note that some agents may run on colliding ports

#### Run the dev script for the entire repo, and run the agent(s) separately
In one terminal, you can run `pnpm dev` from the *repository root*
This WILL automatically rebuild dependencies, for example if you change the mastra integration, it will automatically rebuild and be bundled into the dojo with HMR.
In another terminal, you'll need to run any other agents you want to test separately, see "Run Agents" below.
The dojo will start on port 3000 by default

Note that some agents may run on colliding ports

#### Run Agents
Agent examples for the dojo are generally located in `integrations/{integrationName}/{language}/examples`. A readme there should explain what you need to do to run the example, but it's usually either `npm dev` for typescript packages, or `poetry install && poetry run dev` or `uv sync && uv run dev` for python servers.

Note that some agents may run on colliding ports

#### Use the `dojo-everything` scripts

These are the easiest ways to run everything. They will automatically configure all of your ports to not be colliding, provide that information to the dojo, and spin up the dojo.

```
# In the apps/dojo directory
./scripts/prep-dojo-everything.js
./scripts/run-dojo-everything.js
```

The demo viewer will now run on port 9999.

The one caveat here is that (for precompiled speed while running tests) this runs a production nextjs build, and that build has to be redone if you modify the dojo code at all (or any of the typescript integrations).

You can look in the `run-dojo-everything.js` script and see which ports it runs agents at, and export those as environment variables, which can be found in `apps/dojo/src/env.ts`. Then you can run the dojo via `pnpm dev` at the repo root, to get live updates to typescript integrations and the dojo. There is not HMR on most of the python framework agent examples.

To choose which agents or services the `run-dojo-everything.js` script runs you can use the `--only` flag, like this: `./scripts/run-dojo-everything.js --only adk-middleware,langgraph-fastapi`. The names for these IDs match what is in `src/agents.ts` as well as being findable in the run-dojo-everything script. .

### Adding a new integration
Integrations should go in `integrations/{integrationID}`. There should always be a typescript folder that at least contains the client, and possibly a python (or other language) folder.

To add it to the dojo, please make sure it gets added to
- src/agents.ts
- src/menu.ts
- scripts/prep-dojo-everything.js
- scripts/run-dojo-everything.js
- e2e.yml
- the `apps/dojo/e2e` folder, look in the tests folder of other frameworks, and you should be able to mostly dupiclate these.

---

## File: apps/client-cli-example/README.md

# AG-UI CLI Example

A command-line chat interface demonstrating the AG-UI client with a Mastra agent. This example shows how to build an interactive CLI application that streams agent responses and tool calls in real-time.

## Features

- Interactive chat loop with streaming responses
- Real-time tool call visualization (weather and browser tools)
- Message history persistence using LibSQL
- Built with `@ag-ui/client` and `@ag-ui/mastra`

## Prerequisites

- Node.js 22.13.0 or later
- OpenAI API key

## Setup

1. Install dependencies from the repository root:

   ```bash
   pnpm install
   ```

2. Set your OpenAI API key:
   ```bash
   export OPENAI_API_KEY=your_api_key_here
   ```

## Usage

Run the CLI:

```bash
pnpm start
```

Try these example prompts:

- "What's the weather in San Francisco?"
- "Browse https://example.com"

Press `Ctrl+D` to quit.

## How It Works

This example uses:

- **MastraAgent**: Wraps a Mastra agent with AG-UI protocol support
- **Event Handlers**: Streams text deltas, tool calls, and results to the console
- **Memory**: Persists conversation history in a local SQLite database

---

## File: docs/concepts/agents.mdx

---
title: "Agents"
---

# Agents

Agents are the core components in the AG-UI protocol that process requests and
generate responses. They establish a standardized way for front-end applications
to communicate with AI services through a consistent interface, regardless of
the underlying implementation.

## What is an Agent?

In AG-UI, an agent is a class that:

1. Manages conversation state and message history
2. Processes incoming messages and context
3. Generates responses through an event-driven streaming interface
4. Follows a standardized protocol for communication

Agents can be implemented to connect with any AI service, including:

- Large language models (LLMs) like GPT-4 or Claude
- Custom AI systems
- Retrieval augmented generation (RAG) systems
- Multi-agent systems

## Agent Architecture

All agents in AG-UI extend the `AbstractAgent` class, which provides the
foundation for:

- State management
- Message history tracking
- Event stream processing
- Tool usage

```typescript
import { AbstractAgent } from "@ag-ui/client"

class MyAgent extends AbstractAgent {
  run(input: RunAgentInput): RunAgent {
    // Implementation details
  }
}
```

### Core Components

AG-UI agents have several key components:

1. **Configuration**: Agent ID, thread ID, and initial state
2. **Messages**: Conversation history with user and assistant messages
3. **State**: Structured data that persists across interactions
4. **Events**: Standardized messages for communication with clients
5. **Tools**: Functions that agents can use to interact with external systems

## Agent Types

AG-UI provides different agent implementations to suit various needs:

### AbstractAgent

The base class that all agents extend. It handles core event processing, state
management, and message history.

### HttpAgent

A concrete implementation that connects to remote AI services via HTTP:

```typescript
import { HttpAgent } from "@ag-ui/client"

const agent = new HttpAgent({
  url: "https://your-agent-endpoint.com/agent",
  headers: {
    Authorization: "Bearer your-api-key",
  },
})
```

### Custom Agents

You can create custom agents to integrate with any AI service by extending
`AbstractAgent`:

```typescript
class CustomAgent extends AbstractAgent {
  // Custom properties and methods

  run(input: RunAgentInput): RunAgent {
    // Implement the agent's logic
  }
}
```

## Implementing Agents

### Basic Implementation

To create a custom agent, extend the `AbstractAgent` class and implement the
required `run` method:

```typescript
import {
  AbstractAgent,
  RunAgent,
  RunAgentInput,
  EventType,
  BaseEvent,
} from "@ag-ui/client"
import { Observable } from "rxjs"

class SimpleAgent extends AbstractAgent {
  run(input: RunAgentInput): RunAgent {
    const { threadId, runId } = input

    return () =>
      new Observable((observer) => {
        // Emit RUN_STARTED event
        observer.next({
          type: EventType.RUN_STARTED,
          threadId,
          runId,
        })

        // Send a message
        const messageId = Date.now().toString()

        // Message start
        observer.next({
          type: EventType.TEXT_MESSAGE_START,
          messageId,
          role: "assistant",
        })

        // Message content
        observer.next({
          type: EventType.TEXT_MESSAGE_CONTENT,
          messageId,
          delta: "Hello, world!",
        })

        // Message end
        observer.next({
          type: EventType.TEXT_MESSAGE_END,
          messageId,
        })

        // Emit RUN_FINISHED event
        observer.next({
          type: EventType.RUN_FINISHED,
          threadId,
          runId,
        })

        // Complete the observable
        observer.complete()
      })
  }
}
```

## Agent Capabilities

Agents in the AG-UI protocol provide a rich set of capabilities that enable
sophisticated AI interactions:

### Interactive Communication

Agents establish bi-directional communication channels with front-end
applications through event streams. This enables:

- Real-time streaming responses character-by-character
- Immediate feedback loops between user and AI
- Progress indicators for long-running operations
- Structured data exchange in both directions

### Tool Usage

Agents can use tools to perform actions and access external resources.
Importantly, tools are defined and passed in from the front-end application to
the agent, allowing for a flexible and extensible system:

```typescript
// Tool definition
const confirmAction = {
  name: "confirmAction",
  parameters: {
    type: "object",
    properties: {
      action: {
        type: "string",
      },
      importance: {
        type: "string",
        enum: ["low", "medium", "high", "critical"],
      },
      details: {
        type: "string",
      },
    },
    required: ["action"],
  },
}

// Running an agent with tools from the frontend
agent.runAgent({
  tools: [confirmAction], // Frontend-defined tools passed to the agent
  // other parameters
})
```

Tools are invoked through a sequence of events:

1. `TOOL_CALL_START`: Indicates the beginning of a tool call
2. `TOOL_CALL_ARGS`: Streams the arguments for the tool call
3. `TOOL_CALL_END`: Marks the completion of the tool call

Front-end applications can then execute the tool and provide results back to the
agent. This bidirectional flow enables sophisticated human-in-the-loop workflows
where:

- The agent can request specific actions be performed
- Humans can execute those actions with appropriate judgment
- Results are fed back to the agent for continued reasoning
- The agent maintains awareness of all decisions made in the process

This mechanism is particularly powerful for implementing interfaces where AI and
humans collaborate. For example, [CopilotKit](https://docs.copilotkit.ai/)
leverages this exact pattern with their
[`useCopilotAction`](https://docs.copilotkit.ai/guides/frontend-actions) hook,
which provides a simplified way to define and handle tools in React
applications.

By keeping the AI informed about human decisions through the tool mechanism,
applications can maintain context and create more natural collaborative
experiences between users and AI assistants.

### State Management

Agents maintain a structured state that persists across interactions. This state
can be:

- Updated incrementally through `STATE_DELTA` events
- Completely refreshed with `STATE_SNAPSHOT` events
- Accessed by both the agent and front-end
- Used to store user preferences, conversation context, or application state

```typescript
// Accessing agent state
console.log(agent.state.preferences)

// State is automatically updated during agent runs
agent.runAgent().subscribe((event) => {
  if (event.type === EventType.STATE_DELTA) {
    // State has been updated
    console.log("New state:", agent.state)
  }
})
```

### Multi-Agent Collaboration

AG-UI supports agent-to-agent handoff and collaboration:

- Agents can delegate tasks to other specialized agents
- Multiple agents can work together in a coordinated workflow
- State and context can be transferred between agents
- The front-end maintains a consistent experience across agent transitions

For example, a general assistant agent might hand off to a specialized coding
agent when programming help is needed, passing along the conversation context
and specific requirements.

### Human-in-the-Loop Workflows

Agents support human intervention and assistance:

- Agents can request human input on specific decisions
- Front-ends can pause agent execution and resume it after human feedback
- Human experts can review and modify agent outputs before they're finalized
- Hybrid workflows combine AI efficiency with human judgment

This enables applications where the agent acts as a collaborative partner rather
than an autonomous system.

### Conversational Memory

Agents maintain a complete history of conversation messages:

- Past interactions inform future responses
- Message history is synchronized between client and server
- Messages can include rich content (text, structured data, references)
- The context window can be managed to focus on relevant information

```typescript
// Accessing message history
console.log(agent.messages)

// Adding a new user message
agent.messages.push({
  id: "msg_123",
  role: "user",
  content: "Can you explain that in more detail?",
})
```

### Metadata and Instrumentation

Agents can emit metadata about their internal processes:

- Reasoning steps through custom events
- Performance metrics and timing information
- Source citations and reference tracking
- Confidence scores for different response options

This allows front-ends to provide transparency into the agent's decision-making
process and help users understand how conclusions were reached.

## Using Agents

Once you've implemented or instantiated an agent, you can use it like this:

```typescript
// Create an agent instance
const agent = new HttpAgent({
  url: "https://your-agent-endpoint.com/agent",
})

// Add initial messages if needed
agent.messages = [
  {
    id: "1",
    role: "user",
    content: "Hello, how can you help me today?",
  },
]

// Run the agent
agent
  .runAgent({
    runId: "run_123",
    tools: [], // Optional tools
    context: [], // Optional context
  })
  .subscribe({
    next: (event) => {
      // Handle different event types
      switch (event.type) {
        case EventType.TEXT_MESSAGE_CONTENT:
          console.log("Content:", event.delta)
          break
        // Handle other events
      }
    },
    error: (error) => console.error("Error:", error),
    complete: () => console.log("Run complete"),
  })
```

## Agent Configuration

Agents accept configuration through the constructor:

```typescript
interface AgentConfig {
  agentId?: string // Unique identifier for the agent
  description?: string // Human-readable description
  threadId?: string // Conversation thread identifier
  initialMessages?: Message[] // Initial messages
  initialState?: State // Initial state object
}

// Using the configuration
const agent = new HttpAgent({
  agentId: "my-agent-123",
  threadId: "thread-456",
  initialMessages: [
    { id: "1", role: "system", content: "You are a helpful assistant." },
  ],
  initialState: { preferredLanguage: "English" },
})
```

## Agent State Management

AG-UI agents maintain state across interactions:

```typescript
// Access current state
console.log(agent.state)

// Access messages
console.log(agent.messages)

// Clone an agent with its state
const clonedAgent = agent.clone()
```

## Conclusion

Agents are the foundation of the AG-UI protocol, providing a standardized way to
connect front-end applications with AI services. By implementing the
`AbstractAgent` class, you can create custom integrations with any AI service
while maintaining a consistent interface for your applications.

The event-driven architecture enables real-time, streaming interactions that are
essential for modern AI applications, and the standardized protocol ensures
compatibility across different implementations.

---

## File: docs/concepts/architecture.mdx

---
title: "Core architecture"
---

Agent User Interaction Protocol (AG-UI) is built on a flexible, event-driven
architecture that enables seamless, efficient communication between front-end
applications and AI agents. This document covers the core architectural
components and concepts.

## Design Principles

AG-UI is designed to be lightweight and minimally opinionated, making it easy to
integrate with a wide range of agent implementations. The protocol's flexibility
comes from its simple requirements:

1. **Event-Driven Communication**: Agents need to emit any of the 16
   standardized event types during execution, creating a stream of updates that
   clients can process.

2. **Bidirectional Interaction**: Agents accept input from users, enabling
   collaborative workflows where humans and AI work together seamlessly.

The protocol includes a built-in middleware layer that maximizes compatibility
in two key ways:

- **Flexible Event Structure**: Events don't need to match AG-UI's format
  exactly—they just need to be AG-UI-compatible. This allows existing agent
  frameworks to adapt their native event formats with minimal effort.

- **Transport Agnostic**: AG-UI doesn't mandate how events are delivered,
  supporting various transport mechanisms including Server-Sent Events (SSE),
  webhooks, WebSockets, and more. This flexibility lets developers choose the
  transport that best fits their architecture.

This pragmatic approach makes AG-UI easy to adopt without requiring major
changes to existing agent implementations or frontend applications.

## Architectural Overview

AG-UI follows a client-server architecture that standardizes communication
between agents and applications:

```mermaid
flowchart LR
    subgraph "Frontend"
        App["Application"]
        Client["AG-UI Client"]
    end

    subgraph "Backend"
        A1["AI Agent A"]
        P["Secure Proxy"]
        A2["AI Agent B"]
        A3["AI Agent C"]
    end

    App <--> Client
    Client <-->|"AG-UI Protocol"| A1
    Client <-->|"AG-UI Protocol"| P
    P <-->|"AG-UI Protocol"| A2
    P <-->|"AG-UI Protocol"| A3

    class P mintStyle;
    classDef mintStyle fill:#E0F7E9,stroke:#66BB6A,stroke-width:2px,color:#000000;

    style App rx:5, ry:5;
    style Client rx:5, ry:5;
    style A1 rx:5, ry:5;
    style P rx:5, ry:5;
    style A2 rx:5, ry:5;
    style A3 rx:5, ry:5;
```

- **Application**: User-facing apps (i.e. chat or any AI-enabled application).
- **AG-UI Client**: Generic communication clients like `HttpAgent` or
  specialized clients for connecting to existing protocols.
- **Agents**: Backend AI agents that process requests and generate streaming
  responses.
- **Secure Proxy**: Backend services that provide additional capabilities and
  act as a secure proxy.

## Core components

### Protocol layer

AG-UI's protocol layer provides a flexible foundation for agent communication.

- **Universal compatibility**: Connect to any protocol by implementing
  `run(input: RunAgentInput) -> Observable`

The protocol's primary abstraction enables applications to run agents and
receive a stream of events:

{/* prettier-ignore */}
```typescript
// Core agent execution interface
type RunAgent = () => Observable

class MyAgent extends AbstractAgent {
  run(input: RunAgentInput): RunAgent {
    const { threadId, runId } = input
    return () =>
      from([
        { type: EventType.RUN_STARTED, threadId, runId },
        {
          type: EventType.MESSAGES_SNAPSHOT,
          messages: [
            { id: "msg_1", role: "assistant", content: "Hello, world!" }
          ],
        },
        { type: EventType.RUN_FINISHED, threadId, runId },
      ])
  }
}
```

### Standard HTTP client

AG-UI offers a standard HTTP client `HttpAgent` that can be used to connect to
any endpoint that accepts POST requests with a body of type `RunAgentInput` and
sends a stream of `BaseEvent` objects.

`HttpAgent` supports the following transports:

- **HTTP SSE (Server-Sent Events)**

  - Text-based streaming for wide compatibility
  - Easy to read and debug

- **HTTP binary protocol**
  - Highly performant and space-efficient custom transport
  - Robust binary serialization for production environments

### Message types

AG-UI defines several event categories for different aspects of agent
communication:

- **Lifecycle events**

  - `RUN_STARTED`, `RUN_FINISHED`, `RUN_ERROR`
  - `STEP_STARTED`, `STEP_FINISHED`

- **Text message events**

  - `TEXT_MESSAGE_START`, `TEXT_MESSAGE_CONTENT`, `TEXT_MESSAGE_END`

- **Tool call events**

  - `TOOL_CALL_START`, `TOOL_CALL_ARGS`, `TOOL_CALL_END`

- **State management events**

  - `STATE_SNAPSHOT`, `STATE_DELTA`, `MESSAGES_SNAPSHOT`

- **Special events**
  - `RAW`, `CUSTOM`

## Running Agents

To run an agent, you create a client instance and execute it:

```typescript
// Create an HTTP agent client
const agent = new HttpAgent({
  url: "https://your-agent-endpoint.com/agent",
  agentId: "unique-agent-id",
  threadId: "conversation-thread"
});

// Start the agent and handle events
agent.runAgent({
  tools: [...],
  context: [...]
}).subscribe({
  next: (event) => {
    // Handle different event types
    switch(event.type) {
      case EventType.TEXT_MESSAGE_CONTENT:
        // Update UI with new content
        break;
      // Handle other event types
    }
  },
  error: (error) => console.error("Agent error:", error),
  complete: () => console.log("Agent run complete")
});
```

## State Management

AG-UI provides efficient state management through specialized events:

- `STATE_SNAPSHOT`: Complete state representation at a point in time
- `STATE_DELTA`: Incremental state changes using JSON Patch format (RFC 6902)
- `MESSAGES_SNAPSHOT`: Complete conversation history

These events enable efficient client-side state management with minimal data
transfer.

## Tools and Handoff

AG-UI supports agent-to-agent handoff and tool usage through standardized
events:

- Tool definitions are passed in the `runAgent` parameters
- Tool calls are streamed as sequences of `TOOL_CALL_START` → `TOOL_CALL_ARGS` →
  `TOOL_CALL_END` events
- Agents can hand off to other agents, maintaining context continuity

## Events

All communication in AG-UI is based on typed events. Every event inherits from
`BaseEvent`:

```typescript
interface BaseEvent {
  type: EventType
  timestamp?: number
  rawEvent?: any
}
```

Events are strictly typed and validated, ensuring reliable communication between
components.

---

## File: docs/concepts/events.mdx

---
title: "Events"
---

# Events

The Agent User Interaction Protocol uses a streaming event-based architecture.
Events are the fundamental units of communication between agents and frontends,
enabling real-time, structured interaction.

## Event Types Overview

Events in the protocol are categorized by their purpose:

| Category                | Description                             |
| ----------------------- | --------------------------------------- |
| Lifecycle Events        | Monitor the progression of agent runs   |
| Text Message Events     | Handle streaming textual content        |
| Tool Call Events        | Manage tool executions by agents        |
| State Management Events | Synchronize state between agents and UI |
| Activity Events         | Represent ongoing activity progress     |
| Special Events          | Support custom functionality            |
| Draft Events            | Proposed events under development       |

## Base Event Properties

All events share a common set of base properties:

| Property    | Description                                                      |
| ----------- | ---------------------------------------------------------------- |
| `type`      | The specific event type identifier                               |
| `timestamp` | Optional timestamp indicating when the event was created         |
| `rawEvent`  | Optional field containing the original event data if transformed |
| `metadata`  | Optional extra information attached to the event                 |

### Metadata

`metadata` is an optional, open-by-key object for attaching extra information to
an event — token usage, a trace id, a finish reason. It is declared once on the
base event, so every event type carries it.

Consumers merge an event's metadata into the message that event builds, key by
key, with the last write winning. That is what lets a producer send token usage
on the final event of a message rather than having to know it up front.

See [Metadata](/concepts/metadata) for the full rules: the reserved `ag-ui` key,
which events do and do not merge, how tool calls carry their own, and how the
object behaves across transports.

## Lifecycle Events

These events represent the lifecycle of an agent run. A typical agent run
follows a predictable pattern: it begins with a `RunStarted` event, may contain
multiple optional `StepStarted`/`StepFinished` pairs, and concludes with either
a `RunFinished` event (success) or a `RunError` event (failure).

Lifecycle events provide crucial structure to agent runs, enabling frontends to
track progress, manage UI states appropriately, and handle errors gracefully.
They create a consistent framework for understanding when operations begin and
end, making it possible to implement features like loading indicators, progress
tracking, and error recovery mechanisms.

```mermaid
sequenceDiagram
    participant Agent
    participant Client

    Note over Agent,Client: Run begins
    Agent->>Client: RunStarted

    opt Sending steps is optional
        Note over Agent,Client: Step execution
        Agent->>Client: StepStarted
        Agent->>Client: StepFinished
    end

    Note over Agent,Client: Run completes
    alt
        Agent->>Client: RunFinished
    else
        Agent->>Client: RunError
    end
```

The `RunStarted` and either `RunFinished` or `RunError` events are mandatory,
forming the boundaries of an agent run. Step events are optional and may occur
multiple times within a run, allowing for structured, observable progress
tracking.

### RunStarted

Signals the start of an agent run.

The `RunStarted` event is the first event emitted when an agent begins
processing a request. It establishes a new execution context identified by a
unique `runId`. This event serves as a marker for frontends to initialize UI
elements such as progress indicators or loading states. It also provides crucial
identifiers that can be used to associate subsequent events with this specific
run.

| Property      | Description                                                                                                                                                    |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `threadId`    | ID of the conversation thread                                                                                                                                  |
| `runId`       | ID of the agent run                                                                                                                                            |
| `parentRunId` | (Optional) Lineage pointer for branching/time travel. If present, refers to a prior run within the same thread, creating a git-like append-only log            |
| `input`       | (Optional) The exact agent input payload that was sent to the agent for this run. May omit messages already present in history; compactEvents() will normalize |

### RunFinished

Signals the end of an agent run. Every run terminates with either `RunFinished`
or `RunError`.

`RunFinished` has an optional `outcome` discriminated union:

- **omitted** — legacy producer that has not yet adopted the interrupt-aware
  lifecycle. Treated as a normal completion.
- `outcome: { type: "success" }` — the run completed normally. The optional
  `result` stays at the root of the event for back-compat.
- `outcome: { type: "interrupt", interrupts: [...] }` — the run paused for human
  input. The non-empty `interrupts` array lives inside the outcome variant. The
  client resumes by starting a new run whose `RunAgentInput` includes a `resume`
  array addressing every open interrupt.

<Note>
  For the full interrupt lifecycle — the `Interrupt` type, contract rules, error
  handling, reason taxonomy, and worked examples — see
  [Interrupts](/concepts/interrupts).
</Note>

### RunError

Signals an error during an agent run.

The `RunError` event indicates that the agent encountered an error it could not
recover from, causing the run to terminate prematurely. This event provides
information about what went wrong, allowing frontends to display appropriate
error messages and potentially offer recovery options. After a `RunError` event,
no further processing will occur in this run.

| Property  | Description         |
| --------- | ------------------- |
| `message` | Error message       |
| `code`    | Optional error code |

### StepStarted

Signals the start of a step within an agent run.

The `StepStarted` event indicates that the agent is beginning a specific subtask
or phase of its processing. Steps provide granular visibility into the agent's
progress, enabling more precise tracking and feedback in the UI. Steps are
optional but highly recommended for complex operations that benefit from being
broken down into observable stages. The `stepName` could be the name of a node
or function that is currently executing.

| Property   | Description      |
| ---------- | ---------------- |
| `stepName` | Name of the step |

### StepFinished

Signals the completion of a step within an agent run.

The `StepFinished` event indicates that the agent has completed a specific
subtask or phase. When paired with a corresponding `StepStarted` event, it
creates a bounded context for a discrete unit of work. Frontends can use these
events to update progress indicators, show completion animations, or reveal
results specific to that step. The `stepName` must match the corresponding
`StepStarted` event to properly pair the beginning and end of the step.

| Property   | Description      |
| ---------- | ---------------- |
| `stepName` | Name of the step |

## Text Message Events

These events represent the lifecycle of text messages in a conversation. Text
message events follow a streaming pattern, where content is delivered
incrementally. A message begins with a `TextMessageStart` event, followed by one
or more `TextMessageContent` events that deliver chunks of text as they become
available, and concludes with a `TextMessageEnd` event.

This streaming approach enables real-time display of message content as it's
generated, creating a more responsive user experience compared to waiting for
the entire message to be complete before showing anything.

```mermaid
sequenceDiagram
    participant Agent
    participant Client

    Note over Agent,Client: Message begins
    Agent->>Client: TextMessageStart

    loop Content streaming
        Agent->>Client: TextMessageContent
    end

    Note over Agent,Client: Message completes
    Agent->>Client: TextMessageEnd
```

The `TextMessageContent` events each contain a `delta` field with a chunk of
text. Frontends should concatenate these deltas in the order received to
construct the complete message. The `messageId` property links all related
events, allowing the frontend to associate content chunks with the correct
message.

### TextMessageStart

Signals the start of a text message.

The `TextMessageStart` event initializes a new text message in the conversation.
It establishes a unique `messageId` that will be referenced by subsequent
content chunks and the end event. This event allows frontends to prepare the UI
for an incoming message, such as creating a new message bubble with a loading
indicator. The `role` property identifies whether the message is coming from the
assistant or potentially another participant in the conversation.

| Property    | Description                                                                     |
| ----------- | ------------------------------------------------------------------------------- |
| `messageId` | Unique identifier for the message                                               |
| `role`      | Role of the message sender ("developer", "system", "assistant", "user", "tool") |

### TextMessageContent

Represents a chunk of content in a streaming text message.

The `TextMessageContent` event delivers incremental parts of the message text as
they become available. Each event contains a small chunk of text in the `delta`
property that should be appended to previously received chunks. The streaming
nature of these events enables real-time display of content, creating a more
responsive and engaging user experience. Implementations should handle these
events efficiently to ensure smooth text rendering without visible delays or
flickering.

| Property    | Description                            |
| ----------- | -------------------------------------- |
| `messageId` | Matches the ID from `TextMessageStart` |
| `delta`     | Text content chunk (non-empty)         |

### TextMessageEnd

Signals the end of a text message.

The `TextMessageEnd` event marks the completion of a streaming text message.
After receiving this event, the frontend knows that the message is complete and
no further content will be added. This allows the UI to finalize rendering,
remove any loading indicators, and potentially trigger actions that should occur
after message completion, such as enabling reply controls or performing
automatic scrolling to ensure the full message is visible.

| Property    | Description                            |
| ----------- | -------------------------------------- |
| `messageId` | Matches the ID from `TextMessageStart` |

### TextMessageChunk

Convenience event that expands to Start → Content → End automatically.

The `TextMessageChunk` event lets you omit explicit `TextMessageStart` and
`TextMessageEnd` events. The client stream transformer expands chunks into the
standard triad:

- First chunk for a message must include `messageId` and will emit
  `TextMessageStart` (role defaults to `assistant` when not provided).
- Each chunk with a `delta` emits a `TextMessageContent` for the current
  `messageId`.
- `TextMessageEnd` is emitted automatically when the stream switches to a new
  message ID or when the stream completes.

| Property    | Description                                                                          |
| ----------- | ------------------------------------------------------------------------------------ |
| `messageId` | Optional unique identifier for the message; required on the first chunk of a message |
| `role`      | Optional role of the sender ("developer", "system", "assistant", "user")             |
| `delta`     | Optional text content of the message                                                 |

## Tool Call Events

These events represent the lifecycle of tool calls made by agents. Tool calls
follow a streaming pattern similar to text messages. When an agent needs to use
a tool, it emits a `ToolCallStart` event, followed by one or more `ToolCallArgs`
events that stream the arguments being passed to the tool, and concludes with a
`ToolCallEnd` event.

This streaming approach allows frontends to show tool executions in real-time,
making the agent's actions transparent and providing immediate feedback about
what tools are being invoked and with what parameters.

```mermaid
sequenceDiagram
    participant Agent
    participant Client

    Note over Agent,Client: Tool call begins
    Agent->>Client: ToolCallStart

    loop Arguments streaming
        Agent->>Client: ToolCallArgs
    end

    Note over Agent,Client: Tool call completes
    Agent->>Client: ToolCallEnd

    Note over Agent,Client: Tool execution result
    Agent->>Client: ToolCallResult
```

The `ToolCallArgs` events each contain a `delta` field with a chunk of the
arguments. Frontends should concatenate these deltas in the order received to
construct the complete arguments object. The `toolCallId` property links all
related events, allowing the frontend to associate argument chunks with the
correct tool call.

### ToolCallStart

Signals the start of a tool call.

The `ToolCallStart` event indicates that the agent is invoking a tool to perform
a specific function. This event provides the name of the tool being called and
establishes a unique `toolCallId` that will be referenced by subsequent events
in this tool call. Frontends can use this event to display tool usage to users,
such as showing a notification that a specific operation is in progress. The
optional `parentMessageId` allows linking the tool call to a specific message in
the conversation, providing context for why the tool is being used.

| Property          | Description                         |
| ----------------- | ----------------------------------- |
| `toolCallId`      | Unique identifier for the tool call |
| `toolCallName`    | Name of the tool being called       |
| `parentMessageId` | Optional ID of the parent message   |

### ToolCallArgs

Represents a chunk of argument data for a tool call.

The `ToolCallArgs` event delivers incremental parts of the tool's arguments as
they become available. Each event contains a segment of the argument data in the
`delta` property. These deltas are often JSON fragments that, when combined,
form the complete arguments object for the tool. Streaming the arguments is
particularly valuable for complex tool calls where constructing the full
arguments may take time. Frontends can progressively reveal these arguments to
users, providing insight into exactly what parameters are being passed to tools.

| Property     | Description                         |
| ------------ | ----------------------------------- |
| `toolCallId` | Matches the ID from `ToolCallStart` |
| `delta`      | Argument data chunk                 |

### ToolCallEnd

Signals the end of a tool call.

The `ToolCallEnd` event marks the completion of a tool call. After receiving
this event, the frontend knows that all arguments have been transmitted and the
tool execution is underway or completed. This allows the UI to finalize the tool
call display and prepare for potential results. In systems where tool execution
results are returned separately, this event indicates that the agent has
finished specifying the tool and its arguments, and is now waiting for or has
received the results.

| Property     | Description                         |
| ------------ | ----------------------------------- |
| `toolCallId` | Matches the ID from `ToolCallStart` |

### ToolCallResult

Provides the result of a tool call execution.

The `ToolCallResult` event delivers the output or result from a tool that was
previously invoked by the agent. This event is sent after the tool has been
executed by the system and contains the actual output generated by the tool.
Unlike the streaming pattern of tool call specification (start, args, end), the
result is delivered as a complete unit since tool execution typically produces a
complete output. Frontends can use this event to display tool results to users,
append them to the conversation history, or trigger follow-up actions based on
the tool's output.

| Property     | Description                                                 |
| ------------ | ----------------------------------------------------------- |
| `messageId`  | ID of the conversation message this result belongs to       |
| `toolCallId` | Matches the ID from the corresponding `ToolCallStart` event |
| `content`    | The actual result/output content from the tool execution    |
| `role`       | Optional role identifier, typically "tool" for tool results |

### ToolCallChunk

Convenience event that expands to Start → Args → End automatically.

The `ToolCallChunk` event lets you omit explicit `ToolCallStart` and
`ToolCallEnd` events. The client stream transformer expands chunks into the
standard tool-call triad:

- First chunk for a tool call must include `toolCallId` and `toolCallName` and
  will emit `ToolCallStart` (propagating any `parentMessageId`).
- Each chunk with a `delta` emits a `ToolCallArgs` for the current `toolCallId`.
- `ToolCallEnd` is emitted automatically when the stream switches to a new
  `toolCallId` or when the stream completes.

| Property          | Description                                                          |
| ----------------- | -------------------------------------------------------------------- |
| `toolCallId`      | Optional on later chunks; required on the first chunk of a tool call |
| `toolCallName`    | Optional on later chunks; required on the first chunk of a tool call |
| `parentMessageId` | Optional ID of the parent message                                    |
| `delta`           | Optional argument data chunk (often a JSON fragment)                 |

## State Management Events

These events are used to manage and synchronize the agent's state with the
frontend. State management in the protocol follows an efficient snapshot-delta
pattern where complete state snapshots are sent initially or infrequently, while
incremental updates (deltas) are used for ongoing changes.

This approach optimizes for both completeness and efficiency: snapshots ensure
the frontend has the full state context, while deltas minimize data transfer for
frequent updates. Together, they enable frontends to maintain an accurate
representation of agent state without unnecessary data transmission.

```mermaid
sequenceDiagram
    participant Agent
    participant Client

    Note over Agent,Client: Initial state transfer
    Agent->>Client: StateSnapshot

    Note over Agent,Client: Incremental updates
    loop State changes over time
        Agent->>Client: StateDelta
        Agent->>Client: StateDelta
    end

    Note over Agent,Client: Occasional full refresh
    Agent->>Client: StateSnapshot

    loop More incremental updates
        Agent->>Client: StateDelta
    end

    Note over Agent,Client: Message history update
    Agent->>Client: MessagesSnapshot
```

The combination of snapshots and deltas allows frontends to efficiently track
changes to agent state while ensuring consistency. Snapshots serve as
synchronization points that reset the state to a known baseline, while deltas
provide lightweight updates between snapshots.

### StateSnapshot

Provides a complete snapshot of an agent's state.

The `StateSnapshot` event delivers a comprehensive representation of the agent's
current state. This event is typically sent at the beginning of an interaction
or when synchronization is needed. It contains all state variables relevant to
the frontend, allowing it to completely rebuild its internal representation.
Frontends should replace their existing state model with the contents of this
snapshot rather than trying to merge it with previous state.

| Property   | Description             |
| ---------- | ----------------------- |
| `snapshot` | Complete state snapshot |

### StateDelta

Provides a partial update to an agent's state using JSON Patch.

The `StateDelta` event contains incremental updates to the agent's state in the
form of JSON Patch operations (as defined in RFC 6902). Each delta represents
specific changes to apply to the current state model. This approach is
bandwidth-efficient, sending only what has changed rather than the entire state.
Frontends should apply these patches in sequence to maintain an accurate state
representation. If a frontend detects inconsistencies after applying patches, it
may request a fresh `StateSnapshot`.

| Property | Description                               |
| -------- | ----------------------------------------- |
| `delta`  | Array of JSON Patch operations (RFC 6902) |

### MessagesSnapshot

Provides a snapshot of all messages in a conversation.

The `MessagesSnapshot` event delivers a complete history of messages in the
current conversation. Unlike the general state snapshot, this focuses
specifically on the conversation transcript. This event is useful for
initializing the chat history, synchronizing after connection interruptions, or
providing a comprehensive view when a user joins an ongoing conversation.
Frontends should use this to establish or refresh the conversational context
displayed to users.

| Property   | Description              |
| ---------- | ------------------------ |
| `messages` | Array of message objects |

`activity` and `reasoning` messages are all-or-nothing inside a
`MessagesSnapshot`. If the snapshot carries any message of that role, it is the
complete set for that role: entries it repeats replace the client's copies, and
ones it leaves out are removed. If it carries none, the snapshot says nothing
about that role and the client keeps the messages it already has.

Both roles are client-side by default, so leaving them out is safe. Activity
messages never travel back to the agent — they are stripped from `RunAgentInput`
— and reasoning usually exists only as streamed `Reasoning` events. A backend
that tracks neither simply omits them from the snapshot, and nothing the client
holds is lost.

## Activity Events

Activity Events expose structured, in-progress activity updates that occur
between chat messages. They follow the same snapshot/delta pattern as the state
system so that UIs can render a complete activity view immediately and then
incrementally update it as new information arrives.

### ActivitySnapshot

Delivers a complete snapshot of an activity message.

| Property       | Description                                                                                   |
| -------------- | --------------------------------------------------------------------------------------------- |
| `messageId`    | Identifier for the `ActivityMessage` this event updates                                       |
| `activityType` | Activity discriminator (for example `"PLAN"`, `"SEARCH"`)                                     |
| `content`      | Structured JSON payload representing the full activity state                                  |
| `replace`      | Optional. Defaults to `true`. When `false`, ignore the snapshot if the message already exists |

Frontends should either create a new `ActivityMessage` or replace the existing
one with the payload supplied by the snapshot.

### ActivityDelta

Applies incremental updates to an existing activity using JSON Patch operations.

| Property       | Description                                                              |
| -------------- | ------------------------------------------------------------------------ |
| `messageId`    | Identifier for the target activity message                               |
| `activityType` | Activity discriminator (mirrors the value from the most recent snapshot) |
| `patch`        | Array of RFC 6902 JSON Patch operations to apply to the activity data    |

Activity deltas should be applied in order to the previously synchronized
activity content. If an application detects divergence, it can request or emit a
fresh `ActivitySnapshot` to resynchronize.

## Special Events

Special events provide flexibility in the protocol by allowing for
system-specific functionality and integration with external systems. These
events don't follow the standard lifecycle or streaming patterns of other event
types but instead serve specialized purposes.

### Raw

Used to pass through events from external systems.

The `Raw` event acts as a container for events originating from external systems
or sources that don't natively follow the Agent UI Protocol. This event type
enables interoperability with other event-based systems by wrapping their events
in a standardized format. The enclosed event data is preserved in its original
form inside the `event` property, while the optional `source` property
identifies the system it came from. Frontends can use this information to handle
external events appropriately, either by processing them directly or by
delegating them to system-specific handlers.

| Property | Description                |
| -------- | -------------------------- |
| `event`  | Original event data        |
| `source` | Optional source identifier |

### Custom

Used for application-specific custom events.

The `Custom` event provides an extension mechanism for implementing features not
covered by the standard event types. Unlike `Raw` events which act as
passthrough containers, `Custom` events are explicitly part of the protocol but
with application-defined semantics. The `name` property identifies the specific
custom event type, while the `value` property contains the associated data. This
mechanism allows for protocol extensions without requiring formal specification
changes. Teams should document their custom events to ensure consistent
implementation across frontends and agents.

| Property | Description                     |
| -------- | ------------------------------- |
| `name`   | Name of the custom event        |
| `value`  | Value associated with the event |

## Reasoning Events

Reasoning events support LLM reasoning visibility and continuity, enabling
chain-of-thought reasoning while maintaining privacy. These events allow agents
to surface reasoning signals (e.g., summaries) and support encrypted reasoning
items for state carry-over across turns—especially under `store:false` or zero
data retention policies—without exposing raw chain-of-thought.

See
[OpenAI ZTR documentation](https://developers.openai.com/cookbook/examples/responses_api/reasoning_items/#encrypted-reasoning-items),
[OpenAI store parameter documentation](https://platform.openai.com/docs/api-reference/responses/create#responses_create-store),
and
[Gemini Thought Signatures](https://ai.google.dev/gemini-api/docs/thought-signatures)
for the underlying concept of encrypted reasoning items, which inspired this
design.

See [Reasoning](/concepts/reasoning) for comprehensive documentation including
privacy considerations, compliance guidance, and implementation examples.

```mermaid
sequenceDiagram
    participant Agent
    participant Client

    Note over Agent,Client: Reasoning begins
    Agent->>Client: ReasoningStart

    Note over Agent,Client: Stream reasoning content
    Agent->>Client: ReasoningMessageStart
    Agent->>Client: ReasoningMessageContent
    Agent->>Client: ReasoningMessageEnd

    Note over Agent,Client: Reasoning completes
    Agent->>Client: ReasoningEnd
```

### ReasoningStart

Marks the start of reasoning.

The `ReasoningStart` event signals that the agent is beginning a reasoning
process. It establishes a reasoning context identified by a unique `messageId`.

| Property    | Description                         |
| ----------- | ----------------------------------- |
| `messageId` | Unique identifier of this reasoning |

### ReasoningMessageStart

Signals the start of a reasoning message.

The `ReasoningMessageStart` event begins a streaming reasoning message. This
message will contain the visible portion of the agent's reasoning that should be
displayed to users (e.g., a summary or partial chain-of-thought).

| Property    | Description                                   |
| ----------- | --------------------------------------------- |
| `messageId` | Unique identifier of the message              |
| `role`      | Role of the reasoning message (`"reasoning"`) |

### ReasoningMessageContent

Represents a chunk of content in a streaming reasoning message.

The `ReasoningMessageContent` event delivers incremental reasoning content to
the client. Multiple content events with the same `messageId` should be
concatenated to form the complete visible reasoning.

| Property    | Description                                |
| ----------- | ------------------------------------------ |
| `messageId` | Matches ID from ReasoningMessageStart      |
| `delta`     | Reasoning content chunk (non-empty string) |

### ReasoningMessageEnd

Signals the end of a reasoning message.

The `ReasoningMessageEnd` event indicates that all content for the specified
reasoning message has been sent. Clients should finalize any UI representing
this reasoning message.

| Property    | Description                           |
| ----------- | ------------------------------------- |
| `messageId` | Matches ID from ReasoningMessageStart |

### ReasoningMessageChunk

A convenience event to auto start/close reasoning messages.

The `ReasoningMessageChunk` event simplifies implementation by automatically
managing message lifecycle. The first chunk with a `messageId` implicitly starts
the message. An empty `delta` or the next non-reasoning event implicitly closes
the message.

| Property    | Description                                               |
| ----------- | --------------------------------------------------------- |
| `messageId` | Message ID (first event must be non-empty)                |
| `delta`     | Reasoning content chunk (empty string closes the message) |

### ReasoningEnd

Marks the end of reasoning.

The `ReasoningEnd` event signals that the agent has completed its reasoning
process for the given context. No further reasoning events with the same
`messageId` should be expected after this event.

| Property    | Description                         |
| ----------- | ----------------------------------- |
| `messageId` | Unique identifier of this reasoning |

### ReasoningEncryptedValue

Attaches encrypted chain-of-thought reasoning to a message or tool call.

The `ReasoningEncryptedValue` event carries encrypted reasoning content that
represents the LLM's internal chain-of-thought related to a specific entity.
This allows the agent to preserve reasoning state across conversation turns
without exposing the raw content to the client. The client stores and forwards
these encrypted values opaquely—only the agent (or authorized backend) can
decrypt them.

| Property         | Description                                              |
| ---------------- | -------------------------------------------------------- |
| `subtype`        | Entity type: `"message"` or `"tool-call"`                |
| `entityId`       | ID of the message or tool call this reasoning belongs to |
| `encryptedValue` | Encrypted chain-of-thought content blob                  |

Use cases:

- **Message reasoning**: Attach encrypted reasoning to an `AssistantMessage` or
  `ReasoningMessage` to preserve context for follow-up turns
- **Tool call reasoning**: Attach encrypted reasoning to a tool call to capture
  why the agent chose specific arguments or how it interpreted results

## Deprecated Events

<Warning>
  The following events are deprecated and will be removed in version 1.0.0. Use
  the corresponding Reasoning events instead.
</Warning>

### Thinking Events (Deprecated)

The `THINKING_*` events have been replaced by `REASONING_*` events:

| Deprecated Event                | Replacement                 |
| ------------------------------- | --------------------------- |
| `THINKING_START`                | `REASONING_START`           |
| `THINKING_END`                  | `REASONING_END`             |
| `THINKING_TEXT_MESSAGE_START`   | `REASONING_MESSAGE_START`   |
| `THINKING_TEXT_MESSAGE_CONTENT` | `REASONING_MESSAGE_CONTENT` |
| `THINKING_TEXT_MESSAGE_END`     | `REASONING_MESSAGE_END`     |

See [Reasoning Migration](/concepts/reasoning#migration-from-thinking-events)
for detailed migration guidance.

## Draft Events

These events are currently in draft status and may change before finalization.
They represent proposed extensions to the protocol that are under active
development and discussion.

### Meta Events


  DRAFT

[View Proposal](/drafts/meta-events)

Meta events provide annotations and signals independent of agent runs, such as
user feedback or external system events.

#### MetaEvent

A side-band annotation event that can occur anywhere in the stream.

| Property   | Description                                         |
| ---------- | --------------------------------------------------- |
| `metaType` | Application-defined type (e.g., "thumbs_up", "tag") |
| `payload`  | Application-defined payload                         |

### Modified Lifecycle Events


  DRAFT

[View Specification](/concepts/interrupts)

Extensions to existing lifecycle events to support interrupts and branching.

#### RunFinished (Extended)

The `RunFinished` event gains new fields to support interrupt-aware workflows.

| Property  | Description                                                                                                                       |
| --------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `outcome` | Optional discriminated union: `{ type: "success" }` or `{ type: "interrupt", interrupts: [...] }`. Omitted on legacy producers.   |
| `result`  | Optional. Free-form completion payload. Lives at the event root for back-compat with legacy producers; coexists with any outcome. |

See [Serialization](/concepts/serialization) for lineage and input capture.

#### RunStarted (Extended)

The `RunStarted` event gains new fields to support branching and input tracking.

| Property      | Description                                       |
| ------------- | ------------------------------------------------- |
| `parentRunId` | Optional: Parent run ID for branching/time travel |
| `input`       | Optional: The exact agent input for this run      |

## Event Flow Patterns

Events in the protocol typically follow specific patterns:

1. **Start-Content-End Pattern**: Used for streaming content (text messages,
   tool calls)
   - `Start` event initiates the stream
   - `Content` events deliver data chunks
   - `End` event signals completion

2. **Snapshot-Delta Pattern**: Used for state synchronization
   - `Snapshot` provides complete state
   - `Delta` events provide incremental updates

3. **Lifecycle Pattern**: Used for monitoring agent runs
   - `Started` events signal beginnings
   - `Finished`/`Error` events signal endings

## Implementation Considerations

When implementing event handlers:

- Events should be processed in the order they are received
- Events with the same ID (e.g., `messageId`, `toolCallId`) belong to the same
  logical stream
- Implementations should be resilient to out-of-order delivery
- Custom events should follow the established patterns for consistency

---

## File: docs/concepts/generative-ui-specs.mdx

---
title: "Generative UI"
---

## **AG-UI and Generative UI Specs**

Several recently released specs have enabled agents to return generative UI, increasing the power and flexibility of the Agent&lt;-&gt;User conversation.

A2UI, MCP-UI, and Open-JSON-UI are all **generative UI specifications.** Generative UIs allow agents to respond to users not only with text but also with dynamic UI components.

| **Specification** | **Origin / Maintainer** | **Purpose** |
| --- | --- | --- |
| **A2UI** | Google | A declarative, LLM-friendly Generative UI spec. JSONL-based and streaming, designed for platform-agnostic rendering. |
| **Open-JSON-UI** | OpenAI | An open standardization of OpenAI's internal declarative Generative UI schema. |
| **MCP-UI** | Microsoft + Shopify | A fully open, iframe-based Generative UI standard extending MCP for user-facing experiences. |

Despite the naming similarities, **AG-UI is not a generative UI specification** — it's a **User Interaction protocol** that provides the **bi-directional runtime connection** between the agent and the application.

AG-UI natively supports all of the above generative UI specs and allows developers to define **their own custom generative UI standards** as well.

---

## File: docs/concepts/messages.mdx

---
title: "Messages"
---

# Messages

Messages form the backbone of communication in the AG-UI protocol. They
represent the conversation history between users and AI agents, and provide a
standardized way to exchange information regardless of the underlying AI service
being used.

## Message Structure

AG-UI messages follow a vendor-neutral format, ensuring compatibility across
different AI providers while maintaining a consistent structure. This allows
applications to switch between AI services (like OpenAI, Anthropic, or custom
models) without changing the client-side implementation.

The basic message structure includes:

```typescript
interface BaseMessage {
  id: string // Unique identifier for the message
  role: string // The role of the sender (user, assistant, system, tool, reasoning)
  content?: string // Optional text content of the message
  name?: string // Optional name of the sender
  encryptedContent?: string // Optional encrypted content for privacy-preserving state continuity
  metadata?: Record<string, any> // Optional extra information attached to the message
}
```

The `role` discriminator can be `"user"`, `"assistant"`, `"system"`, `"tool"`,
`"developer"`, `"activity"`, or `"reasoning"`. Concrete message types extend
this shape with the fields they need.

Every message type carries `metadata`, an optional open-by-key object that
accumulates as the message is built from its events. Tool calls carry one of
their own. See [Metadata](/concepts/metadata) for the rules.

> The `encryptedContent` field enables privacy-preserving workflows where
> sensitive content (such as reasoning chains) can be passed across turns
> without exposing the raw content. This is particularly useful for zero data
> retention (ZDR) compliance and `store:false` scenarios.

## Message Types

AG-UI supports several message types to accommodate different participants in a
conversation:

### User Messages

Messages from the end user to the agent:

```typescript
interface UserMessage {
  id: string
  role: "user"
  content: string | InputContent[] // Text or multimodal input from the user
  name?: string // Optional user identifier
}

type InputContent =
  | TextInputContent
  | ImageInputContent
  | AudioInputContent
  | VideoInputContent
  | DocumentInputContent

interface InputContentDataSource {
  type: "data"
  value: string
  mimeType: string
}

interface InputContentUrlSource {
  type: "url"
  value: string
  mimeType?: string
}

type InputContentSource = InputContentDataSource | InputContentUrlSource

interface TextInputContent {
  type: "text"
  text: string
}

interface ImageInputContent {
  type: "image"
  source: InputContentSource
  metadata?: Record<string, unknown>
}

interface AudioInputContent {
  type: "audio"
  source: InputContentSource
  metadata?: Record<string, unknown>
}

interface VideoInputContent {
  type: "video"
  source: InputContentSource
  metadata?: Record<string, unknown>
}

interface DocumentInputContent {
  type: "document"
  source: InputContentSource
  metadata?: Record<string, unknown>
}
```

> In Python, the previous `BinaryInputContent` model is deprecated and remains
> temporarily available as a compatibility path.

This structure keeps traditional plain-text inputs working while enabling richer
payloads such as images, audio clips, or uploaded files in the same message.

### Assistant Messages

Messages from the AI assistant to the user:

```typescript
interface AssistantMessage {
  id: string
  role: "assistant"
  content?: string // Text response from the assistant (optional if using tool calls)
  name?: string // Optional assistant identifier
  toolCalls?: ToolCall[] // Optional tool calls made by the assistant
  encryptedContent?: string // Optional encrypted content for state continuity
}
```

### System Messages

Instructions or context provided to the agent:

```typescript
interface SystemMessage {
  id: string
  role: "system"
  content: string // Instructions or context for the agent
  name?: string // Optional identifier
}
```

### Tool Messages

Results from tool executions:

```typescript
interface ToolMessage {
  id: string
  role: "tool"
  content: string // Result from the tool execution
  toolCallId: string // ID of the tool call this message responds to
  error?: string // Optional error message if the tool execution failed
  encryptedValue?: string // Optional encrypted reasoning for state continuity
}
```

Key points:

- The `toolCallId` links the result back to the original tool call
- Use `error` to indicate tool execution failures
- Use `encryptedValue` to attach encrypted chain-of-thought related to how the
  agent interpreted or processed the tool result

### Activity Messages

Structured UI messages that exist only on the frontend.  Used for progress,
status, or any custom visual element that shouldn’t be sent to the model:

```typescript
interface ActivityMessage {
  id: string
  role: "activity"
  activityType: string // e.g. "PLAN", "SEARCH", "SCRAPE"
  content: Record<string, any> // Structured payload rendered by the frontend
}
```

Key points

- Emitted via `ACTIVITY_SNAPSHOT` and `ACTIVITY_DELTA` to support live,
  updateable UI (checklists, steps, search-in-progress, etc.).
- **Frontend-only:** never forwarded to the agent, so no filtering and no LLM
  confusion.
- **Customizable:** define your own `activityType` and `content` and render a
  matching UI component.
- **Streamable:** can be updated over time for long-running operations.
- Helps persist/restore custom events by turning them into durable message
  objects.

### Developer Messages

Internal messages used for development or debugging:

```typescript
interface DeveloperMessage {
  id: string
  role: "developer"
  content: string
  name?: string
}
```

### Reasoning Messages

Messages representing the agent's internal reasoning or chain-of-thought
process:

```typescript
interface ReasoningMessage {
  id: string
  role: "reasoning"
  content: string // Reasoning content (visible to client)
  encryptedValue?: string // Optional encrypted reasoning for state continuity
}
```

<Tip>
  Unlike Activity messages, Reasoning messages are intended to represent the
  agent's internal thought process and may be encrypted for privacy and are
  meant to be sent back to the agent for further processing on subsequent turns.
</Tip>

Key points:

- Emitted via `REASONING_MESSAGE_START`, `REASONING_MESSAGE_CONTENT`, and
  `REASONING_MESSAGE_END` events.
- **Visibility control:** Content may be visible to users (as a summary) or
  fully encrypted.
- **Encrypted values:** Use `REASONING_ENCRYPTED_VALUE` events to attach
  encrypted chain-of-thought to messages or tool calls without exposing content.
- **State continuity:** Encrypted reasoning items can be passed across
  conversation turns without exposing raw chain-of-thought.
- **Privacy-first:** Supports `store:false` and zero data retention (ZDR)
  policies while preserving reasoning capabilities.
- **Separate from assistant messages:** Reasoning is kept distinct from final
  responses to avoid polluting the conversation history.

See [Reasoning Events](/concepts/events#reasoning-events) for the streaming
event lifecycle.

## Vendor Neutrality

AG-UI messages are designed to be vendor-neutral, meaning they can be easily
mapped to and from proprietary formats used by various AI providers:

```typescript
// Example: Converting AG-UI messages to OpenAI format
const openaiMessages = agUiMessages
  .filter((msg) => ["user", "system", "assistant"].includes(msg.role))
  .map((msg) => ({
    role: msg.role as "user" | "system" | "assistant",
    content: msg.content || "",
    // Map tool calls if present
    ...(msg.role === "assistant" && msg.toolCalls
      ? {
          tool_calls: msg.toolCalls.map((tc) => ({
            id: tc.id,
            type: tc.type,
            function: {
              name: tc.function.name,
              arguments: tc.function.arguments,
            },
          })),
        }
      : {}),
  }))
```

This abstraction allows AG-UI to serve as a common interface regardless of the
underlying AI service.

## Message Synchronization

Messages can be synchronized between client and server through two primary
mechanisms:

### Complete Snapshots

The `MESSAGES_SNAPSHOT` event provides a complete view of all messages in a
conversation:

```typescript
interface MessagesSnapshotEvent {
  type: EventType.MESSAGES_SNAPSHOT
  messages: Message[] // Complete array of all messages
}
```

This is typically used:

- When initializing a conversation
- After connection interruptions
- When major state changes occur
- To ensure client-server synchronization

### Streaming Messages

For real-time interactions, new messages can be streamed as they're generated:

1. **Start a message**: Indicate a new message is being created

   ```typescript
   interface TextMessageStartEvent {
     type: EventType.TEXT_MESSAGE_START
     messageId: string
     role: string
   }
   ```

2. **Stream content**: Send content chunks as they become available

   ```typescript
   interface TextMessageContentEvent {
     type: EventType.TEXT_MESSAGE_CONTENT
     messageId: string
     delta: string // Text chunk to append
   }
   ```

3. **End a message**: Signal the message is complete
   ```typescript
   interface TextMessageEndEvent {
     type: EventType.TEXT_MESSAGE_END
     messageId: string
   }
   ```

This streaming approach provides a responsive user experience with immediate
feedback.

## Tool Integration in Messages

AG-UI messages elegantly integrate tool usage, allowing agents to perform
actions and process their results:

### Tool Calls

Tool calls are embedded within assistant messages:

```typescript
interface ToolCall {
  id: string // Unique ID for this tool call
  type: "function" // Type of tool call
  function: {
    name: string // Name of the function to call
    arguments: string // JSON-encoded string of arguments
  }
}
```

Example assistant message with tool calls:

```typescript
{
  id: "msg_123",
  role: "assistant",
  content: "I'll help you with that calculation.",
  toolCalls: [
    {
      id: "call_456",
      type: "function",
      function: {
        name: "calculate",
        arguments: '{"expression": "24 * 7"}'
      }
    }
  ]
}
```

### Tool Results

Results from tool executions are represented as tool messages:

```typescript
{
  id: "result_789",
  role: "tool",
  content: "168",
  toolCallId: "call_456" // References the original tool call
}
```

This creates a clear chain of tool usage:

1. Assistant requests a tool call
2. Tool executes and returns a result
3. Assistant can reference and respond to the result

## Streaming Tool Calls

Similar to text messages, tool calls can be streamed to provide real-time
visibility into the agent's actions:

1. **Start a tool call**:

   ```typescript
   interface ToolCallStartEvent {
     type: EventType.TOOL_CALL_START
     toolCallId: string
     toolCallName: string
     parentMessageId?: string // Optional link to parent message
   }
   ```

2. **Stream arguments**:

   ```typescript
   interface ToolCallArgsEvent {
     type: EventType.TOOL_CALL_ARGS
     toolCallId: string
     delta: string // JSON fragment to append to arguments
   }
   ```

3. **End a tool call**:
   ```typescript
   interface ToolCallEndEvent {
     type: EventType.TOOL_CALL_END
     toolCallId: string
   }
   ```

This allows frontends to show tools being invoked progressively as the agent
constructs its reasoning.

## Practical Example

Here's a complete example of a conversation with tool usage:

```typescript
// Conversation history
;[
  // User query
  {
    id: "msg_1",
    role: "user",
    content: "What's the weather in New York?",
  },

  // Assistant response with tool call
  {
    id: "msg_2",
    role: "assistant",
    content: "Let me check the weather for you.",
    toolCalls: [
      {
        id: "call_1",
        type: "function",
        function: {
          name: "get_weather",
          arguments: '{"location": "New York", "unit": "celsius"}',
        },
      },
    ],
  },

  // Tool result
  {
    id: "result_1",
    role: "tool",
    content:
      '{"temperature": 22, "condition": "Partly Cloudy", "humidity": 65}',
    toolCallId: "call_1",
  },

  // Assistant's final response using tool results
  {
    id: "msg_3",
    role: "assistant",
    content:
      "The weather in New York is partly cloudy with a temperature of 22°C and 65% humidity.",
  },
]
```

## Conclusion

The message structure in AG-UI enables sophisticated conversational AI
experiences while maintaining vendor neutrality. By standardizing how messages
are represented, synchronized, and streamed, AG-UI provides a consistent way to
implement interactive human-agent communication regardless of the underlying AI
service.

This system supports everything from simple text exchanges to complex tool-based
workflows, all while optimizing for both real-time responsiveness and efficient
data transfer.

---

## File: docs/concepts/middleware.mdx

---
title: "Middleware"
---

# Middleware

Middleware in AG-UI provides a powerful way to transform, filter, and augment the event streams that flow through agents. It enables you to add cross-cutting concerns like logging, authentication, rate limiting, and event filtering without modifying the core agent logic.

Examples below assume the relevant RxJS operators/utilities (`map`, `tap`, `catchError`, `switchMap`, `timer`, etc.) are imported.

## What is Middleware?

Middleware sits between the agent execution and the event consumer, allowing you to:

1. **Transform events** – Modify or enhance events as they flow through the pipeline
2. **Filter events** – Selectively allow or block certain events
3. **Add metadata** – Inject additional context or tracking information
4. **Handle errors** – Implement custom error recovery strategies
5. **Monitor execution** – Add logging, metrics, or debugging capabilities

## How Middleware Works

Middleware forms a chain where each middleware wraps the next, creating layers of functionality. When an agent runs, the event stream flows through each middleware in sequence.

```typescript
import { AbstractAgent } from "@ag-ui/client"

const agent = new MyAgent()

// Middleware chain: logging -> auth -> filter -> agent
agent.use(loggingMiddleware, authMiddleware, filterMiddleware)

// When agent runs, events flow through all middleware
await agent.runAgent()
```

Middleware added with `agent.use(...)` is applied in `runAgent()`. `connectAgent()` currently calls `connect()` directly and does not run middleware.

## Function-Based Middleware

For simple transformations, you can use function-based middleware. This is the most concise way to add middleware:

```typescript
import { MiddlewareFunction } from "@ag-ui/client"
import { EventType } from "@ag-ui/core"

const prefixMiddleware: MiddlewareFunction = (input, next) => {
  return next.run(input).pipe(
    map(event => {
      if (
        event.type === EventType.TEXT_MESSAGE_CHUNK ||
        event.type === EventType.TEXT_MESSAGE_CONTENT
      ) {
        return {
          ...event,
          delta: `[AI]: ${event.delta}`
        }
      }
      return event
    })
  )
}

agent.use(prefixMiddleware)
```

## Class-Based Middleware

For more complex scenarios requiring state or configuration, use class-based middleware:

```typescript
import { Middleware } from "@ag-ui/client"
import { Observable } from "rxjs"
import { tap } from "rxjs/operators"

class MetricsMiddleware extends Middleware {
  private eventCount = 0

  constructor(private metricsService: MetricsService) {
    super()
  }

  run(input: RunAgentInput, next: AbstractAgent): Observable {
    const startTime = Date.now()

    return this.runNext(input, next).pipe(
      tap(event => {
        this.eventCount++
        this.metricsService.recordEvent(event.type)
      }),
      finalize(() => {
        const duration = Date.now() - startTime
        this.metricsService.recordDuration(duration)
        this.metricsService.recordEventCount(this.eventCount)
      })
    )
  }
}

agent.use(new MetricsMiddleware(metricsService))
```

If you are writing class middleware, prefer the helper methods:
- `runNext(input, next)` normalizes chunk events into full `TEXT_MESSAGE_*`/`TOOL_CALL_*` sequences.
- `runNextWithState(input, next)` also provides accumulated `messages` and `state` after each event.

## Built-in Middleware

AG-UI provides several built-in middleware components for common use cases:

### FilterToolCallsMiddleware

Filter tool calls based on allowed or disallowed lists:

```typescript
import { FilterToolCallsMiddleware } from "@ag-ui/client"

// Only allow specific tools
const allowedFilter = new FilterToolCallsMiddleware({
  allowedToolCalls: ["search", "calculate"]
})

// Or block specific tools
const blockedFilter = new FilterToolCallsMiddleware({
  disallowedToolCalls: ["delete", "modify"]
})

agent.use(allowedFilter)
```

`FilterToolCallsMiddleware` filters emitted `TOOL_CALL_*` events. It does not block tool execution in the upstream model/runtime.

## Middleware Patterns

Common patterns include logging, auth via `forwardedProps`, and rate limiting. See the [JS middleware reference](/sdk/js/client/middleware) for concrete implementations.

## Combining Middleware

You can combine multiple middleware to create sophisticated processing pipelines:

```typescript
const logMiddleware: MiddlewareFunction = (input, next) => next.run(input)
const metricsMiddleware = new MetricsMiddleware(metricsService)
const filterMiddleware = new FilterToolCallsMiddleware({ allowedToolCalls: ["search"] })

agent.use(logMiddleware, metricsMiddleware, filterMiddleware)
```

## Execution Order

Middleware executes in the order it's added, with each middleware wrapping the next:

1. First middleware receives the original input
2. It can modify the input before passing to the next middleware
3. Each middleware processes events from the next in the chain
4. The final middleware calls the actual agent

```typescript
agent.use(middleware1, middleware2, middleware3)

// Execution flow:
// → middleware1
//   → middleware2
//     → middleware3
//       → agent.run()
//     ← events flow back through middleware3
//   ← events flow back through middleware2
// ← events flow back through middleware1
```

## Best Practices

1. **Keep middleware focused** – Each middleware should have a single responsibility
2. **Handle errors gracefully** – Use RxJS error handling operators
3. **Avoid blocking operations** – Use async patterns for I/O operations
4. **Document side effects** – Clearly indicate if middleware modifies state
5. **Test middleware independently** – Write unit tests for each middleware
6. **Consider performance** – Be mindful of processing overhead in the event stream

## Advanced Use Cases

### Conditional Middleware

Apply middleware based on runtime conditions:

```typescript
const conditionalMiddleware: MiddlewareFunction = (input, next) => {
  if (input.forwardedProps?.debug === true) {
    // Apply debug logging
    return next.run(input).pipe(
      tap(event => console.debug(event))
    )
  }
  return next.run(input)
}
```

For event transformation and stream-control variants, see the [JS middleware reference](/sdk/js/client/middleware).

## Conclusion

Middleware provides a flexible and powerful way to extend AG-UI agents without modifying their core logic. Whether you need simple event transformation or complex stateful processing, the middleware system offers the tools to build robust, maintainable agent applications.