Agent Substrate
Durable agent runtime

Agents that pause,
not burn.

An agent that sits idle 99% of the time still costs you 100% of a server. Agent Substrate suspends a run to durable state the moment it starts waiting — on a person, a schedule, a webhook — holding no worker, then resumes on exactly the step it left.

run r-8f21a3 · invoice-intake
Suspended2h 14m
workers held0
  1. fetch_invoices
    12 documents · 2.4s
  2. extract_fields
    12/12 parsed · 8.1s
  3. validate_totals
    1 mismatch flagged · 0.3s
  4. send_invoice_email
    awaiting human approval
  5. archive_batch
    queued behind approval
Resumes on
human approvalwebhook24h timeout
trace_id a1b2c3d4e5f6 · 6 steps recorded before suspension
One runtime, three ways in

Code it, draw it, or ship it — same durability.

Engine

Import it directly

A Python async framework underneath everything else. Write the agent in code, and the suspend/resume behavior every other surface gets for free is the same runtime call.

agent.py
from substrate.agents.core import ReActAgent
from substrate.capabilities.tools import AskHumanTool

agent = ReActAgent(
    tools=[AskHumanTool(), send_invoice_email],
    model="gpt-5.4",
)

async def run(ctx, inbox):
    await agent.run(ctx, inbox) # suspends + resumes automatically

Builder

Compose it visually

Drag agents, tools, guardrails, and approval gates onto a canvas. The graph the builder produces is executed by the same durable runtime — not exported to a different format first.

canvas.pipeline
agentguardrailapprovaltool call

Chat

Ship it as a surface

Deploy the same graph as a project-scoped chat interface with streaming, memory, and file handling. A run suspended waiting on approval shows up here as a card, not a dead conversation.

chat · invoice-intake
Process this week's invoices
Parsed 12 invoices, flagged 1 mismatch. Ready to send — need your approval first.
⏸ paused — send_invoice_email
still here whenever you get to it

Durability is not a feature we bolted on

Python 3.13async runtime
PostgreSQLdurable run state
Redissessions & queues
OpenTelemetrytracing
MCPtool protocol
How it holds up

Built for runs that outlive the request.

Waiting is a state, not a bill

The moment a run blocks — on a person, a cron, an inbound webhook — its state is written to Postgres and the worker is released. Nothing spins. Nothing polls a database in a hot loop waiting for an answer that lands tomorrow morning.

run r-8f21a3 · lifetime
Wall clock
00:0002:38
Billed compute
nothing held

Every step survives the pause

Runs are an append-only event log, not an in-memory call stack. Which tools ran, what came back, which guardrail fired, why it stopped — all still there after the suspension, after a deploy, after a crash.

trace a1b2c3d4e5f6
INFOruntimestep validate_totals ok (0.3s)
WARNguardrailtotal mismatch on invoice_007
INFOhitlask_human → send_invoice_email
INFOruntimerun suspended · state persisted
INFOschedulerresume armed: approval|webhook|24h

Human approval, built in

Risky tool calls stop and ask. The reviewer gets the call, its arguments, and the risk classification — and can take as long as they need, because a run waiting on them costs the same as a run that finished.

approval · run r-8f21a3
Approval required

Send 12 invoice emails to external recipients?

tool
send_invoice_email
risk
external side effect
waiting
2h 14m · 0 workers held
ApproveReject

One graph, drawn and run

Compose the pipeline visually from typed nodes — agents, tools, routers, guardrails, approval gates, loops. The artifact the builder produces is the artifact the durable runtime executes. No export step, no second source of truth.

invoice-intake.pipeline
startextractguardrailapprovalarchive

Runs measured in seconds days

Long-horizon work — approvals that land tomorrow, schedules that fire next week — stops being an infrastructure problem you route around.

0workers
held while a run is suspended

State lives in Postgres, not in a parked process.

duration
a run can stay suspended

Minutes or months — resumption is an event, not a timeout.

13node types
in the visual builder

Agents, tools, routers, guardrails, approvals, loops.

15+tools
built in, plus any MCP server

Web, code interpreter, documents, email, task boards.

Get started

Add it to a project, or run the whole platform

Use it as a library

Published on PyPI. Import the agent loop directly into your own code — no server to stand up first.

terminal
$uv add agent-substrate --prerelease=allow
agent.py
from substrate import ReActAgent, Runtime

Run the full platform

Same package — add it, then run its FastAPI server, durable runtime, and observability stack directly. Needs Postgres and Redis; see the full setup guide for env vars and infra.

terminal
$uv add agent-substrate --prerelease=allow && uv run start

Stop paying for agents
that are just waiting.

Free to start, BYOK to scale. No credit card for the free tier.