Anthropic
Use the Anthropic API for MainSDK AI calls - API keys, main.yaml, the model allowlist, data-use rules, local testing and swapping.
Anthropic makes the Claude models, and its API is one of the drivers behind ai. Your app calls ai.generate() and ai.embed() as usual; the driver sends the redacted prompt straight to the Anthropic API. Pick it when you want Claude models without an AWS account, or as a fallback next to Amazon Bedrock, the default driver.
Interfaces it serves
Pick Anthropic in main.yaml for any of these. Your calls stay the same, and you can swap later.
aiBuilding for 0.3Driver anthropic Anthropic
ai:
driver: anthropicSwap to another provider
Before you start
You need an Anthropic account with API access.
- Create an API key. In the Anthropic Console, create a key for your app. Use separate keys for development, stage and production so you can revoke one without touching the others.
- Set spend limits on the account. MainSDK caps spend in your app, but a limit on the provider side is a second line of defence.
- Review the data terms for your account.
ai.datarequires no training and no retention. Check how Anthropic handles API inputs for your account, and whether you need an arrangement with Anthropic for the retention yourmain.yamlasks for.
Store the key in your secrets manager, never in code or a committed env file.
Configure
ai:
driver: anthropic
key: secret:ANTHROPIC_API_KEY # suggested name; [to be decided] key field name for drivers that need one
models: [anthropic/claude-*] # allowlist
data: { training: never, retention: zero }
limits: { per-user: $1/day, per-feature: { chat: $200/month }, total: $500/month }The key is always a secret: reference. A literal key in main.yaml fails mainsdk check. Anthropic's API host comes from the driver's declared hosts, so you don't add it to network.allow.
Use it
"use server";
import { ai, auth } from "mainsdk";
import { listOrders, refundOrder } from "@/actions/orders";
export async function chat(req: Request, messages: { role: "user" | "assistant"; content: string }[]) {
const session = await auth.require(req);
return ai.generate({
model: "anthropic/claude-sonnet", // [to be decided] model identifiers per driver
feature: "chat",
user: session.user,
messages,
tools: [ai.tool(listOrders), ai.tool(refundOrder)], // only functions declared with action()
});
}Tool results go back to the model through the injection check, and destructive actions still need a person's yes.
Local development and testing
- No key: set
ai.driver: localinmain.env.dev.yamlto use the built-in local fake. - Real calls in development: use a development key with a low cap in the dev overlay, for example
limits: { total: $10/month }. - Tests:
createTestApp()from@mainsdk/testingrunsaion its in-memory fake with redaction, caps and audit enforced.chaos.on("ai:anthropic", { outage: true })simulates an Anthropic outage. The spec's conformance suite runs the Anthropic driver against recorded responses.
import { it } from "node:test";
import assert from "node:assert/strict";
import { createTestApp } from "@mainsdk/testing";
import { ai } from "mainsdk";
it("ai.AC4 refuses a call that would pass the per-user cap", async () => {
createTestApp({ main: "./main.yaml" }); // limits.per-user: $1/day
const user = { id: "u_1" };
// [to be decided] helper to set a user's spend on the fake to $0.98
await assert.rejects(ai.generate({ model: "anthropic/claude-sonnet", feature: "chat", user, prompt: "hello" }), { code: "MAIN-AI-0007" });
});What MainSDK adds on top
- The API key never in your code, only a
secret:reference. - Providers, models or account modes that train on or keep prompts are refused; a declaration that doesn't meet
ai.datafailsmainsdk checkwithMAIN-AI-0001. - Personal data redacted before Claude sees it, and restored only inside your app.
- Spend limits per user, per feature and in total, checked before the call (
MAIN-AI-0007at the limit). - Every call audited with feature, model, tokens and cost, never the prompt.
See AI calls for the full contract.
Limits and notes
- The Anthropic driver comes with the
aispec (phase 1, milestone 0.3). - The name of the key field for keyed AI drivers is not final.
- How "no retention" is proven for a provider, by checking account settings or by your declaration, is an open question in the spec.
- The Anthropic API is not region-pinned in the way Bedrock is. If your prompts must stay in a MainSDK region (US, EU or India), check Anthropic's processing locations, or use Bedrock with a region set.
ai.raw()returns the Anthropic client for featuresaidoes not wrap.mainsdk checklists every use.
Swap to or from it
AI calls are stateless, so a swap is instant once mainsdk swap has run the contract tests:
ai:
driver: bedrock # was anthropic
region: us-east-1Your ai.generate(), ai.embed() and ai.tool() calls stay the same. The new driver must meet ai.data and serve a model in ai.models.
FAQ
Can I use the same Claude models through Bedrock instead? Yes. Keep models: [anthropic/claude-*] and change the driver to bedrock with a region. No code changes.
Where does my Anthropic API key go? In your secrets manager, referenced as secret:ANTHROPIC_API_KEY. It is read on the server only.
Do I need MainSDK Cloud for caps or audit? No. Caps, redaction and audit run in your app and are free.
Next
Open questions
Was this page helpful?