Build with agents
How a coding agent reads, builds and repairs an app on MainSDK, and the rules it never breaks. The whole loop on one page, for the agent and the developer.
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.
This page is the whole loop for a coding agent and the developer who runs it: what the agent reads first, the rules it follows, how it builds and repairs, and what it must never do. Reading it takes about five minutes.
MainSDK is pre-release: the commands on this page are the planned design and do not run yet. mainsdk check --json --agent is planned for 0.3.
A coding agent builds your app. An app agent runs inside it and acts for a user; that is a different job, covered in Agents with an identity, a budget and approvals. The words are fixed in the vocabulary.
App agents path
If your app runs agents of its own, read these in order:
- Agents with an identity, a budget and approvals: name the agent in each call, give it a budget, and make a person approve risky or costly steps.
- MCP server and client: expose your actions as tools, and call other MCP servers from an allowlist, both under the same checks.
- Agent payments and wallets: let an agent pay a declared payee inside its budget, and add wallet sign-in (milestone 0.7).
What the agent reads first
| Read | Where | Why |
|---|---|---|
llms.txt | https://mainsdk.dev/llms.txt | The index of every docs page. Each page is also Markdown at https://mainsdk.dev/docs/<section>/<slug>.md, and https://mainsdk.dev/llms-full.txt has all of it. |
| The skill | .claude/skills/mainsdk/SKILL.md | The rules, the workflow, and the exact call shapes. Claude Code loads it; other agents reach it from the AGENTS.md section. |
| The rules files | AGENTS.md and CLAUDE.md | The short MainSDK section between <!-- mainsdk:start --> and <!-- mainsdk:end -->, written by mainsdk init. |
main.yaml | app root | What the app is, needs and may do. |
| The spec or issue | your tracker | What to build. Build only that. |
If a call or option is not in the docs or the skill's references/interfaces.md, it does not exist yet. The agent says so and never invents it.
The rules the agent follows
- Call interfaces (
import { auth, db, ai } from "mainsdk"), never a provider SDK. - Keep secrets out of code:
secret:NAMEinmain.yaml. - Deny by default. Every route and action names its permission, and records are read through
db.<model>.for(user). - Destructive actions ask a person, also when an agent calls them.
- Uploads and share links go through
filesandshare. - Declare what the change needs in
main.yaml(driver, permissions, data labels, network hosts) and keep the change minimal.
The loop
read the spec or issue
|
v
build on interfaces <-----------------------+
| |
v |
mainsdk check --json --agent |
| |
passed: true? --- yes --> report and stop |
| |
no |
v |
read each finding: code, file, line, fix |
| |
v |
fix the code (never the rule) ---------------+
Same finding still open after three rounds:
the check returns `ask: person`. Stop and ask.- Read the spec or the issue, then the interface page for each interface the change touches.
- Build on the interfaces. Write tests with
@mainsdk/testing. - Run
npx mainsdk check --json --agent. Exit code 0 means passed, 1 means a gate failed, 2 means a usage or configuration error. - Fix every finding from its
file,lineandfix. Runnpx mainsdk explain <code>if a fix is unclear. - Run the same command again.
- After the third unresolved round on the same finding, stop and ask a person. The repair loop has the output shape.
What the agent must never do
- Weaken a check: lower a severity, relax a
main.yamlrule, a network allowlist or a limit, delete a test or a gate, or hide a use behindraw(). - Add an exception without an owner and an expiry. An exception is a person's decision, so the agent proposes it and tells the developer.
- Call a provider SDK directly (
stripe,openai,@aws-sdk/*) for something an interface covers. - Commit a secret, a
.envfile or a key in the client bundle.
For agents
Goal: Make the requested change and reach `"passed": true`.
Read: llms.txt, .claude/skills/mainsdk/SKILL.md, AGENTS.md, main.yaml, the spec or issue.
Touch: the files the change needs, plus main.yaml to declare what it uses. Nothing else.
Verify: npx mainsdk check --json --agent (pass = "passed": true and exit code 0)
Repair: fix each finding from its file, line and fix. Re-run. After three unresolved
rounds on one finding, stop and ask the developer.
Never: weaken a check, add an exception without an owner and expiry, call a provider
SDK directly, or commit a secret.In this section
| Page | What it gives you |
|---|---|
| Prompts that work | Ten copy-paste prompts, each ending with the check to run and what a pass looks like |
| The repair loop | The shape of mainsdk check --json --agent and how an agent reads it |
| MCP server and client | Your actions as tools for agents, and your app calling other MCP servers |
| Agents with an identity, a budget and approvals | App agents with an audit identity, a budget, approvals and a kill switch |
| Agent payments and wallets | An agent paying a declared payee, and wallet sign-in |
Next
Was this page helpful?