AG-UI DevTools

May 13, 2026 · View on GitHub

CI License: MIT

Developer tools for the AG-UI protocol. Inspect, debug, and replay AI agent sessions with a local web UI.

Why AG-UI DevTools?

AI agent applications are opaque at runtime — you send a message and get a response, but what happened in between? Which tools were called, what state changed, why did the agent make that decision? AG-UI DevTools makes agent behavior transparent by recording every protocol event, capturing screenshots and DOM state, and presenting it all in a structured, replayable format.

Who is this for? Developers building apps with AG-UI-compatible agents — CopilotKit, LangGraph, LM Studio, Ollama, or any server implementing the AG-UI protocol — who need observability into agent sessions during development.

Features

  • Event recording — Capture all AG-UI protocol events (messages, tool calls, state deltas, reasoning, approvals, MCP requests, and more)
  • 12 inspection panels — Timeline, event stream, state diff, tool calls, approvals, screenshots, MCP inspector, session replay, Playwright export, traces, generative UI, sessions
  • Session replay — Step through recorded sessions event-by-event with state restoration
  • Live agent integration — Run agent sessions directly from the DevTools UI via HttpAgent
  • Dual storage — Server-side SQLite + client-side IndexedDB with automatic fallback
  • Real-time streaming — SSE-based live event streaming with 30-second heartbeat
  • React integration — Drop-in AGUIDevToolsProvider and useDevToolsRecorder hook
  • Screenshot and DOM capture — Automatic periodic screenshots and DOM snapshots via MutationObserver
  • Playwright export — Export recorded sessions as runnable Playwright test scripts
  • Multiple integration patterns — Class-based recorder, React provider, or standalone event capture

Quick Start

git clone <repo-url> ag-ui-devtools-sdk
cd ag-ui-devtools-sdk
pnpm install
pnpm build:sdk
pnpm dev:all

This starts the DevTools UI on http://localhost:5173 and the server on http://localhost:3100.

Architecture

flowchart LR
  App["Host app + AG-UI agent"]
  SDK["@ag-ui-devtools/sdk"]
  IDB["IndexedDB"]
  Server["NestJS + SQLite"]
  UI["DevTools React UI"]

  App -->|subscribe| SDK
  SDK --> IDB
  SDK -->|POST events| Server
  UI -->|REST / SSE| Server
  UI -->|fallback| IDB
  UI -->|runAgent HttpAgent| App

The SDK runs inside your app. It records agent events and sends them to the DevTools server (with IndexedDB as a local fallback). The DevTools UI reads events from the server via REST and SSE, and can also launch live agent sessions by connecting to any AG-UI-compatible endpoint.

Monorepo Structure

ag-ui-devtools-sdk/
├── packages/
│   └── sdk/                # @ag-ui-devtools/sdk
│       ├── src/
│       │   ├── index.ts     # Public API exports
│       │   ├── recorder.ts  # Core event recorder with batching
│       │   ├── storage.ts   # IndexedDB persistence layer
│       │   ├── provider.tsx # React context provider + Error Boundary
│       │   └── types.ts     # Type definitions
│       ├── dist/
│       ├── package.json
│       └── tsconfig.json
├── apps/
│   └── devtools/           # DevTools application
│       ├── src/            # React UI (Vite + Tailwind)
│       ├── server/         # NestJS backend (SQLite via Drizzle)
│       ├── package.json
│       └── vite.config.ts
├── .github/
│   └── workflows/
│       └── ci.yml          # GitHub Actions CI (Node 18/20/22)
├── Dockerfile              # Multi-stage production build
├── eslint.config.js
├── .prettierrc
└── vitest.config.ts

Prerequisites

  • Node.js >= 18
  • pnpm >= 8 (npm install -g pnpm)

Using the SDK in Your App

Install

# From this repo's root
cd packages/sdk
npm link

# In your app
npm link @ag-ui-devtools/sdk

Option 1: Attach to any AG-UI agent

import { AGUIDevToolsRecorder } from '@ag-ui-devtools/sdk';

