# Register an Agent

This guide covers everything about registering a new agent identity, including all fields, validation rules, and how to fix common errors.

---

## The registration request

`POST /api/v1/agents`

Requires: `Authorization: Bearer <token>` with `agents:write` scope.

### Request fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `email` | string (email) | Yes | Unique identifier for this agent. Must be a valid email format and unique across all registered agents. |
| `agentType` | string (enum) | Yes | Functional classification of the agent. See values below. |
| `version` | string (semver) | Yes | Semantic version of the agent software (e.g. `1.0.0`, `2.3.1-beta`). |
| `capabilities` | string[] | Yes | One or more capability strings in `resource:action` format. Minimum 1. |
| `owner` | string | Yes | Team or organisation that owns this agent. 1–128 characters. |
| `deploymentEnv` | string (enum) | Yes | Target deployment environment. See values below. |
| `organization_id` | string (UUID) | No | UUID of the organization to scope this agent to. Recommended on all multi-tenant instances. |

### `agentType` values

| Value | Description |
|-------|-------------|
| `screener` | Screens or filters content |
| `classifier` | Classifies or categorises inputs |
| `orchestrator` | Coordinates other agents or workflows |
| `extractor` | Extracts structured data |
| `summarizer` | Produces summaries |
| `router` | Routes requests to other agents |
| `monitor` | Monitors systems or outputs |
| `custom` | Any type not covered above |

### `deploymentEnv` values

| Value | Description |
|-------|-------------|
| `development` | Local or dev environment |
| `staging` | Pre-production testing |
| `production` | Live production workloads |

### `capabilities` format

Each capability is a string matching `resource:action`. Examples:

```
resume:read
email:send
candidate:score
document:classify
data:*
```

The `*` wildcard in the action position means all actions on that resource. Capabilities are informational in Phase 1.

---

## Example — register a screener agent

```bash
curl -s -X POST http://localhost:3000/api/v1/agents \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "screener-001@talent.ai",
    "agentType": "screener",
    "version": "1.0.0",
    "capabilities": ["resume:read", "email:send", "candidate:score"],
    "owner": "talent-acquisition-team",
    "deploymentEnv": "production",
    "organization_id": "'$ORG_ID'"
  }' | jq .
```

Successful response (`201 Created`):

```json
{
  "agentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "screener-001@talent.ai",
  "agentType": "screener",
  "version": "1.0.0",
  "capabilities": ["resume:read", "email:send", "candidate:score"],
  "owner": "talent-acquisition-team",
  "deploymentEnv": "production",
  "status": "active",
  "createdAt": "2026-03-28T09:00:00.000Z",
  "updatedAt": "2026-03-28T09:00:00.000Z"
}
```

The `agentId` is assigned by the system — it is immutable and never changes.

> **Organization scoping**: If you include `organization_id` in the request, the agent is
> associated with that organization. Analytics, webhook events, and tier enforcement are all
> scoped by organization. To create an organization first, see the
> [Quick Start](../quick-start.md) guide.

---

## Immutable fields

After registration, the following fields **cannot be changed**:

- `agentId` — system-assigned, permanent
- `email` — the agent's stable identity
- `createdAt` — registration timestamp

To update any other field, use `PATCH /api/v1/agents/{agentId}`.

---

## Common errors and fixes

### `400 VALIDATION_ERROR` — invalid email format

```json
{
  "code": "VALIDATION_ERROR",
  "message": "Request validation failed.",
  "details": { "field": "email", "reason": "Must be a valid email address." }
}
```

**Fix**: Use a valid email format, e.g. `my-agent@myproject.ai`.

---

### `400 VALIDATION_ERROR` — invalid version format

```json
{
  "code": "VALIDATION_ERROR",
  "message": "Request validation failed.",
  "details": { "field": "version", "reason": "Must be a valid semantic version string." }
}
```

**Fix**: Use semantic versioning — `1.0.0`, `2.1.3`, `1.0.0-beta.1`. The format is `MAJOR.MINOR.PATCH`.

---

### `400 VALIDATION_ERROR` — invalid capability format

Capabilities must match `resource:action` — lowercase letters, numbers, hyphens, and underscores only.

**Fix**: Use `resume:read` not `Resume:Read` or `read-resume`.

---

### `409 AGENT_ALREADY_EXISTS` — duplicate email

```json
{
  "code": "AGENT_ALREADY_EXISTS",
  "message": "An agent with this email address is already registered.",
  "details": { "email": "screener-001@talent.ai" }
}
```

**Fix**: Choose a different email address. Each agent must have a unique email.

---

### `403 FREE_TIER_LIMIT_EXCEEDED` — 100 agent limit reached

```json
{
  "code": "FREE_TIER_LIMIT_EXCEEDED",
  "message": "Free tier limit of 100 registered agents has been reached.",
  "details": { "limit": 100, "current": 100 }
}
```

**Fix**: Decommission agents you no longer need before registering new ones.
