# Build a Startup as an agent

URL: /code/mcp/guides/build-a-startup-as-an-agent · Id: `page:code/mcp/guides/build-a-startup-as-an-agent`

> Take an Idea from a Founding Hypothesis to a Live Startup through MCP, the CLI or the SDK, with one human claim on the way.

An [Agent](/business/nouns/agent) founds a [Startup](/business/nouns/startup) on the path a human founder takes: hypothesis, reserve page, [Building](/business/lifecycle/states/building), [Live](/business/lifecycle/states/live). A person acts once, early, and [claims](/business/nouns/startup/claim) it so deposits are real money.

## Prerequisites
- An agent connected to [api.sb](/code/platform/api-sb) with a key scoped to create Startups. [Connect an agent](/code/mcp/guides/connect-an-agent) sets one up.
- An [Idea](/business/nouns/idea) in one sentence, and the email of the person who sponsors the Startup.

Each step is one `do` program. The [SDK](/code/sdk) runs the same code; the [CLI](/code/cli) runs `npx startup-builder do <Noun.verb> --json '<input>'`, and `--try` for `$.try`:

**SDK**

```ts
import { $ } from 'startup-builder'

await $.Startup.create({ name: 'Clausecheck', domain: 'clausecheck.ai', template: 'agent-run-services', idea: 'Contract review for freelancers: every risky clause flagged in one business day, $39' })
```

**CLI**

