MainSDK
Search⌘K
How-to

Call a model

Call a model through ai with limits and audit, and get typed output.

Building for 0.3

Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.

Stability The promise an interface ships with.

  • Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
  • Beta Usable in production; may change before it becomes stable.
  • Experimental May change or go away; needs an explicit opt-in in main.yaml.
Stability levels
Updated 2026-10-28

You will configure a driver, call a model, and get output checked against a schema. It takes about 15 minutes.

You need

  • A provider key in your secrets manager (for example secret:ANTHROPIC_API_KEY).

For a first run with no key, use driver: local: it needs no account and no network and prices every call at $0.

1. Configure

main.yaml
ai:
  driver: anthropic
  models: [anthropic/claude-*]
  limits: { per-user: $1/day, total: $500/month }
  prices:
    anthropic/claude-sonnet-4-5: { input: $3, output: $15 }   # a model with no price cannot be called

2. Generate text

app/api/summary/route.ts
import { ai } from "mainsdk";

const user = { id: "u_1" };
const order = { id: "o_1" };   // your own order record

const text = await ai.generate({
  model: "anthropic/claude-sonnet-4-5",
  prompt: `Summarise order ${order.id}`,
  feature: "order-summary",
  user,
});

feature and user are what spend limits and the audit log group by. The audit record holds the model, tokens and cost, never the prompt.

3. Get typed data

lib/extract.ts
import { ai } from "mainsdk";
import { s } from "mainsdk/schema";

const user = { id: "u_1" };
const emailText = "Invoice 42, total $120, due 1 Dec";   // the email body
const Invoice = s.object({ total: s.string(), due: s.string() });
const found = await ai.extract({
  input: emailText,
  schema: Invoice,
  model: "anthropic/claude-sonnet-4-5",
  feature: "invoice-extract",
  user,
});
console.log(found.value.total);

Invalid output is repaired once (up to twice with repairs), then refused with MAIN-AI-0011. It is never returned.

Check it worked

A call over the per-user limit fails with MAIN-AI-0007 before anything reaches the provider. With driver: local and per-user: $0/day you can see it with no account.

Fail a change that makes a feature worse

Put an eval set next to the feature, then run it before every merge:

bash
npx mainsdk eval summarise --json
npx mainsdk eval summarise --update-baseline

mainsdk eval exits 1 when a score drops below its threshold or below the saved baseline. --update-baseline writes the baseline only when the run passes, and --max-cost stops the run before it spends more than you allow. mainsdk eval samples summarise --export samples.json exports the recorded samples for review.

Next

Was this page helpful?

↑↓ moveEnter openEsc close

Not decided yet