---
url: /blog/2026/06/16/electric-agents-0-6-from-runtime-to-app.md
description: >-
  Electric Agents 0.6 rounds out the platform launched in April with a broader
  SDK and runtime surface for long-lived entities, StreamDB state, runners,
  wakes, signals, schedules, app APIs, and multi-agent coordination.
---

# Electric Agents 0.6

Electric Agents 0.6 is out today. It rounds out the [platform we launched in April](/blog/2026/04/29/introducing-electric-agents) with a broader SDK and runtime surface for building agentic systems.

* **Core APIs.** [Long-lived entities](/docs/agents/usage/defining-entities), [StreamDB state](/docs/streams/stream-db), [local and remote runners](/docs/agents/usage/embedded-builtins), [spawning and forking](/docs/agents/usage/spawning-and-coordinating), [wakes](/docs/agents/usage/waking-entities), [signals](/docs/agents/usage/signals), [schedules](/docs/agents/usage/programmatic-runtime-client#schedules), [self-sends](/docs/agents/usage/writing-handlers#sending-messages), [app APIs](/docs/agents/usage/programmatic-runtime-client), and [multi-agent coordination patterns](/docs/agents/usage/spawning-and-coordinating).
* **Apps in development.** Desktop and mobile devtools for inspecting and controlling agent systems. Download canary builds from [GitHub releases](https://github.com/electric-sql/electric/releases) or build from source.
* **Cloud next.** Managed Agents servers in Electric Cloud are coming soon.

> \[!Info] Get started with Electric Agents
> Run the [Quickstart](/docs/agents/quickstart), read the [docs](/docs/agents/), or revisit the [original launch post](/blog/2026/04/29/introducing-electric-agents).

## The Electric Agents stack

The ecosystem is converging on a thesis: the agent is the log. If you accept that, the rest of the stack follows.

If the agent is the log, the log has to outlive any single process or device — and if multiple readers need to observe it (UIs, supervisors, other agents), it has to sync. **[Durable Streams](/docs/streams/)** are append-only logs that do both.

Raw logs aren't ergonomic. You want typed projections — messages, runs, tool calls, errors, children — that update live as events land. **[StreamDB](/docs/streams/stream-db)** projects those collections over the stream.

Projections need queries: filter, join, aggregate for a UI timeline or an agent's context window. **[TanStack DB](/sync/tanstack-db)** is the reactive query layer.

At this point you have durable, syncable, queryable agent state. What's missing is compute. Something has to run the LLM loop, call tools, and write the results back. And something has to track which entities exist, route messages, [schedule wakes](/docs/agents/usage/waking-entities), and dispatch work. The **[Agents runtime](/docs/agents/usage/overview)** is that control plane.

[Runners](/docs/agents/usage/embedded-builtins) do the compute; the runtime coordinates. A runner can live on your laptop, in your infrastructure, in CI, or anywhere you control. Because coordination and compute are separate, you can start a session on your machine, leave the runner there, then open the same session from your phone to send a follow-up or stop it.

Managed Agents servers in Electric Cloud are coming soon — hosted coordination, user-owned compute.

## Every entity is a StreamDB

In Electric Agents, the agent is the durable stream, not the process currently handling it.

* An [Electric Agents entity](/docs/agents/usage/defining-entities) is a long-lived, addressable thing: an assistant, worker, coding session, support ticket, lead researcher, orchestrator, monitor, or any agent type you define.
* Every entity has a durable stream, which is the log of what happened.
* Every entity also has a typed [StreamDB projection](/docs/streams/stream-db). That projection gives you live state: timeline, inbox, runs, tool calls, context, errors, children, signals, and [custom collections](/docs/agents/usage/managing-state).
* The process that handles a wake can come and go. The entity persists. It can sleep, wake, replay, fork, spawn children, and be observed by apps or other agents.

## Demos and videos

### Logical entities

See how Electric Agents models agents as durable, addressable entities. Each entity is backed by a durable stream and has its own URL, so apps, agents, and [runtime APIs](/docs/agents/usage/programmatic-runtime-client) can all refer to the same long-lived thing.

Watch on YouTube: [Electric Agents logical entities demo](https://www.youtube.com/watch?v=AhQRJ_9yOFw)

### Custom entities

Define your own [entity types](/docs/agents/usage/defining-entities) with [custom state](/docs/agents/usage/managing-state), [handlers](/docs/agents/usage/writing-handlers), [permissions](/docs/agents/usage/permissions-and-principals), and [tools](/docs/agents/usage/defining-tools).

Watch on YouTube: [Electric Agents custom entities demo](https://www.youtube.com/watch?v=xKo3iqbDkI4)

### State

Inspect an entity's live [StreamDB state](/docs/streams/stream-db): messages, runs, tool calls, child status, and custom collections.

Watch on YouTube: [Electric Agents state demo](https://www.youtube.com/watch?v=GoADVUN_BAQ)

### Forking and spawning

Spawning starts a fresh child entity. Forking branches an existing entity from a historical point in its stream, preserving the useful context while opening an alternative path forward.

Watch on YouTube: [Electric Agents spawn and fork demo](https://www.youtube.com/watch?v=sG8NHMX0NPM)

### Child agents

Use child agents to split work into separately owned streams that the parent can observe and coordinate. A spawned child can receive instructions, perform operations, and report back through its own durable state.

Watch on YouTube: [Electric Agents child agent demo](https://www.youtube.com/watch?v=TwPFeDzX8S4)

### Signals

[Signals](/docs/agents/usage/signals) give operators and apps a control plane for active work: `SIGINT`, pause, resume, kill, and handler-level lifecycle events.

Watch on YouTube: [Electric Agents signals demo](https://www.youtube.com/watch?v=WqkmhQM2X-Q)

### PG sync triggers

[Postgres changes](/docs/agents/usage/programmatic-runtime-client#registerpgsyncsource) can flow through sync and wake an agent when the data it cares about changes.

Watch on YouTube: [Electric Agents PG sync triggers demo](https://www.youtube.com/watch?v=0dH9tJDHvI0)

### Send to self

An agent can send itself a future message to sleep now and continue work later.

Watch on YouTube: [Electric Agents send to self demo](https://www.youtube.com/watch?v=B3pWzh6KouA)

### Cron

[Cron schedules](/docs/agents/usage/programmatic-runtime-client#schedules) wake agents on recurring intervals without keeping a worker process alive.

Watch on YouTube: [Electric Agents cron demo](https://www.youtube.com/watch?v=iPczPCOLJLs)

## Core APIs

### Define

Define [entity types](/docs/agents/usage/defining-entities) with schemas, handlers, [permissions](/docs/agents/usage/permissions-and-principals), and [tools](/docs/agents/usage/defining-tools). This is where you decide what kind of long-lived thing exists in the system, what state it owns, and what code runs when it wakes. `SDK`

```ts
const registry = createEntityRegistry()

registry.define("assistant", {
  description: "A project-aware assistant",
  state: {
    notes: {
      schema: z.object({ id: z.string(), text: z.string() }),
      primaryKey: "id",
    },
  },
  async handler(ctx) {
    // ...
  },
})
```

### Run

Run an agent loop that persists runs, text, reasoning, tool calls, and errors to the entity stream. The handler can do normal application work before or after the LLM loop; `ctx.useAgent()` and `ctx.agent.run()` record the agent trace. See [writing handlers](/docs/agents/usage/writing-handlers) and [configuring the agent loop](/docs/agents/usage/configuring-the-agent). `Runtime`

```ts
async handler(ctx) {
  ctx.useAgent({
    systemPrompt: "You are a helpful assistant.",
    model: "claude-sonnet-4-6",
    tools: [...ctx.electricTools, searchDocsTool],
  })

  await ctx.agent.run()
}
```

### Spawn

Spawn a fresh child entity without parent history. Use this for workers, fan-out, and multi-layer agent trees where the parent wants another entity to own a separate stream of work. See [spawning and coordinating](/docs/agents/usage/spawning-and-coordinating#spawn). `SDK`

```ts
const worker = await ctx.spawn(
  "worker",
  "audit-docs",
  { tools: ["read", "search"] },
  {
    initialMessage: "Audit the docs for missing release notes.",
    wake: { on: "runFinished", includeResponse: true },
  }
)
```

### Fork

Fork an entity with history. Use this when you want a second path through the same session. The fork keeps the useful context and branches the durable stream, so you can try another approach without overwriting the original. See [spawning and coordinating](/docs/agents/usage/spawning-and-coordinating). `Runtime` `App`

```ts
const fork = await ctx.forkSelf("variant-a", {
  initialMessage: { text: "Try the shorter implementation path." },
  tags: { branch: "variant-a" },
})
```

### Send

Send [messages](/docs/agents/usage/writing-handlers#sending-messages) to any entity. Because messages are durable inbox entries, the same API works for user input, parent-to-child steering, and send-to-self continuation after a delay. `SDK`

```ts
await ctx.send(
  "/worker/audit-docs",
  { files: ["website/docs/agents/index.md"] },
  { type: "review_request" }
)

await ctx.send(
  ctx.entityUrl,
  { step: "continue-after-indexing" },
  { type: "self", afterMs: 60_000 }
)
```

### Wake

Wake entities from inbox messages, child completion, state changes, cron, future sends, event sources, and Postgres sync triggers. Wakes are how agents scale to zero: no process has to stay alive just to notice that something changed. See [waking entities](/docs/agents/usage/waking-entities). `Runtime`

```ts
await ctx.observe(entity("/worker/audit-docs"), {
  wake: { on: "runFinished", includeResponse: true },
})

await client.registerWake({
  subscriberUrl: "/monitor/docs",
  sourceUrl: "/worker/audit-docs/main",
  condition: { on: "change", collections: ["runs", "texts"] },
})
```

### Observe

Observe entities, shared state, entity lists, timelines, and child state in real time from handlers or apps. Observing loads the target stream into a typed local DB. Those collections can drive UI, coordination logic, or debugging tools. Use the [runtime client](/docs/agents/usage/programmatic-runtime-client) and [React client APIs](/docs/agents/usage/clients-and-react). `SDK` `App APIs`

```ts
const client = createAgentsClient({ baseUrl: "http://localhost:4437" })
const db = await client.observe(entity("/assistant/release-post"))

console.log(db.collections.texts.toArray)
```

### Schedule

Schedule work with [cron and future sends](/docs/agents/usage/programmatic-runtime-client#schedules). Agents can sleep until the next scheduled wake. Recurring jobs and delayed follow-ups live in the entity's durable manifest, not in an external timer you have to reconcile. `Runtime`

```ts
await client.upsertCronSchedule({
  entityUrl: "/assistant/release-post",
  id: "daily-checkin",
  expression: "0 9 * * *",
  timezone: "Europe/London",
  payload: "Review open launch tasks.",
})

await client.upsertFutureSendSchedule({
  entityUrl: "/assistant/release-post",
  id: "follow-up",
  fireAt: new Date(Date.now() + 60_000).toISOString(),
  payload: "Continue after the preview build finishes.",
})
```

### Signal

Signal running agents: interrupt, pause, resume, kill, or deliver handler-level lifecycle signals. Signals give apps and operators a control plane for active work without treating the agent as an opaque process. See the [signals guide](/docs/agents/usage/signals) and [CLI reference](/docs/agents/reference/cli). `Runtime` `CLI` `App`

```ts
await client.signalEntity({
  entityUrl: "/horton/release-post",
  signal: "SIGINT",
  reason: "User wants to redirect the current run.",
})
```

### Coordinate

Coordinate with [shared state](/docs/agents/usage/shared-state) and multi-agent patterns such as [orchestrator/worker](/docs/agents/entities/patterns/manager-worker), [blackboard](/docs/agents/entities/patterns/blackboard), [reactive observers](/docs/agents/entities/patterns/reactive-observers), [map-reduce](/docs/agents/entities/patterns/map-reduce), and [pipelines](/docs/agents/entities/patterns/pipeline). Coordination is explicit state and explicit streams, so parent agents, child agents, and UI clients can inspect the work. `SDK`

```ts
const board = ctx.mkdb("release-board", {
  tasks: {
    schema: z.object({ id: z.string(), status: z.string() }),
    type: "shared:task",
    primaryKey: "id",
  },
})

board.tasks.insert({ id: "screenshots", status: "needed" })

const reviewer = await ctx.spawn("worker", "reviewer", {})
await ctx.observe(entity(reviewer.entityUrl), {
  wake: { on: "change", collections: ["texts"] },
})
```

### Connect

Connect external tools and systems with [MCP servers](/docs/agents/usage/mcp-servers), [webhook-source subscriptions](/docs/agents/usage/webhook-sources), [webhooks](/docs/agents/usage/clients-and-react#observation-sources), and [PG sync-driven triggers](/docs/agents/usage/programmatic-runtime-client#registerpgsyncsource). Agents can subscribe to operational systems and wake when those systems change. `Runtime`

```ts
await client.subscribeToWebhookSource({
  entityUrl: "/horton/release-post",
  id: "github-pr",
  sourceKey: "github",
  bucketKey: "repo",
  params: { repo: "electric-sql/electric" },
  lifetime: { kind: "until_entity_stopped" },
})

const todos = await client.observe(
  pgSync({ table: "todos", where: "project_id = $1", params: ["agents"] })
)
```

### Inspect

Inspect every entity as a StreamDB: timeline, inbox, runs, tool calls, child status, errors, signals, [attachments](/docs/agents/usage/attachments), and [custom collections](/docs/agents/usage/managing-state). The runtime exposes these as TanStack DB collections, so app code can query the agent's state instead of scraping logs. See the [built-in collections reference](/docs/agents/reference/built-in-collections) and the [TanStack DB query docs](https://tanstack.com/db/latest/docs/guides/live-queries). `App APIs` `App`

```ts
import { eq, queryOnce } from "@durable-streams/state/db"

const db = await client.observe(entity("/horton/release-post"))

const runs = await queryOnce((q) => q.from({ run: db.collections.runs }))

const toolCalls = await queryOnce((q) =>
  q.from({ toolCall: db.collections.toolCalls })
)

const attachments = await queryOnce((q) =>
  q
    .from({ manifest: db.collections.manifests })
    .where(({ manifest }) => eq(manifest.kind, "attachment"))
)
```

## Apps in development

The desktop and mobile apps are built on the same APIs you use: `observe(entities())` to list agents, `observe(entity(...))` to load one, the runtime client to spawn, signal, and send. The app is a subscriber, not special infrastructure.

We're using them to dogfood the SDK and runtime, and to build toward our own software factory: agents that shepherd PRs and issues, keep work moving, and let everyone connect to the same durable session.

* **Custom agent types:** build entities with `@electric-ax/agents-runtime` and inspect them in the desktop app.
* **State explorer:** see each entity's runs, inbox, manifests, and custom state in one view.
* **Entity timeline:** replay a run event by event, then fork from a point in the timeline to try another path.
* **Cloud or self-hosted:** use Electric Cloud when available, or point the app at an agents-server you run yourself.
* **Remote sessions:** open sessions started by CI, webhooks, issues, cron, or another machine.
* **MCP servers:** add MCP servers with native OAuth. Workspace `mcp.json` files are respected.
* **Model providers:** use an API key from your keychain, or sign in to Codex. Anthropic, OpenAI, DeepSeek, and Moonshot are supported.
* **Skills and slash commands:** use `/quickstart` to get started, then save commands for your workflows.
* **Phone handoff:** open a run on iOS or Android to steer it, send a message, or check progress.
* **Desktop workflow extras:** pick a working directory, split the tile workspace, attach files and screenshots to chat, discover local dev servers, and install the `electric` CLI system-wide.

You can download app canaries from [GitHub releases](https://github.com/electric-sql/electric/releases), or build the apps yourself from the repo.

## How to try it

Run the quickstart from the CLI:

```sh
npx electric-ax agents quickstart
```

Open the UI, spawn Horton, send a message, and watch the timeline update as the agent thinks, calls tools, and responds.

Then define your own entity type and connect it to the same runtime and apps:

```ts
import {
  createEntityRegistry,
  createRuntimeHandler,
} from "@electric-ax/agents-runtime"

const registry = createEntityRegistry()

registry.define("assistant", {
  description: "A general-purpose AI assistant",
  async handler(ctx) {
    ctx.useAgent({
      systemPrompt: "You are a helpful assistant.",
      model: "claude-sonnet-4-6",
      tools: [...ctx.electricTools],
    })

    await ctx.agent.run()
  },
})

export const runtime = createRuntimeHandler({
  baseUrl: process.env.ELECTRIC_AGENTS_URL ?? "http://localhost:4437",
  serveEndpoint: "http://localhost:3000/webhook",
  registry,
})
```

Once registered, `assistant` appears as an entity type in the app. Spawn `/assistant/my-agent`, send it a message, and use the same timeline, state, and devtools surfaces that Horton uses.

## Coming next

* Managed Agents servers in Electric Cloud.
* More examples and docs for app builders: PG sync triggers, [webhook sources](/docs/agents/usage/webhook-sources), [MCP](/docs/agents/usage/mcp-servers), [attachments](/docs/agents/usage/attachments), [sandbox profiles](/docs/agents/usage/sandboxing), and multi-agent patterns.
* More app development polish: desktop builds, smoother downloads and updates, and richer mobile distribution.

## Next steps

* Run `npx electric-ax agents quickstart`.
* Read the [Electric Agents docs](/docs/agents/).
* Watch the demos in this post.
* Download app canaries from [GitHub releases](https://github.com/electric-sql/electric/releases), or build them from source.
* Join the [Electric Discord](https://discord.electric-sql.com) and tell us what you build.

***