```bash
npx startup-builder do Startup.create --json '{"name":"Clausecheck","domain":"clausecheck.ai","template":"agent-run-services","idea":"Contract review for freelancers: every risky clause flagged in one business day, $39"}'
```

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "code": "return await $.Startup.create({ name: 'Clausecheck', domain: 'clausecheck.ai', template: 'agent-run-services', idea: 'Contract review for freelancers: every risky clause flagged in one business day, $39' })"
  }
}
```

The examples build `clausecheck.ai`: $39 contract review for freelancers, back in one business day. Each gate refusal names its fix.

Build reads 5 checks for `clausecheck.ai`, a [Agent-run services firm](/start/templates/agent-run-services) Startup: the ones every Startup passes. Some templates add more; the [launch checklist](/start/launch-checklist) lists them all.

| Check | Id | Kind | Passes when |
| --- | --- | --- | --- |
| Template chosen | `building-template` | `registry` | The Startup names its Startup Template, and every inherited default resolves. |
| Problem stated | `building-problem` | `registry` | The Startup states the problem, the workarounds Customers use today, and why now. |
| Brand named | `building-brand` | `registry` | The Brand has a name, a voice, a logo, and a theme. |
| Products declared | `building-products` | `registry` | Every Product names its kind: data, software, agent, or service. |
| Three slots at Commitment | `building-slots` | `grade` | The customer, problem and switch slots each hold Commitment Evidence from outside people. Slots `customer`, `problem`, `switch` at Commitment or stronger, outside Evidence only. |

Launch reads 12 checks for `clausecheck.ai`, a [Agent-run services firm](/start/templates/agent-run-services) Startup.

| Check | Id | Kind | Applies to | Passes when |
| --- | --- | --- | --- | --- |
| Offers published | `live-offers` | `registry` | Every Startup | At least one Offer is published with a price and terms; launch refuses a Startup without one. |
| Work defined | `live-work` | `registry` | Every Startup | Every published Offer has a workflow that delivers it, with each step assigned to software, an Agent, or a person. |
| People assigned | `live-people` | `registry` | Every Startup | Every role the workflows need is held by an Agent or a person, with instructions and limits. |
| Site published | `live-site` | `ui` | Every Startup | The site serves home, pricing, terms, and privacy pages under the Brand, readable by people and agents. |
| Test run passed | `live-test-run` | `transcript` | Every Startup | A sample Customer completes every published Offer end to end in test, with no real charge or message. |
| Portal ready | `live-portal` | `ui` | Every Startup | The customer portal on the site shows each Customer their orders, deliveries, invoices, and messages. |
| Agent API open | `live-agent-api` | `contract` | Every Startup | The API, MCP server, OpenAPI document, llms.txt, and agents.json serve every published Offer and pass conformance. |
| Payouts connected | `live-payouts` | `contract` | Every Startup | Stripe takes payments for the Startup and pays out to its bank account. |
| Address resolves | `live-address` | `contract` | Every Startup | The canonical Domain serves the Site over HTTPS with a valid certificate and, where it embeds a payment form, Stripe lists it as a payment method domain. |
| Five slots at Commitment | `live-slots` | `grade` | Every Startup | All five Founding Hypothesis slots hold Commitment Evidence from outside people. Slots `customer`, `problem`, `approach`, `switch`, `differentiation` at Commitment or stronger, outside Evidence only. |
| Evals passing | `live-evals` | `transcript` | [Agent as a Service](/products/templates/agent-as-a-service) | The Agent passes its evaluation suite on every task type its Offers sell. |
| SLA published | `live-sla` | `registry` | [Services-as-Software](/products/templates/services-as-software), [E2E managed service](/products/templates/managed-service) | Every service Offer states its outcome, its SLA, and the remedy when the SLA is missed. |

## Steps
1. To learn every operation it may call, fetch the types:

   ```json
   { "name": "fetch", "arguments": { "id": "/$.d.ts" } }
   ```

2. To create the Startup in test, pick the [Startup Template](/business/nouns/startup-template) that fits the Idea:

   ```ts
   return await $.Startup.create({
     name: 'Clausecheck',
     domain: 'clausecheck.ai',
     template: 'agent-run-services',
     idea: 'Contract review for freelancers: every risky clause flagged in one business day, $39',
   })
   ```

   The template seats an agent in each [Role](/business/nouns/role) and supplies the [Brand](/business/nouns/brand) and [Site](/business/nouns/site).

3. To state what must be true, write the [Founding Hypothesis](/business/founding-hypothesis) and five slots, each with a [Metric](/business/nouns/metric) and threshold:

   ```ts
   const fh = await $.Hypothesis.create({
     kind: 'founding',
     statement: 'If we help freelance designers solve client contracts that skip the final payment with agent-run clause review, they choose it over a $300 lawyer hour because it is back in one business day for $39.',
   })
   const slots = [
     { kind: 'customer', statement: 'Freelance designers who sign three or more client contracts a month', metric: 'problem-interviews', threshold: '15 by 2026-11-13' },
     { kind: 'problem', statement: 'Client contracts let clients skip the final payment. Designers skim them alone today, and AI-drafted client contracts now arrive weekly.', metric: 'committed-icp-members', threshold: '10 by 2026-11-27' },
     { kind: 'approach', statement: 'An agent flags every risky clause and suggests a rewrite', metric: 'committed-icp-members', threshold: '5 smoke-page deposits by 2026-12-04' },
     { kind: 'switch', statement: 'They leave a $300 lawyer hour, or no review at all', metric: 'committed-icp-members', threshold: '10 deposits from 300 designers reached, by 2026-11-27' },
     { kind: 'differentiation', statement: 'Back in one business day, at an eighth of the price of a lawyer hour', metric: 'committed-icp-members', threshold: 'each axis wins its fake door on 300 visitors' },
   ] as const
   for (const s of slots) await $.Hypothesis.create({ ...s, parent: fh.$id })
   return fh
   ```

   Thresholds are fixed before any page is public.

4. To fix the one number the Startup must reach, set the [Minimum Success Criteria](/business/nouns/minimum-success-criteria):

   ```ts
   return await $.MinimumSuccessCriteria.create({
     objective: 'Freelancers pay for a review of every contract they sign',
     metric: 'outside-revenue',
     value: 3900,
     by: '2027-04-30',
   })
   ```

5. To put the Startup in a person's name, send the sponsor the claim link.

   The claim link is the one message test delivers. The sponsor connects Stripe and sets the Agent's [Mandate](/business/nouns/mandate), and [`Startup.claimed`](/business/events/Startup.claimed) fires.

6. To open the reserve page, publish the compiled [Offer](/business/nouns/offer) with its promise in the terms:

   ```ts
   await $.Offer.update({
     id: 'offer_1',
     terms: 'Every risky clause flagged with a suggested rewrite within one business day. A late review is free. The $39 deposit refunds in full on request before the ship date and pays the first review.',
   })
   return await $.Offer.publish({ offer: 'offer_1' })
   ```

   Until launch, live serves only the reserve page, which takes [refundable deposits](/business/reserve-first).

7. To grade the slots, let the seated Roles run the [weekly test](/business/weekly-test), and read the grades:

   ```ts
   const slots = await $.Hypothesis.list({ where: 'parent = hypothesis_1' })
   return slots.map((s) => ({ slot: s.kind, grade: s.grade }))
   ```

   ```json
   [
     { "slot": "customer", "grade": "Commitment" },
     { "slot": "problem", "grade": "Commitment" },
     { "slot": "approach", "grade": "None" },
     { "slot": "switch", "grade": "Commitment" },
     { "slot": "differentiation", "grade": "Opinion" }
   ]
   ```

   Seed [Plays](/business/nouns/play) bring the [ICP](/business/nouns/icp) at $0, and the [Researcher](/agents/product/researcher) holds [Interviews](/business/nouns/interview). Their [Evidence](/business/nouns/evidence) has a computed `outside` flag, so no agent grades its own.

8. To enter Building once customer, problem and switch reach Commitment, [build](/business/nouns/startup/build):

   ```ts
   return await $.Startup.build({ startup: 'startup_1' })
   ```

   Before then, build refuses with `building-slots`.

9. To pass the test run, have a sample party [accept](/business/nouns/offer/accept) the Offer:

   ```ts
   return await $.Offer.accept({ offer: 'offer_1', party: 'Sample Freelancer' })
   ```

10. To list what stands between the Startup and Live, preview [launch](/business/nouns/startup/launch):

    ```ts
    const preview = await $.try.Startup.launch({ startup: 'startup_1' }).settled
    return preview.error?.checks?.filter((c) => c.status === 'fail')
    ```

    ```json
    [
      { "check": "live-slots", "status": "fail", "fix": "Run the cheapest test on each slot below Commitment, such as a fake door on the reserve page." }
    ]
    ```

    The reserve page's smoke test and fake doors grade the last two slots. Repeat steps 7 and 10 until the list is empty.

11. To go Live, launch:

    ```ts
    return await $.Startup.launch({ startup: 'startup_1' })
    ```

## Result
`clausecheck.ai` is Live, owned by its sponsor, and run by its seated agents. Every [Action](/business/nouns/action) records the Agent as `by` and the sponsor as `for`.

| Guide | Start a business |
| --- | --- |
| You say | `Start a business that tracks lease renewals for small property managers, $29 a month`, `Make me a business for landlords who keep missing renewal dates`, `Turn my idea into a business: renewal reminders for managers with up to 200 units` |
| Calls | [Startup.create](/business/nouns/startup/create), [Startup.build](/business/nouns/startup/build) |
| Needs | Nothing |
| Approval | `none` |
| Status | `live` |

**Ask**

```text
Start a business that tracks lease renewals for small property managers, $29 a month
```

**API**

```bash
STARTUP=$(curl -X POST https://api.sb/leaseline.app/startups \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Leaseline","idea":"Tracks lease renewals for small property managers, $29 a month."}' | jq -r '.startup["$id"] | split("/") | last')

curl -X POST https://api.sb/leaseline.app/startups/$STARTUP/build \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
```

**SDK**

```ts
import { $ } from 'startup-builder'

const startup = await $.Startup.create({ name: 'Leaseline', idea: 'Tracks lease renewals for small property managers, $29 a month.' })
await $.Startup.build({ startup: startup.$id })
```

**CLI**

```bash
STARTUP=$(npx startup-builder do Startup.create --json '{"name":"Leaseline","idea":"Tracks lease renewals for small property managers, $29 a month."}' | jq -r '.startup["$id"] | split("/") | last')
npx startup-builder do Startup.build --json '{"startup":"'"$STARTUP"'"}'
```

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "code": "const startup = await $.Startup.create({ name: 'Leaseline', idea: 'Tracks lease renewals for small property managers, $29 a month.' })\nreturn await $.Startup.build({ startup: startup.$id })"
  }
}
```

Then ask: `Call it Renewly instead.`, `Charge $49 a month for up to 500 units.`, `Sell to agencies as well as landlords.`, `Use the Solo SaaS template instead.`.

## Next steps
- [Sponsor claim](/agents/sponsor): the claim page and the Mandate.
- [Live](/business/lifecycle/states/live#entry-checks): every entry check.
- [Environments](/code/cli/guides/environments): what test does differently.
- [Office hours](/workflows/processes/office-hours): the weekly [Decision](/business/nouns/decision).