Eagle eyes on your agents. An orchestrator built for full observability into what your AI agents are doing, right now.
Every agent run, log line, and context item traced in a structured span tree. Know exactly what happened and when.
A single background process owns all state. Agents survive terminal sessions. All clients get live push events.
Any CLI agent, any workflow. One TypeScript config file. Hooks, plugins, and attach scripts — all customizable.
adlerd is the single authority over all sessions and agent processes. The CLI and TUI are thin clients — they send commands or subscribe to events over a Unix socket. Persistence is hidden behind a Storage interface, making the backend swappable.
Instead of separate tables for agents, workflow steps, and hooks, adler uses a single spans table for every unit of work. A kind field says what it is. Adding new kinds — workflow steps, hooks, assistant runs — costs nothing: no schema change, no migration.
Everything that happens is an event with an open-ended type string and a JSON payload. This is the OpenTelemetry model applied to agent orchestration.
Context flows through environment variables — the subprocess equivalent of W3C Trace Context over HTTP headers. When the daemon spawns an agent it injects the span context. If that agent calls adler agent run, the CLI reads ADLER_SPAN_ID from its own environment and passes it as the parent. Propagation works at any depth automatically.
Running adler with no arguments opens a live dashboard. The TUI holds an open socket connection to the daemon and re-renders on push events — no polling. Five tabs cover every view you need.
Every adler agent run follows the same flow. The daemon is the authority throughout — spawning, tracking, streaming output, and broadcasting to any connected TUI clients in real time.
SDK connects to socket. Auto-starts daemon if not running.
Daemon creates a span (kind=agent) in SQLite via Storage interface.
Daemon calls Bun.spawn() with PTY. Injects ADLER_* env vars.
Each stdout line → agent.output event in DB → pushed to TUI.
On exit: span updated to done/failed, event emitted, TUI re-renders.
All commands are thin wrappers around SDK calls. Session context is resolved automatically from --session flag, ADLER_SESSION env, or .adler/.session file.
adler is configured with a TypeScript file. Global config at ~/.config/adler/adler.ts, project config at .adler/adler.ts. Project config merges over global. Agents are just functions returning shell commands.
import type { AdlerConfig } from "@adler/sdk"
const config: AdlerConfig = {
agent: {
agents: {
// Any CLI agent — return a shell command string
opencode: ({ prompt, subagent }) =>
`opencode run --agent ${subagent} "${prompt}"`,
},
// Invoked when pressing 'o' on an agent in the TUI
attach: ({ agentId }) =>
`tmux new-window "adler agent read --name ${agentId}"`,
},
}
export default config
Each phase produces a working, useful system. The span and event data model is designed so that Phases 3 and 4 add capabilities without touching the schema.
The foundation. A global daemon managing sessions and agents. Full SQLite-backed span/event tracing. SDK, CLI, and a live Ink dashboard with five tabs — overview, context, agents, traces, and logs.
YAML or TypeScript workflow definitions with sequential and parallel steps. Before/after hooks for any adler event. npm plugin system for distributing agent configs — first-party plugin: @adler/opencode.
An AI agent with full awareness of the current session — all spans, events, and context. Ask it anything about the session, or let it auto-orchestrate: read state, decide what to run next, iterate until done.
A browser dashboard built on @adler/sdk — just another client. Remote daemon support via TCP socket allows connecting from anywhere. Multi-user sessions for team visibility.