const recorder = new AGUIDevToolsRecorder({
  serverUrl: 'http://localhost:3100',
  captureScreenshots: true,
  captureDOM: true,
});

agent.subscribe(recorder.subscriber);

Option 2: React Provider

Wrap your app with AGUIDevToolsProvider and use the useDevToolsRecorder hook to access the recorder, sessions, and events from any component:

import { AGUIDevToolsProvider, useDevToolsRecorder } from '@ag-ui-devtools/sdk';

function App() {
  return (
    <AGUIDevToolsProvider config={{ serverUrl: 'http://localhost:3100' }}>
      <YourApp />
    </AGUIDevToolsProvider>
  );
}

function DevPanel() {
  const { recorder, sessions, activeEvents, isRecording } = useDevToolsRecorder();
  // ...
}

Option 3: Standalone event capture

import { AGUIDevToolsRecorder } from '@ag-ui-devtools/sdk';

const recorder = new AGUIDevToolsRecorder();

recorder.onEvent((event) => {
  console.log('Captured:', event.event.type, event.eventIndex);
});

SDK API

AGUIDevToolsRecorder — the main class:

MethodDescription
subscriberGetter — pass to agent.subscribe()
onEvent(callback)Register a per-event callback; returns an unsubscribe function
getCurrentSession()Returns the current DevToolsSession or null
loadAllSessions()Load all persisted sessions from IndexedDB
loadSessionEvents(id)Load events for a specific session
deleteSession(id)Delete a session and its events
destroy()Clean up all listeners and stop recording

useDevToolsRecorder() hook — returns { recorder, sessions, activeEvents, refreshSessions, loadSessionEvents, isRecording }.

SDK Configuration

OptionDefaultDescription
serverUrlhttp://localhost:3100DevTools server URL
projectNameDefault ProjectProject bucket on the server (auto-created)
projectIdOptional local IndexedDB project association
sessionNameOverride auto-generated session name
apiKeySends x-api-key when the server has API_KEY set
captureScreenshotstrueCapture periodic PNG screenshots via html-to-image
captureDOMtrueCapture DOM snapshots via MutationObserver
screenshotInterval5000Screenshot interval in ms (minimum 1000)
persistToIndexedDBtruePersist events locally as fallback
maxEventsPerSession50000Max events before auto-close
onEventCallback fired for each captured event
onSessionStartCallback fired when a session starts
onSessionEndCallback fired when a session ends
onErrorconsole.warnCustom error handler

Development

pnpm dev             # DevTools UI only (port 5173)
pnpm dev:server      # NestJS server only (port 3100)
pnpm dev:all         # Both UI and server concurrently

Build

pnpm build:sdk       # SDK package only
pnpm build           # SDK + DevTools UI
pnpm build:all       # SDK + UI + server

Production Deployment

The NestJS server serves the built UI and API on one port (default 3100).

pnpm build:all
cd apps/devtools/server && node dist/main.js

The Docker image is a self-contained production build:

docker build -t ag-ui-devtools .
docker run -p 3100:3100 \
  -e API_KEY=your-key \
  -e CORS_ORIGINS=https://your-app.com \
  ag-ui-devtools

The image runs as a non-root user and includes an automatic health check against /health.

Server Configuration

Environment variables (see .env.example):

VariableDefaultDescription
PORT3100Server port
API_KEY(none)API key for authentication (optional)
CORS_ORIGINShttp://localhost:5173,http://localhost:3000Comma-separated allowed origins
DATABASE_PATH(relative to server)SQLite database path
LOG_LEVELinfoLogging level: debug, info, warn, error
RATE_LIMIT_WINDOW_MS60000Rate limit window in ms
RATE_LIMIT_MAX_REQUESTS200Max requests per window per IP
TRUST_PROXY(none)Set to true or 1 to trust the first proxy, or loopback for loopback only

DevTools UI build-time variables:

VariableDefaultDescription
VITE_API_BASEhttp://localhost:3100/apiBackend API URL
VITE_API_KEY(none)API key embedded in bundle (development only — see Security)

