The backend your AI agent sets up

Build your product. Your agent sets up the backend.

dabadata is a hosted backend written for AI agents to read. Plain Postgres underneath, tables and rules in one definition, live data, sign-in, file storage, AI calls and your frontend on your own domain. Every allow and deny comes with a sentence that explains it, so you can see every decision your agent made.

written by your agentJSON
{
  "roles": ["admin", "member"],
  "tables": {
    "expenses": {
      "columns": {
        "what":    { "type": "text" },
        "amount":  { "type": "float" },
        "paid_by": { "type": "userId" }
      },
      "rules": {
        "read":   "authenticated",
        "create": { "role": ["admin", "member"] },
        "update": { "owner": "paid_by" },
        "delete": { "any": [{ "role": "admin" }, { "owner": "paid_by" }] }
      }
    }
  }
}

What that definition gives you

  • A table in Postgres. Plain rows in expenses: the three columns plus id, created_at, updated_at and created_by. Nothing to migrate away from.
  • Four rules. Anyone signed in reads. Members add expenses. Whoever paid edits their own. They or an admin delete.
  • A live feed. Subscribe once and every insert, update and delete you are allowed to see arrives over the socket.
  • An explanation on every decision. delete expenses: allowed by any[1] owner(paid_by): row.paid_by "dana" == user "dana"

What you get

A database with a brain on top

Everything below is built and running today, on one server, over plain Postgres tables.

Declared tables

Name a table and its columns - text, int, float, bool, date, datetime, json, userId or a ref - and dabadata creates a plain Postgres table. Every row also gets id, created_at, updated_at and created_by, which clients never set.

Docs ->

Rules that read like membership

One rule per operation - read, create, update, delete - built from anyone, authenticated, role, owner, any and all. A missing rule means nobody, and an unsafe file is refused before it is applied.

Docs ->

An explanation on every decision

Every evaluation returns a sentence naming the path that decided, like delete tasks: denied, role "viewer" not in ["admin"]. The client, the trace and the agent all get the same sentence.

Docs ->

The trace

Every call writes one row: who called, the op and table, the decision, the rule and its explanation, the values before and after. It also records the fan-out - how many live subscribers the change reached.

Docs ->

Live subscriptions

One socket carries all of a client's subscriptions. The server sends the matching rows, then a change message for every insert, update and delete the subscriber's read rule lets them see.

Docs ->

Bring your own identity

Your backend signs people in its own way and mints a user token with their id, name and role. Declare the providers you trust (Google, Apple, Clerk, Auth0, Firebase, Supabase, Keycloak or your own JWTs) and hand their tokens straight to dabadata. The project key is for your servers, view tokens are for the viewer, and a call with no token is anonymous.

Docs ->

MCP for agents

An agent reads the schema with a plain-language summary of its rules, changes rows under those rules and reads the trace. It can simulate a decision before acting, and a denial comes back with its explanation.

Docs ->

WordPress plugin + viewer

The plugin mirrors a site's changes - posts, meta, users, comments, terms, WooCommerce orders - as they happen. The viewer, in wp-admin or on its own, shows Tables, Trace and a Rules simulator.

Docs ->

How it works

You describe the app. Your agent sets up the backend.

dabadata is written to be read by an AI agent: /llms.txt, every docs page as markdown, an OpenAPI file and an MCP server. You keep the parts that need you - what to build and whether it is right.

  1. Sign up and hand over the keys

    Free, no card. Copy the test environment's keys from the console into the project's .env, where the agent can read them and your browser code never ships them.

    .envbash
    DABADATA_URL=https://dabadata.com
    DABADATA_PUBLISHABLE_KEY=pk_test_...  # safe in a browser
    DABADATA_SECRET_KEY=sk_test_...       # server only
  2. Tell your agent what to build

    Claude Code, Cursor, Codex or any agent that reads the web and your files. One link teaches it the API, the rules and the safe way to write.

    prompttext
    Read https://dabadata.com/llms.txt
    and follow it. My keys are in .env.
    
    Build: a shared expenses app for my
    flat - who paid what, who owes whom.
  3. It checks the plan, then applies it

    The agent writes the tables and one rule per operation, asks for a dry run, and applies only what it saw. Applying adds tables and columns, never drops one, and an unsafe definition is refused before anything changes.

    PUT /v1/schema, dry runjson
    { "ok": true,
      "plan": ["create table members",
               "create table expenses"],
      "drift": [] }
  4. When a call is refused, it reads why

    Every denial names the rule that decided, in words, with a trace id. The agent fixes the rule or the call instead of retrying blind, and you can read the same trace in the console.

    403 forbidden: the explanationtext
    delete expenses: denied,
      role "member" not in ["admin"]
    
    # with a traceId for the full record

The trace is the product

Every call, with the rule that decided

Debugging access is reading, not guessing. Every mutation, read and subscription leaves one row behind: who called, what they tried, which rule applied and the sentence that explains the outcome.

The simulator answers the question directly. As user X, on row Y, is this allowed, and which rule decided? It changes nothing and runs the same rule engine as the real call.

An agent reads the same trace. When its write is refused, the MCP server hands back the explanation and the trace id, so it can repair its own mistake instead of retrying blind.

Built for

One API, three ways in

Every way in uses the same API, the same rules and the same trace.

Developers

Integrate from your own app with the zero-dependency JS client or the HTTP API: insert, update, delete, query and subscribe. Every refusal arrives with its explanation and its trace id.

JS client ->

People building with an agent

Point your own agent at the MCP server. It reads the schema and its rules in plain language, works under the same rules as everyone else, and reads the trace when something is refused.

MCP server ->

Site owners

Start with the WordPress plugin. It mirrors every change your site makes, so you watch your data flow live while the site keeps running exactly as it does today.

WordPress plugin ->

Where we are

Honest status

What runs today, and what comes next. No dates promised.

Today

  • Declared tables in plain Postgres
  • Rules with an explanation on every decision
  • Insert, update and delete under the rules
  • A trace of every interaction
  • Live subscriptions, fanned out in-process
  • MCP server for agents
  • Zero-dependency JS client
  • Viewer: Tables, Trace, Rules simulator
  • WordPress plugin that mirrors a site's changes
  • Hosted projects and a console: sign up free
  • Hosted sign-in for your app's users
  • File storage under the same rules, uploaded straight to object storage
  • Static sites at <name>.dabadata.site or your own domain
  • Actions that call Claude, OpenAI or Gemini with your key
  • Webhooks when rows change: signed, retried, every delivery in the trace
  • Restricted keys for your backend jobs, under your rules
  • Scheduled actions: your actions on a timetable, no cron job of your own
  • Self-host it: docker compose up, your Postgres, your machine

Pricing

Start free, pay per organization

Never per developer, never per read. Live updates ride one socket, not a metered call.

Free

$0

  • 50 concurrent connections
  • 500 MB database
  • 3 days trace retention

Enterprise

Call us

  • Custom limits and region
  • Backups: PITR 30 days + replica
  • 99.95 % uptime, SLA

See it move

Two people, one live database. Change a row on one side, watch it land on the other, and read why each action was allowed or denied.