Skip to main content

Open source · Self-hosted · Apache 2.0

The infrastructure layer for production-ready AI agents.

Sessions, knowledge, memory, orchestration, guardrails, IAM, evaluations and traces from one self-hosted Node.js server on PostgreSQL. Reachable over REST, MCP, the CLI and the SDK.

docker compose up -dPostgreSQL, Ollama and the server. Runs offline.
agentformationsiamworkflowssessionsorchestrationsknowledgememoriestoolsguardrailsapprovalsevaluationstraces
Apache 2.0licensed, nothing withheld
1 processNode.js on PostgreSQL + pgvector
4 surfacesREST, MCP, CLI, SDK
0 signupsself-hosted, self-serve keys

What SOAT is

One server. Every layer an agent needs.

SOAT is open-source infrastructure for production-ready AI agents: one self-hostable Node.js server that gives an agent identity, storage with vector search, memory, orchestration, guardrails, evaluations and traces, backed by PostgreSQL. You bring the product. SOAT handles the infrastructure layer.

The REST API and the MCP endpoint are one process calling the same business logic through the same permission engine, so a resource created on one surface is already visible on the others.

Not in the diagram, on purpose:a message queuea vector databasean auth servera trace collectora scheduler

Callers

BackendREST /api/v1
Claude, Cursor, VS CodeMCP /mcp
CI and scriptssoat CLI
TypeScript app@soat/sdk
Browserweb app /app
SOAT serverone Node.js process · :5047
REST /api/v1MCP /mcp
Business logicPermission engine

State

PostgreSQL+ pgvector
  • rows and files
  • embeddings
  • message history
  • traces and audit log

The four layers of an agent system

Harness first. Loop second. Graph last. Then the ratchet.

An agent system decomposes into four layers, and the investment order is not equal. SOAT is built around that order: every module owns one layer, so when a layer is the one failing you know which part of the platform to reach for. Read the framing.

  1. Harness

    What can this agent reach, and what is it forbidden?

    Most failures live here, and so do the cheapest wins. Tools are first-class resources, knowledge and memory are scoped, and every permission is a policy document.

  2. Loop

    What proves it did the job, and when does it stop?

    Output schemas, step limits and stop conditions bound the run. Guardrails classify every tool call before it executes, quotas fail closed, and each generation writes a trace.

  3. Graph

    What is allowed to happen next?

    DAG orchestrations with parallel rounds, state-machine workflows for long-running work, and triggers on a cron, a webhook or an event. Built last, because it is needed least often.

  4. Ratchetgoverns change itself

    How does the system change, and what proves the change was an improvement?

    Agent versions are append-only, a canary splits traffic, and promotion waits for a passing eval run against that canary. The platform owns the verdict; a human owns the judgment.

Client surfaces

One backend. Four ways to call it.

The CLI, the SDK and the MCP tool surface are generated from the same OpenAPI documents the REST API is described by, so an operation that exists on one surface exists on all four. Pick the one that fits where your code runs. This is the same call, four times.

POST /api/v1/agents
curl -X POST http://localhost:5047/api/v1/agents \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{
"project_id": "proj_01HXYZ",
"ai_provider_id": "aip_01HXYZ",
"name": "support-bot",
"instructions": "You are a helpful support assistant."
}'
REST API docs
Authentication
one sk_ key or user JWT
Permission
agents:CreateAgent
Data
one PostgreSQL database
Contract
one OpenAPI document

Agent formations

Deploy a whole agent stack from one template.

Formations are the declarative layer. Describe the stack once, preview the plan, and SOAT creates or updates every dependent resource in the right order, with the same permissions and the same traceable operations as a hand-made call. Formations docs.

support-stack.yaml
resources:
Provider:
type: ai_provider
properties:
name: openai
provider: openai
default_model: gpt-4o
Docs:
type: memory
properties:
name: product-docs
Lookup:
type: tool
properties:
name: order-lookup
type: http
execute:
url: https://api.example.com/orders/{order_id}
method: GET
Support:
type: agent
properties:
name: support-bot
ai_provider_id: { ref: Provider }
knowledge_config:
memory_ids: [{ ref: Docs }]
tool_bindings:
- tool_id: { ref: Lookup }
Hook:
type: webhook
depends_on: [Support]
properties:
name: session-events
url: https://example.com/hooks/soat
events: ['sessions.*']

plan-formation resolves the template into this graph.

  1. 01

    Declare

    soat validate-formation

    One template, JSON or YAML: providers, memories, tools, agents, orchestrations and webhooks. Refs point at logical IDs, not at IDs that exist yet.

  2. 02

    Resolve

    soat plan-formation

    SOAT builds the dependency graph from refs and depends_on, rejects cycles, and provisions in topological rounds. Independent resources go in parallel.

  3. 03

    Operate

    soat list-formation-events

    Every create, update and delete lands in an immutable event log with the resources it touched and the outputs it produced. A failed deploy rolls back.

From zero to a running agent

Four commands. Every one of them recorded.

The CLI is the whole API as sub-commands, so the shortest path to a working agent is also a script you can commit.

  1. 1

    Create the agent

    Bind it to any configured provider. The configuration is archived as an append-only version from the first write.

  2. 2

    Open a session

    One user, one agent. Message history lives in PostgreSQL, so it survives the process.

  3. 3

    Add the message

    Appending and generating are separate calls, so a client can batch input before spending a token.

  4. 4

    Generate the answer

    The reply comes back with a trace: every tool call, model response and token count, attributable to the agent version that served it.

