> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apostra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create an Agent

> Register a private Agent for your organization

`POST /api/v2/agents` creates a private Agent for an enrolled organization
account admin. Supply a unique `idempotencyKey`; repeating the exact request
returns the original Agent with `created: false`.

Sales Agents require `salesMode` of `WHOLESALE`, `COMPOSING`, or `BOTH`.
Non-Sales Agents must set `salesMode` to `null`. Choose an existing claimed
operator, or provide a new operator name to create it atomically with the
Agent. Creation never publishes an Agent or connects a Source.

The organization MCP surface also provides `open_create_agent_task` to open
the bounded Create Agent Task, and `open_agent_page` to open a created Agent.

<Note>
  This is available only to directly authenticated account admins enrolled in
  Organization Agents. Service-token and delegated sessions cannot create Agents.
</Note>

## Request

```bash theme={null}
curl -X POST "https://api.apostra.com/api/v2/agents" \
  -H "Authorization: Bearer $INTERACTIVE_USER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "displayName": "Acme Signal Agent",
    "role": "SIGNAL",
    "salesMode": null,
    "operator": { "kind": "NEW", "displayName": "Acme" },
    "idempotencyKey": "20000000-0000-4000-8000-000000000003"
  }'
```

## Parameters

| Field                  | Type         | Required        | Notes                                                                           |
| ---------------------- | ------------ | --------------- | ------------------------------------------------------------------------------- |
| `displayName`          | string       | Yes             | Agent name, 1–255 characters after trimming.                                    |
| `role`                 | enum         | Yes             | `SALES`, `SIGNAL`, `CREATIVE`, or `OUTCOME`.                                    |
| `salesMode`            | enum or null | Yes             | `WHOLESALE`, `COMPOSING`, or `BOTH` for `SALES`; `null` for every other role.   |
| `operator.kind`        | enum         | Yes             | `EXISTING` or `NEW`.                                                            |
| `operator.operatorUid` | UUID         | When `EXISTING` | A claimed operator owned by your organization.                                  |
| `operator.displayName` | string       | When `NEW`      | New operator name, 1–255 characters after trimming.                             |
| `idempotencyKey`       | UUID         | Yes             | Reuse only for the same request to safely recover from an interrupted response. |

## Response

New creation returns `201`; an exact idempotent replay returns `200`.

```json theme={null}
{
  "agentId": "20000000-0000-4000-8000-000000000001",
  "href": "/42/agents/20000000-0000-4000-8000-000000000001",
  "created": true
}
```

`href` is a handoff target for the canonical Agent Page. It is not a public
Agent URL.

## Errors

* `400 VALIDATION_ERROR` — the request is malformed, a name is empty, the
  role and sales mode are incompatible, or the operator union is invalid.
* `403 ACCESS_DENIED` — the caller is not a directly authenticated organization
  account admin.
* `404 NOT_FOUND` — Organization Agents is unavailable to the caller's enrolled
  organization, or the requested existing operator is not owned and claimed.
* `409 CONFLICT` — the idempotency key was previously used with different input.
  A duplicate active `NEW` operator name in your organization also returns this
  conflict; select the existing claimed operator instead.

See [Errors](/v2/reference/errors) for the full error contract.

## Apostra-mapped operators awaiting claim

Apostra sometimes maps a known operator to your organization before anyone on
your team explicitly claims it — for example, from an audited legacy
integration. A mapped-but-unclaimed operator shows up in `GET /api/v2/agents`
as **Apostra mapped · unclaimed**, and any Agent behind it cannot receive
production revisions, certification, or new connections until an organization
account admin claims it.

Claiming preserves the operator's identity, revisions, bindings, and history —
it never creates a second copy. Claim it with:

```bash theme={null}
curl -X POST "https://api.apostra.com/api/v2/provider/registration/operators/{operatorUid}/claim" \
  -H "Authorization: Bearer $INTERACTIVE_USER_ACCESS_TOKEN"
```

`operator.kind: "EXISTING"` for a Create Agent request only accepts an
already-claimed operator (`404 NOT_FOUND` otherwise per the [Errors](#errors)
table above) — this is deliberate: creating a new Agent under an unclaimed
operator would silently duplicate an identity Apostra already knows about.
Claim the mapped operator first, then create the Agent under it.

## MCP tools

`open_create_agent_task` opens the bounded Create Agent Task for an organization
admin when the organization is enrolled in the Agents preview or has active
Partner program access. After creation, `open_agent_page` opens the private
Agent Page by `agentId`; it is also restricted to directly authenticated
organization account admins.
