# Add a role to the team

URL: /agents/add-a-role · Id: `guide:add-a-role`

> Create a Role for work no seat on the chart covers, and seat an agent in it in two calls.

Create a [Role](/business/nouns/role) for work no seat on the chart covers, and seat an [Agent](/business/nouns/agent) in it. Your agent first checks that no seat already answers to the name: a bookkeeper is the [Finance Lead](/agents/finance/finance-lead).

**Before it runs**

- You leave the chat: Never: it all happens in the chat.

## What you get
- 1 new seat with its job, duties and limits written down (Role)
- 1 agent in the seat, with its own name in your business (Agent)
- 1 tools: only what its duties need (Permission)
- 1 questions come to you until a team lead takes them (Role)

## Your agent does
**For agents**

- Guide: `guide:add-a-role`, status `live`. Page: [/agents/add-a-role.md](/agents/add-a-role.md).
- Approval: none. Run it when the founder asks.
- Leaves the chat: never.
- Run: call the steps in order, each through the API, SDK, CLI or MCP tab below; a later step passes the `$id` an earlier one returns. Each value marked example is the sample business’s: pass the founder’s own.

| Step | Verb | Inputs (type, required, this guide’s value) | Returns |
| --- | --- | --- | --- |
| 1 | [`Role.create`](/business/nouns/role/create) (`verb:Role.create`) | `name` string, required: example `"Maintenance Coordinator"`; `responsibilities` text: example `"Books a vendor for every repair request within one business day. Tells the resident the visit time."` | `role` Role |
| 2 | [`Role.staff`](/business/nouns/role/staff) (`verb:Role.staff`) | `role` Role (an id), required: the `$id` step 1 returns; `worker` Worker (an id), required: example `"agent_maintenance_coordinator"` | `role` Role |

Returns: the last call answers with `role` and its `action`, whose `status` is `done`, `pending` (waiting on an Approval or a Worker), `failed`, `canceled` or `refused`:

```json
{
  "api": "https://api.sb/leaseline.app",
  "role": {
    "$id": "https://api.sb/leaseline.app/roles/role_1",
    "$type": "Role",
    "name": "Maintenance Coordinator",
    "responsibilities": "Books a vendor for every repair request within one business day. Tells the resident the visit time.",
    "status": "filled"
  },
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/action_1",
    "operation": "Role.staff",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/leaseline.app/actions/action_1"
  }
}
```

Next: offer “Put it on the Operations Team”, or “Let it book repairs up to $300 without asking”.

Calls: `Role.create` → `Role.staff`

Ask:

```text
Add a maintenance coordinator to the team.
I need someone to book repair vendors.
Create a new role for leasing.
```

API:

```bash
# 1. Role.create
ROLE=$(curl -X POST https://api.sb/leaseline.app/roles \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Maintenance Coordinator","responsibilities":"Books a vendor for every repair request within one business day. Tells the resident the visit time."}' | jq -r '.role["$id"] | split("/") | last')

# 2. Role.staff
curl -X POST https://api.sb/leaseline.app/roles/$ROLE/staff \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"worker":"agent_maintenance_coordinator"}'
```

SDK:

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

const role = await $.Role.create({ name: 'Maintenance Coordinator', responsibilities: 'Books a vendor for every repair request within one business day. Tells the resident the visit time.' })
await $.Role.staff({ role: role.$id, worker: 'agent_maintenance_coordinator' })
```

CLI:

```bash
ROLE=$(npx startup-builder do Role.create --json '{"name":"Maintenance Coordinator","responsibilities":"Books a vendor for every repair request within one business day. Tells the resident the visit time."}' | jq -r '.role["$id"] | split("/") | last')
npx startup-builder do Role.staff --json '{"role":"'"$ROLE"'","worker":"agent_maintenance_coordinator"}'
```

MCP:

```json
{
  "name": "do",
  "arguments": {
    "code": "const role = await $.Role.create({ name: 'Maintenance Coordinator', responsibilities: 'Books a vendor for every repair request within one business day. Tells the resident the visit time.' })\nreturn await $.Role.staff({ role: role.$id, worker: 'agent_maintenance_coordinator' })"
  }
}
```

## Change it
- Put it on the Operations Team.
- Let it book repairs up to $300 without asking.
- Have it escalate to the Operations Lead, not me.

## Under the hood
- Systems: [Workforce](/systems/workforce), [Work queue](/agents/work-queue)
- Nouns: [Role](/business/nouns/role), [Agent](/business/nouns/agent), [Permission](/business/nouns/permission), [Team](/business/nouns/team)
- Events: [`Role.staffed`](/business/events/Role.staffed)

Write the contract before the seat opens: why it exists, the duties, the [Metric](/business/nouns/metric) that judges it and its [Limits](/business/nouns/limit). [Role contracts](/agents/roles) lists every part. A seat with no result Metric gives its [Role Review](/business/nouns/role-review) nothing to read.