Read the Agents docs
soat · bashexit 0
soat create-agent \  --project-id "$PROJECT_ID" \  --ai-provider-id "$PROVIDER_ID" \  --name support-bot \  --instructions "You are a helpful support assistant."soat create-session \  --agent-id "$AGENT_ID" \  --name user-chat-42soat add-session-message \  --session-id "$SESSION_ID" \  --message "Hello!"soat generate-session-response \  --session-id "$SESSION_ID"# the answer, plus a trace_id you can open in the console

When to use SOAT

Reach for SOAT when the agent has to be trusted with something.

A single model call needs no infrastructure. SOAT earns its place the moment an agent has to remember, retrieve, coordinate, stay inside its permissions, or account for what it did. These are the jobs it is built for, the same list an agent reads at /agents.md, where each one names the call that does it.

  1. 01

    Give an agent memory that survives the process

    Sessions and conversations persist message history in PostgreSQL.

    Sessions
  2. 02

    Ground an agent in your own documents

    Ingest files into chunked, embedded documents and search them with pgvector.

    Documents
  3. 03

    Run multi-step work deterministically instead of hoping one prompt covers it

    Orchestrations are DAGs of agent, tool, and human nodes; workflows are state machines for long-running work.

    Orchestrations
  4. 04

    Bound what an agent is allowed to do

    IAM policies gate every action, API keys scope to one project, guardrails screen input and output, and quotas cap spend.

    IAM
  5. 05

    Put a human in the loop without stopping the run

    Approval nodes and exceptions pause a run, record who decided what, and resume from the same point.

    Approvals
  6. 06

    Prove after the fact what an agent did and what it cost

    Every generation writes a trace with each tool call, model response, and token count, alongside an append-only audit log.

    Traces
  7. 07

    Change an agent in production without guessing whether it got worse

    Agent versions are append-only; a canary release splits traffic, and promotion is gated on a passing eval run.

    Agents
  8. 08

    Expose your own backend to an MCP client (Claude, Cursor, VS Code)

    Every REST operation is also an MCP tool, behind the same permission engine, with OAuth 2.1 discovery and Dynamic Client Registration.

    MCP
  9. 09

    Stand up a whole agent stack reproducibly

    Agent Formations declare providers, tools, agents, orchestrations, and webhooks in one template, resolve the dependency graph, and apply it.

    Formations

Getting access

No signup. No sales call. No waitlist.

SOAT is Apache-2.0 software you run yourself, so there is nothing to request and no tier to be approved for. A local deployment is the same software as a production one: the sandbox, the free tier and the product are one thing. Keys are minted by an API call, which matters because an agent cannot fill in a contact form.

Open the quick start
  1. Nothing to sign up for

    SOAT is Apache-2.0 licensed and self-hosted. There is no account to create, no key to request, no trial to start, and no quota you have to ask anyone to raise.

  2. Run the stack

    Copy the Compose file from the quick start and run docker compose up -d. It brings up PostgreSQL with pgvector, a local Ollama for models, and the SOAT server on port 5047 — so the whole platform runs offline, with no third-party credential.

  3. Get the first credential

    POST /api/v1/users/bootstrap creates the first admin. It is open only until that admin exists, then closed for good, so the same call cannot be replayed against a running deployment.

  4. Issue your own API key

    POST /api/v1/api-keys (or soat create-api-key) mints a project-scoped sk_… key with exactly the actions of the policy you attach. Keys are self-serve and rotatable — POST /api/v1/api-keys/{api_key_id}/rotate.

  5. The sandbox is the same software

    There is no separate sandbox tier to request: a local instance is the product, so throwaway projects, seeded data, and destructive tests all run against your own deployment. Delete the volumes to reset.

Built for agents

Everything on this site is readable by a machine.

SOAT is infrastructure for agents, so its documentation is published the way an agent wants to read it. Every page is server-rendered, with the full text in the HTML and no JavaScript required, and has a Markdown twin one URL away. The REST surface is one OpenAPI description and the error contract is a catalog of stable codes, so a client can be generated and its failures handled without scraping a page.

curl -H "Accept: text/markdown" https://soat.ttoss.dev/9 entries
pathtypewhat an agent gets
/agents.mdtext/markdownInstructions for an agent: which jobs SOAT is the right tool for, which it is not, how to authenticate and call it, and how to get access.
/llms.txttext/plainIndex of every documentation page, with a one-line summary and a link to each Markdown twin.
/llms-full.txttext/plainThe whole prose documentation corpus in one file, ready to be chunked and embedded.
/openapi.jsonapplication/jsonEvery REST operation of the SOAT API in a single OpenAPI 3.0 description — paths, schemas, and security schemes.
/openapi.yamlapplication/yamlThe same merged OpenAPI description in YAML, also served at /api/openapi.yaml.
/errors.jsonapplication/jsonCatalog of every error code the API can return, with its HTTP status and what to do about it.
/docs/openapi-specstext/htmlOne YAML spec per module under /openapi/<module>.yaml, for tools that prefer a narrower surface.
/sitemap.xmlapplication/xmlEvery canonical page with its last-modified date, so a crawler can fetch only what changed.
/robots.txttext/plainCrawl policy: everything is allowed, plus the sitemap link.

Send Accept: text/markdown to any documentation URL and that page answers in Markdown, or append .md for the same file by name, for example /docs/introduction.md. Every HTML page advertises its own twin with a <link rel="alternate" type="text/markdown"> tag, and dead URLs answer with a real HTTP 404 carrying a Markdown recovery map instead of a soft 200.

Stop rebuilding agent infrastructure.

Self-host SOAT and ship agents that can reach what they need, prove they did the job, and improve on evidence. Sessions, knowledge, memory, IAM, guardrails, versions, traces and MCP, on your own infrastructure.

Weighing your options? See how SOAT compares to other agent solutions.