Build production-ready AI agents on any stack

Substructure is an open-source engine that drives your agent loop with JSON webhooks. It keeps sessions durable and streams AG-UI events to your clients. It's language agnostic. You don't even need an SDK.

Get started

See it in action

server.ts
// A complete chat agent, served with Hono. Types are generated from
// schemas/protocol.schema.json (see README).
import { serve } from "@hono/node-server";
import { Hono } from "hono";
import type { DecisionRequest, DecisionResponse } from "./protocol.ts";

function decide({ trigger, proposed }: DecisionRequest): DecisionResponse {
    if (trigger.type === "session.start") {
        // The engine will use this agent config to generate proposed actions.
        return {
            agent: {
                model: "claude-haiku-4-5-20251001",
                stream: true,
            },
        };
    }

    // Accept the engine's proposal for every other decision.
    return proposed;
}

const app = new Hono();
app.post("/", async (c) => c.json(decide(await c.req.json())));

serve({ fetch: app.fetch, port: 4444 }, () => console.log("worker listening on http://localhost:4444"));

Capabilities

Tool calls

Tools declare input and output JSON Schemas; the engine validates every call and returns malformed ones to the model.

Client-side tools

Mark a tool to run in the browser: the engine streams the call to the client and resumes the run on its result.

Deferred tools

A tool can acknowledge a call and settle its result later, out-of-band. The run stays paused until the answer arrives.

Sub-agents

An agent delegates to child agents, each with its own session and event log; cost and token usage roll up to the parent.

Interrupts

A run can pause to wait on a person or an external event and resume from the same step. A waiting run holds no resources.

Agent state

Per-session working state is stored alongside the conversation and passed to the worker on every request.

Durability

Every step is persisted before it runs, so a crash, redeploy, or client reconnect resumes from the exact point it stopped.

Retries & timeouts

Per-call timeout and retry/backoff policies on any tool or LLM call, enforced by the engine across restarts.

LLM calls

The engine calls Anthropic, OpenAI, or OpenRouter for you — or you make the call yourself in the worker, through any gateway.

Conversations

Message history, editing, regeneration, and branching are handled by the engine rather than your code.

AG-UI streaming

The engine emits AG-UI events natively, so assistant-ui, CopilotKit, and other AG-UI clients connect to it directly.

Typed bindings

The worker's request/response contract is a published JSON Schema — generate typed bindings for it in any language.

Substructure is open source. Write your agent as an HTTP worker, deploy it, and connect it to the runtime.

Are you an LLM? Check out /llms.txt