Skip to content
ElectricElectric
PricingBlog
Main Navigation
Go to Cloud
Cloud
Go to Cloud
Are you an LLM? You can read better optimized documentation at /agents.md for this page in Markdown format

Electric Agents

The durable runtime for long-lived agents

QuickstartDocs

Bring the agent loop online

Today's agents live on your laptop or behind a chat window. Real work happens inside business systems — triggered by webhooks, running 24/7 without supervision.

Electric Agents brings durable, composable, serverless agents to the infrastructure you already run. Built on Electric Streams, every agent sleeps when idle, wakes on demand and survives restarts.

agents
support/ticket-11903sleeping
product-desc/optimise-sku-884212sleeping
coding-agent/pr-review-470sleeping
deploy/pipeline-895sleeping
SDK
Lives in your app process
agent.ts
import { defineEntity } from "electric-agents"

defineEntity("assistant", {
  state: { … },
  async handler(ctx) {
    ctx.useAgent({ … })
    await ctx.agent.run()
  },
})
  • wake
  • register
  • ack
Control plane
lifecycle · routing · scheduler
Agents
/assistant/r-1
/assistant/r-2
/coder/refactor
/researcher/x
Electric Streams

Inside the runtime

The runtime has two parts:

  • An SDK in your app, where you define entities and write handlers in plain TypeScript. Runs in your process, so your tools, models, and secrets stay yours.
  • A control plane that runs, routes wakes, and persists every agent to its own durable stream. Owns the lifecycle, so your handlers don't need to stay alive between invocations.

Every agent is an entity with a stream

You define entity types — like assistant or researcher — then spawn instances on demand.

Each instance is backed by its own durable stream: an append-only log that serves as the agent's memory, its inbox, and a complete audit trail of everything it did.

Entity: /assistant/helper
handler.ts
1registry.define("assistant", {
2 async handler(ctx) {
3 ctx.useAgent({
4 systemPrompt: "You are a helpful assistant.",
5 model: "claude-sonnet-4-5-20250929",
6 tools: [calculatorTool, ...ctx.darixTools],
7 })
8 await ctx.agent.run()
9 },
10})
Stream
sleeping — zero compute

Every agent is fully introspectable. The stream is a complete audit trail — what you see above is the actual data model.

/agents/research-agentSleeping
/agents/research-agent/stream
sleeping — zero compute

Durable state, not durable execution

Your agent doesn't need to stay alive. It needs its state to survive. The stream is the source of truth.

When a handler crashes or the process restarts, nothing is lost. The stream replays and the agent picks up exactly where it left off — no checkpointing, no snapshots, no coordination.

Ready to build

Ship your first agent

Install the SDK, define an entity, deploy it on your stack.

QuickstartDocs

Primitives for coordination

Local agents compose through child processes. Electric Agents makes that pattern durable, observable, and serverless.

Spawn & Send

spawn creates a new entity. send delivers a message to any entity — waking it if it's sleeping. The entity replays from its stream, handles the message, then scales back to zero.

plannersleeping
researchersleeping
writersleeping
// create new entities
await ctx.spawn("researcher", "r1")
await ctx.spawn("writer", "w1")

// send wakes them with a message
ctx.send("/researcher/r1", {
  task: "search for X"
})

Observe

Watch another entity's stream in real time. When the observed entity appends an event, the observer wakes to process it — no polling, no open connections while idle.

monitorsleeping
workersleeping
await ctx.observe(
  entity("/worker/task-1"),
  { wake: "runFinished" }
)

// handler re-invoked when worker finishes
const result = wake.payload

Shared State

Multiple entities read and write to a shared state object backed by a stream. Changes propagate automatically — each writer wakes readers when state updates.

writersleeping
reader-asleeping
reader-bsleeping
const state =
  ctx.createSharedState("research", schema)

// other entities:
const view =
  ctx.connectSharedState("research", schema)

Scale to zero. Wake on demand.

Every entity costs nothing when idle. A thousand agents? You pay for the ones that are actually thinking.

Entities sleep between invocations — no long-running processes, no idle VMs. When a message arrives, the handler wakes, replays from the stream, and continues.

40 entities · 0 active

Context Window32,768 tokens
tool definitions
codebase context
conversation
← cacheable prefix (74%)
system promptpinned2,048Never changes between requests
tool definitionsstable5,120Changes rarely — high cache hit rate
codebase contextslow-changing14,336Updates as files change
conversationvolatile7,552Changes every turn — placed last

Cache-friendly context, by construction

Each context source declares how often it changes. The runtime orders sources from most stable to most volatile, so the LLM can cache the shared prefix across every request.

Less re-processing, lower latency, lower cost.

Your stack, not ours

Runs on your infrastructure. Express, Next.js, Hono, TanStack Start — agents are webhook handlers. No vendor lock-in.

