MainSDK
Search⌘K
Architecture

How MainSDK works

The four layers under every MainSDK call, and what the SDK in your app, the CLI and MainSDK Cloud each run and where.

Updated 2026-10-28

MainSDK is a library you import, a CLI you run, and an optional Cloud. Every call your app makes to an interface, for example email.send(), passes through the same four layers inside your process. Nothing runs beside your app: there is no sidecar, daemon or extra service, and no native binary to install (ADR-0001, ADR-0066).

Four layers under every call

flowchart TB
  app["Your code<br/>email.send(), db.orders.for(user), pay.checkout()"]
  subgraph sdk["Inside your app process"]
    iface["1. Interface<br/>one versioned contract, e.g. email@1.4"]
    guar["2. Guarantees<br/>unsubscribe link, owner scope, redaction, idempotency"]
    pol["3. Policy engine<br/>policy.decide(), Cedar by default, in process"]
    drv["4. Driver<br/>resend, ses, postgres, getqr.id …"]
  end
  prov["Provider API"]
  app --> iface --> guar --> pol --> drv --> prov
  pol -. decision .-> audit[("Audit log<br/>OCSF, hash-chained")]
Diagram
LayerWhat it doesExample
InterfaceThe contract you call. Written once in TypeSpec, versioned like email@1.4email.marketing({ to, template })
GuaranteesRules built into the contract, so the unsafe version is hard to writeemail.marketing() won't compile without an unsubscribe link
Policy engineThe single decision point. Every interface asks it before actingCan this user run orders.update? May this call reach api.resend.com?
DriverTalks to the provider. Swapping one is a line in main.yamlproviders: { email: resend }

Changing the provider changes only the bottom layer:

main.yaml
providers:
  email: resend          # was ses: change this line, no code change
fallback:
  email: [resend, ses]   # fail over if the first is down

Every interface also has an escape hatch, raw(), that returns the provider's own client. Each use is logged, listed by mainsdk check and marked as bypassing that interface's guarantees.

App, CLI and Cloud

flowchart LR
  subgraph you["Your machine and CI (free)"]
    cli["mainsdk CLI<br/>init · sync · check · dev · info · logs"]
    repo["Repo<br/>main.yaml · policies/ · main.lock"]
  end
  subgraph run["Where your app runs (free)"]
    sdk["mainsdk SDK<br/>interfaces, guarantees, policy engine, drivers"]
  end
  cloud["MainSDK Cloud (paid plans, phase 2)<br/>history, team views, debug loop"]
  tuf["TUF delivery<br/>baseline and market packs, driver metadata"]
  cli --> repo
  repo --> sdk
  tuf -. signed packs, background .-> sdk
  sdk -. buffered telemetry, after login and opt-in .-> cloud
Diagram
PartWhere it runsWhat it does
SDK (mainsdk)Inside your appRuns every call through the four layers. Never waits on our Cloud
CLI (mainsdk)Your machine and your CIinit writes main.yaml, sync plans changes as a pull request, check runs every gate, dev runs offline on local drivers, info shows what an app is and does
CloudOur regions: US, EU, India (phase 2)Hosted history, team views, live tail, debug sessions, replay, hosted triage

The dotted lines are never in the request path. Packs refresh in the background, and telemetry is buffered and dropped when the Cloud is unreachable. See request lifecycle.

What is free and what is paid

What runs inside your app and your CI is free and open source under Apache-2.0: every interface, guarantee, driver, check and the policy engine. Only what we run in our Cloud is paid, and security is never metered (ADR-0007). Plans and limits are on free and Cloud.

Next

Was this page helpful?

↑↓ moveEnter openEsc close

Not decided yet