
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.
The runtime has two parts:
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.
Every agent is fully introspectable. The stream is a complete audit trail — what you see above is the actual data model.
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.
Install the SDK, define an entity, deploy it on your stack.
Local agents compose through child processes. Electric Agents makes that pattern durable, observable, and serverless.
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.
// 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"
})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.
await ctx.observe(
entity("/worker/task-1"),
{ wake: "runFinished" }
)
// handler re-invoked when worker finishes
const result = wake.payloadMultiple entities read and write to a shared state object backed by a stream. Changes propagate automatically — each writer wakes readers when state updates.
const state =
ctx.createSharedState("research", schema)
// other entities:
const view =
ctx.connectSharedState("research", schema)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
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.
Runs on your infrastructure. Express, Next.js, Hono, TanStack Start — agents are webhook handlers. No vendor lock-in.
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())Once your handlers are registered, talk to the runtime however you prefer.
Spawn entities, send messages, list what's running, and tail an entity's stream live — with reasoning, tool calls, and text rendered inline.
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.
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.
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} />
}Define an entity type. Write a handler. Deploy.
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()
},
})The registry holds your entity definitions and wires them to Electric Streams.
Instances are spawned as /assistant/my-agent, /assistant/support-bot, etc.
ctx gives you the stream, tools, and coordination primitives.
agentTools provides spawn, send and observe. Add your own MCP tools, APIs, or whatever your handler needs.
Reads the stream, calls the LLM, appends events, then sleeps. Survives crashes by replaying from the stream.
Creates a new entity of the given type with a unique ID. Its durable stream starts here.
Delivers a message to the entity's stream, waking it to run its handler.
Stream events as they're appended — see the agent think, call tools, and respond.
Reference apps you can clone, run locally, and learn from.
Go deeper on Electric Agents — the runtime, the patterns, and what teams are building on them.
Install the SDK, define an entity, and ship a durable agent on top of your existing stack.