Your App
Express · Next.js · Hono · Fastify
webhooks
Electric Agents
entities · handlers · context
HTTP streams
Electric Streams
Electric Cloud or self-hosted
import { createRuntimeHandler } from "electric-agents"
import { registry } from "./entities"

const runtime = createRuntimeHandler({
  baseUrl: STREAMS_URL,
  serveEndpoint: WEBHOOK_URL,
  registry,
})

app.post("/webhook", (req, res) => {
  await runtime.onEnter(req, res)
})

app.listen(PORT, () => runtime.registerTypes())
import { createEntityRegistry } from "electric-agents"

export 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-5-20250929",
      tools: [...ctx.agentTools],
    })
    await ctx.agent.run()
  },
})

Three ways in

Once your handlers are registered, talk to the runtime however you prefer.

CLI

From the terminal

Spawn entities, send messages, list what's running, and tail an entity's stream live — with reasoning, tool calls, and text rendered inline.

Terminal
$ electric-agents spawn /assistant/research-1
✓ Spawned /assistant/research-1
$ electric-agents send /assistant/research-1 "summarise the docs"
→ message delivered, entity woke
$ electric-agents observe /assistant/research-1
← reasoning · tool_call(read_file) · text…
Desktop app

Observe and chat

Browse running entities, watch their timelines update in real time, inspect tool calls, and send follow-up messages — all from a cross-platform desktop app.

assistant/research-1
assistant/support-bot
researcher/r-2
coder/refactor
summarise the docs
↳ read_file("docs/intro.md")
The docs cover three primary surfaces…
TypeScript

From your app

Embed agent control directly in your code: spawn and send from any TypeScript service, and render an entity's live stream in React with the useChat hook.

app.tsx
import { createClient } from "electric-agents"
import { useChat } from "electric-agents/react"

const client = createClient({ baseUrl: RUNTIME_URL })
await client.spawn("/assistant/research-1")

function Chat() {
  const { messages, send } = useChat("/assistant/research-1")
  return <Timeline messages={messages} onSend={send} />
}

Your first agent, end to end

Define an entity type. Write a handler. Deploy.

agent.ts
import { createEntityRegistry } from "electric-agents"

const registry = createEntityRegistry()

registry.define("assistant", {
  description: "A helpful AI assistant",

  async handler(ctx) {
    ctx.useAgent({
      model: "claude-sonnet-4-5-20250929",
      systemPrompt: "You are a helpful assistant.",
      tools: [...ctx.agentTools],
    })

    await ctx.agent.run()
  },
})
Terminal
$ electric-agents spawn assistant my-agent
✓ Spawned /assistant/my-agent
$ electric-agents send /assistant/my-agent "..."
✓ Message sent — entity woke, handling...
$ electric-agents observe /assistant/my-agent
← text: "The capital of France is Paris."
1
Create a registry

The registry holds your entity definitions and wires them to Electric Streams.

2
Name your entity type

Instances are spawned as /assistant/my-agent, /assistant/support-bot, etc.

3
Write a handler

ctx gives you the stream, tools, and coordination primitives.

4
Bring your own tools

agentTools provides spawn, send and observe. Add your own MCP tools, APIs, or whatever your handler needs.

5
Run the agent loop

Reads the stream, calls the LLM, appends events, then sleeps. Survives crashes by replaying from the stream.

6
Spawn an instance

Creates a new entity of the given type with a unique ID. Its durable stream starts here.

7
Send a message

Delivers a message to the entity's stream, waking it to run its handler.

8
Observe in real time

Stream events as they're appended — see the agent think, call tools, and respond.

Get startedRead the Docs

Demos

Reference apps you can clone, run locally, and learn from.

Chat Starter

Chat Starter

Multi-agent chatroom where philosopher agents debate, answer questions, and react to messages in real time.

Deep Survey

Deep Survey

Multi-agent research app where an orchestrator coordinates a swarm of explorer agents to build a live knowledge base.

All demos

From the blog

Go deeper on Electric Agents — the runtime, the patterns, and what teams are building on them.

Introducing Electric Agents — the agent platfom built on sync

Read post →

Fork — branching for Durable Streams

Read post →

Durable Streams — the data primitive for the agent loop

Read post →

AI agents as CRDT peers — building collaborative AI with Yjs

Read post →
Electric BlogFollow @ElectricSQL
Open source · Apache 2.0 · built on Electric Streams

Bring your agents online

Install the SDK, define an entity, and ship a durable agent on top of your existing stack.

QuickstartDocsGitHub

ElectricElectric

AboutContactLegalDocsDemosBlogSign up
TanStack DBPGliteXBlueskyDiscordGitHub

© 2026 Electric DB Inc. Released under the Apache 2.0 License.

✨ Markdown