# Agent Onboarding (/build/agent-onboarding)



Connect any AI agent to headless.ly in seconds. No API key, no signup, no OAuth flow. The agent starts operating immediately and progressively unlocks capabilities.

```json
{
  "mcpServers": {
    "headlessly": {
      "url": "https://headless.ly/mcp"
    }
  }
}
```

That's the entire configuration. The agent connects at L0 (anonymous read-only) and can upgrade to full production without ever leaving the MCP conversation.

Connect [#connect]

Point any MCP-compatible client at `https://headless.ly/mcp`. No `Authorization` header, no API key, no bearer token:

```json
{
  "mcpServers": {
    "headlessly": {
      "url": "https://headless.ly/mcp"
    }
  }
}
```

The agent is now connected at **L0** -- anonymous, read-only, 30 requests per minute. Every MCP response includes a `_meta` object describing what the agent can do and how to unlock more.

Explore [#explore]

The first thing an agent should do is call the `explore` tool to discover the full entity graph:

```json title="headless.ly/mcp#fetch"
{ "type": "schema" }
```

This returns all 35 entities across 11 product domains -- Identity, CRM, Billing, Projects, Content, Support, Analytics, Marketing, Experimentation, Platform, and Communication -- with their verbs, relationships, and field definitions. No documentation lookup required. The system describes itself.

Search and Fetch [#search-and-fetch]

At L0, agents can read everything. Search finds entities across the graph:

```json title="headless.ly/mcp#search"
{ "type": "Contact", "filter": { "stage": "Lead" } }
```

Fetch retrieves a specific entity with related data:

```json title="headless.ly/mcp#fetch"
{ "type": "Contact", "id": "contact_uLoSfycy", "include": ["deals", "organization"] }
```

Fetch also retrieves system-level information:

```json title="headless.ly/mcp#fetch"
{ "type": "Metric", "id": "mrr" }
```

These are read-only operations. The agent can explore the entire business graph -- contacts, deals, subscriptions, metrics, projects -- without any authentication.

Provision [#provision]

When the agent needs write access, it upgrades from L0 to L1 by requesting a session:

```json title="headless.ly/mcp#fetch"
{ "type": "session", "action": "provision" }
```

The response includes a session token and updated `_meta`:

```json
{
  "session": "hly_sess_xK9mNpQr",
  "level": 1,
  "limits": { "entities": 1000, "ttl": "24h", "rateLimit": "100/min" },
  "_meta": {
    "level": 1,
    "capabilities": ["search", "fetch", "try", "do"],
    "upgrade": "Commit .github/workflows/headlessly.yml to claim this tenant"
  }
}
```

At **L1**, the agent gets a sandboxed workspace: 1,000 entities, 24-hour TTL, 100 requests per minute. The session token is automatically included in subsequent MCP requests for the duration of the conversation.

Try Before You Do [#try-before-you-do]

The `try` tool lets agents simulate operations without persisting anything. Available at L1+:

```ts title="headless.ly/mcp#try"
const contact = await $.Contact.create({ name: 'Alice', email: 'alice@example.com', stage: 'Lead' })
await $.Contact.qualify(contact.$id)
await $.Deal.create({ contact: contact.$id, value: 25000, stage: 'Negotiation' })

return { contact, deal: await $.Deal.find({ contact: contact.$id }) }
```

The response shows exactly what would happen -- entities created, events emitted, side effects triggered -- but nothing is written. The agent can validate its plan before committing.

Do [#do]

Execute real operations with the `do` tool. Everything the `try` tool previewed now persists:

```ts title="headless.ly/mcp#do"
const contact = await $.Contact.create({ name: 'Alice', email: 'alice@example.com', stage: 'Lead' })
await $.Contact.qualify(contact.$id)
await $.Deal.create({ contact: contact.$id, value: 25000, stage: 'Negotiation' })

return { created: contact.$id }
```

At L1, writes are sandboxed -- isolated to the session, no external side effects, no webhook delivery. This is a safe space for agents to build and test workflows.

Claim [#claim]

To upgrade from L1 to L2, the agent claims the tenant by linking it to a GitHub identity. This is the **claim-by-commit** flow:

1. Generate the workflow file [#1-generate-the-workflow-file]

```ts title="headless.ly/mcp#do"
const claim = await $.session.claim()

return {
  file: '.github/workflows/headlessly.yml',
  content: claim.workflow,
  token: claim.token,
  instructions: 'Commit this file to your repo and push. The push event verifies your identity.'
}
```

2. Commit to the repo [#2-commit-to-the-repo]

The agent writes `.github/workflows/headlessly.yml` to the repository and pushes:

```yaml