Server Endpoints

MethodPathDescription
GET/healthHealth check (uptime, memory, DB status)
GET/api/sessionsList sessions (filter by ?projectId=)
GET/api/sessions/statsAggregate session statistics
GET/api/sessions/:idGet session by ID
POST/api/sessionsCreate session
PATCH/api/sessions/:idUpdate session
DELETE/api/sessions/:idDelete session
GET/api/sessions/:sessionId/eventsList session events
POST/api/eventsIngest single event
POST/api/events/batchIngest event batch (max 500 per request)
GET/api/sessions/:sessionId/streamSSE event stream (30s heartbeat)
GET/api/projectsList projects
POST/api/projectsCreate project
GET/api/projects/:idGet project by ID
DELETE/api/projects/:idDelete project and cascade sessions/events

Rate Limiting

Per-IP fixed-window rate limiting on all /api routes. Returns 429 with a Retry-After header when exceeded.

Graceful Shutdown

On SIGTERM or SIGINT, the server completes active SSE streams, stops accepting new connections, closes the SQLite database, and exits.

Security Considerations

Frontend API key exposure: VITE_API_KEY is embedded in the JavaScript bundle at build time. Anyone with access to the DevTools UI can extract it. Only use VITE_API_KEY in development. For production:

  • Place the DevTools server behind a reverse proxy (Nginx, Cloudflare) that handles authentication at the infrastructure level.
  • Use network-level access controls (VPN, private VPC, IP allowlisting).
  • If the UI must be publicly accessible, implement a user-facing login that issues short-lived tokens.

SSE query parameter limitation: The EventSource API does not support custom headers. When API_KEY is set, SSE streams transmit the key as a ?api_key= query parameter, which exposes it in server logs, browser history, and Referer headers. Mitigate with HTTPS and prefer x-api-key header for non-SSE requests.

Connecting to an LLM Provider

The DevTools UI runs agent sessions via HttpAgent from @ag-ui/client. Any server that implements the AG-UI protocol works — you just need the endpoint URL.

Setup

  1. Start your LLM provider (see provider-specific instructions below)
  2. Open the DevTools UI (http://localhost:5173)
  3. In the Sessions panel, click the config button and enter your endpoint URL and optional API key
  4. Type a message and send it to start a live agent session

Settings are persisted to localStorage and survive browser restarts.

Provider Endpoints

ProviderEndpoint URLSetup
LM Studiohttp://localhost:1234/v1/agentOpen LM Studio, load a model, start the local server (default port 1234)
Ollamahttp://localhost:11434/v1/agentInstall Ollama, run ollama serve, then ollama run <model>
CopilotKitYour app's AG-UI endpointAdd @ag-ui-devtools/sdk to your CopilotKit app (see SDK usage)
LangGraphYour LangGraph server URLDeploy a LangGraph server with AG-UI support and point to its endpoint
CustomAny AG-UI-compatible URLAny server implementing the AG-UI protocol

The endpoint URL is the only required field. The API key is sent as an Authorization: Bearer <key> header and is optional (most local providers don't require one).

Quality

pnpm test            # Run all tests
pnpm test:watch      # Watch mode
pnpm typecheck       # Type checking across all packages
pnpm lint            # ESLint
pnpm lint:fix        # ESLint with auto-fix
pnpm format          # Prettier
pnpm format:check    # Prettier check

CI/CD

GitHub Actions runs on every push/PR to main — type checking, ESLint, production build, and test suite across Node.js 18, 20, and 22.

Peer Dependencies

  • @ag-ui/client >= 0.0.40
  • @ag-ui/core >= 0.0.40
  • react >= 18.0.0 (optional, for React Provider)

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Make your changes and add tests
  4. Ensure pnpm typecheck, pnpm lint, and pnpm test all pass
  5. Open a pull request

Versioning

This project follows Semantic Versioning. The SDK is currently at 0.1.0 — the public API may change between minor versions until 1.0.0. The server database schema uses automatic migrations on startup; no manual migration steps are required.

License

MIT