> ## 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.

# Connect an agent in an Agents account

> The kinds of agent you can connect, what a sales mode is, and how to start from My agents, Ask Apostra, the Agents screen or MCP.

New to building on Apostra? Start with the [Developer quickstart](https://docs.apostra.com/v3/developer-quickstart.md).

Every agent you build lives in your organization's **Agents account**. An
organization holds one Agents account, and it holds any number of agents.
Name it with `accountId` on every call you make to create an agent. If the
organization has none, create it from the organization's **Accounts** screen or
with `save_account` in the organization account. A second Agents account is
refused.

Only a directly authenticated administrator of the Agents account can
create an agent. Service tokens, delegated sessions and impersonation cannot.

An administrator of the organization is an administrator of every account in
it, so you do not need to be added to the Agents account as a member. Open
it on the web or name it with `accountId`, and you can create, read and
register agents there. See
[Name the account on every call](https://docs.apostra.com/v3/name-the-account.md). A person who is only a member of the organization cannot, and a
Scope3 support person sees the agents read-only unless a staff elevation is
active.

## Start building

Any of these opens the same **Connect an agent** task:

* **My agents.** Choose **Connect an agent**.
* **Ask Apostra.** In the Agents account, ask for the agent you want, for
  example "build a sales agent for my publisher". Apostra opens the Connect an
  agent task. Ask Apostra's starter prompts in an Agents account cover building
  a sales, creative or buyer agent, testing an agent and getting it certified.
* **The Agents screen.** Choose **Connect an agent**.
* **MCP.** Call `open_create_agent_task` on the organization MCP surface. From an
  Agents account's `/mcp/v3` connection, call `open_developer_home` (or
  `open_agents_page`, which opens the same page), then choose
  **Connect an agent**. To connect an agent without the task, call `save_agent` with
  the agent's URL: see
  [Connect an agent from its URL](https://docs.apostra.com/v3/connect-an-agent.md#connect-an-agent-from-its-url).
  To register a sales or creative agent that has no URL yet, call `save_agent`
  with no `agentId`, and send `kind`, `displayName` and an `idempotencyKey`. For
  a sales agent you can also send `salesMode`. A buyer agent is created with
  `save_buyer_agent`.
* **REST.** `POST /api/v2/agents`. See [Create an Agent](https://docs.apostra.com/v2/storefront/agents/tasks/create-agent.md)
  for the request and errors.

### What the task asks

The task asks for one thing, the agent's URL, and then shows you what Apostra
read. The agent belongs to your organization. Everything it shows, and every field it makes required, comes
from the `save_agent` response, so an assistant calling `save_agent` sees the
same answers.

1. **Enter the URL.** Paste the agent's address and choose **Read agent**.
   Beside it are two other choices: **It's a buyer agent** and **I haven't built
   it yet**.
2. **Confirm.** The task shows the kind, the sales mode if it is a sales agent,
   a suggested name, what the agent also declares and what Apostra read. You can
   change the name and the sales mode. A field the agent did not declare is empty
   and required. If the agent declares both a sales and a creative role, you
   choose the kind first.
3. **Connect.** Apostra records the agent and its URL, then starts its first
   test. The task shows **Connected** while a creative agent's test runs, and
   **Tested** when the test passes. If the test fails, times out or does not
   run, the agent stays connected, the task says which, and a failed creative
   test can be run again from the task. A sales agent's check runs again from
   its Agent page.
4. **Connect as the other kind.** When the agent also declares the other offered
   kind, the task offers **Connect as sales agent too** or **Connect as creative
   agent too**. Each kind is its own agent and its own confirm, so connecting
   one never connects the other, and the task reads the agent again for the kind
   you choose.

If a read fails, the task shows the reason for it in plain words and keeps the
address you typed, so you can correct it or try again. The reasons are listed in
[When a read fails](https://docs.apostra.com/v3/connect-an-agent.md#when-a-read-fails).

**It's a buyer agent** skips the read. A buyer agent calls Apostra with a
credential and Apostra never calls it, so you give it a name, and the task
creates it and opens the credential step. Apostra stores no URL for a buyer
agent. **I haven't built it yet** registers an agent by kind and name only, so
you can connect its URL later from its Agent page.

Registering an agent by kind and name records its identity only. It does not
publish the agent, connect a source or request credentials. See [Agents](https://docs.apostra.com/v2/concepts/agents.md).

## Connect an agent from its URL

You can paste an agent's URL and let Apostra read what it is, then save it.
Apostra calls the agent's `get_adcp_capabilities` tool, works out the kind of
agent it is, how a sales agent sells and what to call it, and shows you the
result for you to confirm or correct. Saving it creates the agent in your
Agents account and records its URL, so the agent moves from Built to
Connected. To register an agent that has no URL yet, use a kind and a name, as in
[Start building](https://docs.apostra.com/v3/connect-an-agent.md#start-building), and connect it later.

### Preview what Apostra reads

Call `save_agent` with the agent's URL and `dryRun: true`. A preview needs no
`idempotencyKey`, saves nothing and creates no agent.

```json theme={null}
{
  "agentUrl": "https://agent.example.com/mcp",
  "dryRun": true
}
```

You can send three optional fields to confirm or correct what Apostra read:
`kind` (`sales` or `creative`), `salesMode` (`WHOLESALE`, `COMPOSING` or `BOTH`,
for a sales agent only) and `displayName`. A correction can change the name and
the sales mode. It can never add a role the agent does not declare: a `kind` the
agent does not declare is refused with the reason `kind_changed`.

### What Apostra reads

Apostra reads the agent with no credentials. It finds the agent's MCP endpoint,
lists its tools, and calls `get_adcp_capabilities`. The preview returns what the
agent declared, under `reading`:

| Field | What it is |
| - | - |
| `agentUrl` | The address that answered. It can be the address you pasted with `/mcp` added. It is never the address after a redirect. |
| `transport` | `mcp`. Only MCP agents can be connected today. |
| `protocols` | The agent's `supported_protocols`, as it declared them. |
| `adcpVersions` | The AdCP releases the agent declares. |
| `buyingModes` | The agent's `media_buy.buying_modes`, when it declares any. |
| `alsoDeclares` | Other protocols the agent declares besides sales and creative, such as `signals`. They are shown to you and decide nothing. |
| `brandJsonUrl` | The agent's own pointer to its owner's `brand.json`, kept as evidence. It does not decide the kind, the mode or the name. |

### What Apostra infers

What Apostra infers comes only from fields the agent declares. No product, price,
traffic or hostname decides anything. The result is under `inferred`.

| Question | How it is answered |
| - | - |
| Kind | `supported_protocols` containing `media_buy` makes a sales agent, and containing `creative` makes a creative agent. If the agent declares both, no kind is chosen: `kind` is `null`, `alternativeKinds` lists both and you choose one. If it declares neither, the read is refused with `kind_not_offered`. `kindReason` says why Apostra chose the kind. |
| Sales mode | The declared `media_buy.buying_modes`: `wholesale` and `brief` is `BOTH`, `wholesale` alone is `WHOLESALE`, `brief` alone is `COMPOSING`. An agent that declares no buying modes has said nothing, so no mode is inferred and you choose. `salesModeProvenance` is `AGENT_DECLARED` for a declared mode and `OWNER_CONFIRMED` for one you sent. |
| Name | The name the agent's own server reports. If it reports none, Apostra suggests its hostname followed by the kind, such as "example.com sales agent". `displayNameSource` says which, or `developer` for a name you sent. Treat the name as text the agent wrote. |

One role is previewed at a time. An agent that declares both sales and creative
can be connected as either, one after the other.

If a pasted URL has no AdCP agent behind it, Apostra makes one more public
request, for `/.well-known/brand.json` on the same address. When that file lists
the URL as a buying agent, the read reports the kind `buyer`. Apostra uses it only
as a suggestion and never stores the URL. Create the buyer agent with
`save_buyer_agent`.

### What `needs` means

`needs` lists what you still have to supply before an agent could be saved:
`kind` when the agent declares both kinds, and `salesMode` when a sales agent
declares no buying modes. An empty list means the read decided everything. Send
the missing field on the next preview to confirm it.

### Save the agent

To save, send the same call without `dryRun`, with an `idempotencyKey` (a UUID
you generate) and the confirmations you chose.

```json theme={null}
{
  "agentUrl": "https://agent.example.com/mcp",
  "kind": "sales",
  "salesMode": "BOTH",
  "displayName": "Example Sales",
  "idempotencyKey": "3a276b7c-af5f-4d2f-92ac-326d30a48f97"
}
```

Apostra reads the URL again when you save. It does not trust an earlier preview,
because the agent may have changed in between. A save is refused, and nothing is
created, when:

* `needs` is not empty. The error names the missing field (`kind` or `salesMode`)
  and carries the reason `needs_confirmation`. Send the field and save again.
* the `kind` you confirm is no longer one the agent declares (`kind_changed`).
* the URL reads as a buyer agent. Apostra never stores a buyer agent's URL, and the
  error points you to `save_buyer_agent` (`buyer_agent_not_connected_by_url`).
* your account already has an agent of this kind with that name. Choose another
  name.

One save connects one role. To connect an agent that declares both sales and
creative as both, save twice with a different `kind` and a different
`idempotencyKey`. Each role is its own agent.

### What saving creates

A successful save writes everything together, or nothing:

| What | Detail |
| - | - |
| The agent | In your Agents account, with the kind, the name and, for a sales agent, the sales mode. It belongs to your organization. |
| A revision | A record of what Apostra saw: the release the agent declared (its `build_version` when it gives one, otherwise its highest AdCP release) and a fingerprint of its declarations and tools. |
| The endpoint | The URL that answered. |
| A production deployment | The revision is the agent's current production revision, and the endpoint is its current endpoint. |
| A record that the URL is not yet verified as yours | See [Connected, Tested and not yet verified as yours](https://docs.apostra.com/v3/connect-an-agent.md#connected-tested-and-not-yet-verified-as-yours). |

The response is the `developer_created` outcome. It carries `agentId`, `created`,
`stage`, `reading`, `inferred`, `connection`, `test` and `endpointControl`. `connection.state` is
`connected` and `connection.revision` is the revision's id. `endpointControl`
is `unverified` or `verified`, as [Prove your agent is yours](https://docs.apostra.com/v3/connect-an-agent.md#prove-your-agent-is-yours)
explains. `stage` is the agent's
stage as `get_status` reports it, so the two always agree. `test` says which test
applies to the agent and what happened to it, as the next section explains.

### What happens right after connecting

Saving connects the agent first and tests it second. The test runs after the
connect has committed, so a test that fails, times out or cannot run never undoes
the connect: the agent stays **Connected**.

**A sales agent is checked inside the same call.** Apostra runs the endpoint
check against the URL it just read: one `get_products` call with a fixed no-spend
brief, sent with no credentials. The check may spend up to 10 seconds on
`get_products`, and it must be over within 25 seconds of the start of the
`save_agent` call. Reading the URL counts against those 25 seconds, so a slow read
leaves the check less time. The quick reads that build the response afterwards
are not counted. `test` carries `profile: "endpoint-brief"` and
one of these states:

| `test.state` | What it means | What the agent's stage is |
| - | - | - |
| `passed` | The agent answered `get_products`. | `tested` |
| `failed` | The agent answered with an error or an unusable reply. `test.finding` carries the check's own reason, as the agent reported it, and the text version of the response shows it fenced as untrusted. Nothing is undone. | `connected` |
| `timed_out` | The agent did not answer inside the budget. Apostra records no result, because a slow agent has not been shown to fail. | `connected` |
| `not_started` | The check was not run. `test.reason` says why: `rate_limited` when the agent already used its 10 endpoint checks for the hour, or `unavailable` when Apostra could not run or record the check. | `connected` |

For `failed`, `timed_out` and `not_started`, fix anything slow or failing at the
agent URL, then re-run the endpoint check from the agent's Agent page. `stuckOn` on
`get_status` names the same next step.

**A creative agent is handed off.** Creative conformance can take up to 90
seconds, which no tool call should wait for, so the response returns
`test: { "profile": "creative-conformance", "state": "not_started" }` and names how
it starts in `test.start`. The Connect an agent task starts it with
`POST /api/v2/agents/{agentId}/creative-conformance`, the call the Agent page
already makes. An assistant opens the Agent page with `open_agent_page`, because
there is no typed V3 call that starts a test yet. The creative agent stays
**Connected** until a conformance run passes.

**What Tested means.** An agent is **Tested** when its latest test run passed. A
passing sales endpoint check is recorded for 30 days, and a passing creative
conformance run for 7 days. Re-run the test before then to keep a current result.

### Connected, Tested and not yet verified as yours

An agent is **Connected** once Apostra holds its URL and has read it. It is
**Tested** when its latest test run passes. Saving runs the first test for a sales
agent and hands it off for a creative agent (see
[What happens right after connecting](https://docs.apostra.com/v3/connect-an-agent.md#what-happens-right-after-connecting)),
and later runs start from the agent's **Overview** page. Connected and Tested
are statements about the URL: Apostra read it, and it answered as an AdCP agent.

They do not say that you run the agent. Apostra cannot tell, from reading a URL,
who controls it, so every agent connected from a URL starts **not yet verified as
yours**: `endpointControl` is `unverified`. Until you
[prove you control the URL](https://docs.apostra.com/v3/connect-an-agent.md#prove-your-agent-is-yours), the
agent:

* cannot have **Allow certification buys** turned on: `certificationRequested: true`
  is refused with the reason `endpoint_control_unproven`. Turning it off is still
  allowed.
* cannot be given Partner standing or listed in the marketplace.
* cannot be used by another organization.

Only your own account can see the agent, so a connected URL never appears as
another company's agent.

### Prove your agent is yours

Apostra checks that you control an agent's URL by reading a file on the agent's own
host. It checks right after every connect, and again each time you connect the same
agent again with its `agentId` and `agentUrl`. There is no separate call and no new
input.

**What to publish, and where.** Serve a `brand.json` at
`https://<your agent's host>/.well-known/brand.json`, on the same host as the agent's
URL and nowhere else. Add an entry to its `agents` list for the agent:

```json theme={null}
{
  "brands": [{ "id": "northstar", "names": [{ "en": "Northstar" }] }],
  "agents": [
    { "id": "northstar_sales", "type": "sales", "url": "https://agent.northstar.example/mcp" }
  ]
}
```

* `url` is the agent's URL exactly as Apostra stores it, character for character:
  the same case, the same path, the same presence or absence of a trailing slash.
  The response of the connect names it as `reading.agentUrl`, and `stuckOn` repeats it.
* `type` is `sales` for a sales agent and `creative` for a creative agent.
* The file is a valid AdCP `brand.json`, which also gives each entry an `id` of lowercase letters, digits and underscores.

**The domain rule.** The agent's host must be a domain your organization has already
verified, or a subdomain of one. That is the domain registered on your account or
organization once Apostra has approved it: an email on the domain, a DNS TXT record,
or an Apostra review. See [Which domain is which](https://docs.apostra.com/v2/concepts/domains.md). A host on
another domain does not verify, even if its file lists the agent. If your agent runs
on a domain you have not verified, verify the domain first. A domain that only
resembles yours, such as `evilnorthstar.example`, does not count as `northstar.example`.

**How Apostra reads it.** Apostra fetches the file from that exact host. It follows
no redirect at all, so a file served from another host, or from a path the host
redirects to, does not count. It does not read the file `identity.brand_json_url`
points to. It reads from public addresses only, waits at most 8 seconds, and reads at
most 1 MB.

**How to re-check.** Publish the file, then connect the agent again with a new
`idempotencyKey`, its `agentId` and its `agentUrl`. The response shows
`endpointControl`, and the text version says why a check did not pass. A check counts
against the same hourly limits as reading the URL, when it fetches the file.

**What stays true afterwards.**

* Verification belongs to the URL it proved. Connect a different URL and the agent
  returns to `unverified`, until the file on the new host lists it.
* A check that fails because the file is briefly unreachable, missing or wrong
  leaves a `verified` agent verified. Only connecting a different URL, or losing
  the domain approval, ends the verification.
* Verification lasts only while the agent's host is on a domain your organization
  has verified. If the approval is withdrawn, for example the DNS record is
  removed or the member whose email proved the domain leaves, the agent reads as
  `unverified` at once in `get`, `get_status` and `stuckOn`, and certification,
  Partner standing, listing and use by other organizations are refused again, with
  no re-check. If the approval returns, the agent reads as `verified` again. If you
  connect the agent again while the approval is missing, Apostra records it as
  `unverified`, and it becomes `verified` again when you connect it again after the
  domain is approved.
* Until the agent is verified, `get_status` and `get` show `endpointControl:
  unverified`, and once the agent has passed its first test `stuckOn` tells you what
  to publish and where: the file URL, the entry with its `url` and `type`, and the
  domain rule. An agent that was not connected from a URL carries no
  `endpointControl` at all.

**What verification unlocks.** A verified agent can have **Allow certification buys**
turned on, can be certified, can be given Partner standing and listed, and can be
used by another organization.

### Retries and parallel saves

A save needs an `idempotencyKey`. Send the same key with the same request again
and Apostra returns the first agent with `created: false`, without reading the URL
again. Because nothing is read, `reading` and `inferred` are `null` in that
response, and no test runs again: `test` is the result already recorded for the
agent (`not_started` when none is recorded, for example after a `timed_out`).
Send the same key with a different request and the call is refused with a
conflict.

A key only protects a retry. If you save the same URL as the same kind twice with
different keys, even at the same moment, Apostra makes one agent and returns it
with `created: false` the second time.

### Connect an agent you already registered

To connect an agent you registered with a kind and a name, send its `agentId`
with the `agentUrl` and an `idempotencyKey`. A `dryRun` is not accepted here:
preview by omitting `agentId`.

* An agent with no endpoint yet gets its revision, endpoint and deployment.
* An agent that is already connected records a new revision when what Apostra
  reads from it changed. If nothing changed it keeps the revision it has. If the
  URL changed, the new URL becomes the agent's endpoint, for example after you
  restart a tunnel, and the agent returns to not yet verified as yours until the new
  URL is [proved](https://docs.apostra.com/v3/connect-an-agent.md#prove-your-agent-is-yours).
* The kind Apostra reads must be the agent's kind, and you must own the agent. The
  agent keeps its name and sales mode, so a call that sends `displayName` or
  `salesMode` with an `agentId` is refused. Rename an agent with `displayName`
  and no `agentUrl`.

### Which URLs Apostra accepts

* An `https` address, up to 2048 characters, with no username, password, query
  string or fragment, on the default port (443). A bare host such as
  `agent.example.com` is read as `https://agent.example.com`.
* A name, not an IP address.
* An address on the public internet. Apostra refuses `localhost`, private and
  internal addresses and any name that resolves to one.
* No redirect to another address. Apostra follows redirects that stay on the
  address you pasted.

Apostra limits a read to 8 seconds for each call, 20 seconds in all, and 1 MB for
any reply. It limits you to 20 reads an hour for the Agents account and 5 an
hour for the same URL. A preview counts as a read. Only a directly authenticated
administrator of the Agents account can read a URL, because the read makes
requests in Apostra's name. Service tokens, delegated sessions and impersonation
cannot.

### Test an agent running on your own machine

Apostra can only read agents reachable on the public internet, and there is no
override. To connect an agent that runs locally, expose it through a public
tunnel: a tunnelling service, or a reverse tunnel to a host you control. Paste the
tunnel's `https` address. When you restart the tunnel its address changes, so
paste the new address.

### When a read fails

A failed read creates nothing. A read that fails when you save creates nothing
either. In the Connect an agent task, the message for the reason appears under
the address field or in an alert on the confirm step, and the address you typed
stays in the field, so you can correct it or try again. A reason Apostra returns
that the task has no message for shows the server's own message. The error carries a closed `details.reason`, the
AdCP `recovery` (`correctable`, `transient` or `terminal`) and, where it applies,
`retry_after` in seconds.

| `details.reason` | What happened | What to do |
| - | - | - |
| `url_invalid` | The address is not a plain `https` address as described above, or it is an IP address. | Correct the address and read again. |
| `url_not_public` | The address is `localhost`, or a private or internal address, or a name that resolves to one. Apostra does not say which address it resolved to. | Use a public address. For a local agent, use a public tunnel. |
| `agent_unreachable` | The name did not resolve, the connection was refused or the TLS handshake failed. Apostra does not say which. | Check the address and that the agent is running, then try again. |
| `agent_timeout` | The agent did not answer in time. | Try again after `retry_after` seconds. |
| `authentication_required` | The agent needs credentials before it will describe itself. Apostra reads without credentials. | Register the agent with a kind and a name now, and connect it once a [storefront source](https://docs.apostra.com/v3/connect-an-agent.md#test-and-certify-your-agent) holds its credentials. |
| `no_adcp_server` | The address answers, but it is not an MCP server with `get_adcp_capabilities`. | Check that you pasted the agent's URL. |
| `adcp_version_unsupported` | The agent does not declare AdCP 3 or later. | Update the agent to support AdCP 3. |
| `transport_unsupported` | The address looks like an A2A agent. | Only MCP agents can be connected today. |
| `redirected_off_origin` | The address redirects to a different address. Apostra does not say which. | Paste the final address yourself. |
| `response_too_large` | The agent's reply was over 1 MB. | Make the agent's capabilities reply smaller. |
| `kind_not_offered` | The agent declares only protocols Apostra does not connect yet. The error lists them. | Apostra connects sales, creative and buyer agents. |
| `read_rate_limited` | You have read too many URLs. | Try again after `retry_after` seconds. |
| `kind_changed` | You sent a `kind` the agent does not declare. | Send the kind Apostra read, or leave `kind` out. |
| `needs_confirmation` | You saved before supplying a field in `needs`. | Send the field named in the error and save again. |
| `buyer_agent_not_connected_by_url` | The URL reads as a buyer agent, which Apostra does not connect by URL. | Create it with `save_buyer_agent`. |
| `agent_kind_mismatch` | The agent you named is not the kind the URL was read as, or is not a sales or creative agent. | Connect the agent with the URL that serves its kind. |
| `endpoint_control_unproven` | You asked for something an agent that is not yet verified as yours cannot have, such as `certificationRequested: true`. | [Prove you control the URL](https://docs.apostra.com/v3/connect-an-agent.md#prove-your-agent-is-yours), then ask again. |

## Find your agent's places

In the web app, an Agents account lands on **My agents** when it owns no agents or
several, and on the **Overview** of its agent, with the left rail already
switched into it, when it owns exactly one. My agents stays in the rail. The chat box
is under the page, as everywhere else.

My agents lists **your agents**, one row each, with the agent's kind, its
certification stage (Not started, Testing, Waiting on you, Waiting on Apostra,
Waiting on the seller or Certified), its next step and who acts on it. Choosing
a row opens that agent. It lists every agent the account owns, including any Signal or Outcome agent it already holds,
25 at a time, and **Show more
agents** adds the next 25. An agent Scope3 mapped to your account that nobody
has claimed is marked **Scope3 mapped · unclaimed**, and an account administrator
can choose **Review and claim** in its row. Under the agents are, in this order:

* **Connect an agent** is for an agent you already run, whether it is a sales,
  creative or buyer agent. It opens the Connect an agent task. With no agents it
  is the main card.
* **Set up an agent on Apostra** is for an agent Apostra hosts for you, starting
  with a buyer agent that plans and buys media for your advertisers. The card is
  hidden until hosted agents are offered to your account, and appears on its own
  when they are.
* **Work from Claude Code or Codex** has the MCP address, the commands that
  install the Apostra skill in Claude Code and in Codex, and the sentence to say:
  "Connect my agent" with no agents, "Get my agent certified" after.

The last rows are the guides ([Build an agent](https://docs.apostra.com/v3/build-an-agent.md), Connect an
agent and [Agent requirements](https://docs.apostra.com/v3/agent-requirements.md)) and links to the docs,
AdCP, the AAO and GitHub.

Whether an agent is verified as yours is not a status. An unverified agent's
next step says so ("Publish brand.json at your agent's domain to prove you own
this agent") and names who acts, and its certification stage is Not started.

To work on one agent, choose it from the picker at the top of the left rail. The
picker works like the advertiser picker: each agent has a kind label, the agents
you chose most recently come first, you can search, and **My agents** returns
you to My agents. Under the picker are only that agent's places:

* **Overview**: what needs your attention, the agent's states, the checklist
  with the evidence behind it (live certification results, tests and test runs,
  AdCP 4.0 readiness, capability declarations and, for a creative agent,
  conformance), the **Allow certification buys** switch and the agent's endpoint
  and protocol details.
* **Activity**: the calls Apostra made to the agent, grouped into certification
  runs. See [Read the calls Apostra made to your agent](https://docs.apostra.com/v3/connect-an-agent.md#read-the-calls-apostra-made-to-your-agent).
* **Inventory sources**: the sources connected to the agent.
* **Webhooks**: the recent inbound webhook outcomes, each refusal with its
  reason.

**API calls** stays under Account in both views. Each place is its own page.
Overview links to the agent's Activity, Inventory sources (Connections for an
agent that has no sources) and Webhooks pages, and each of those links back to
Overview. The changes you can make from a page are the **Allow certification
buys** switch and the one button each finding on Overview can carry (see
[Open the Overview page](https://docs.apostra.com/v3/connect-an-agent.md#open-the-overview-page)); the
other pages only read. Claude, ChatGPT and other MCP hosts open the same page
for the same place, so the web app and your assistant show you the same thing.
To change anything else about an agent, ask your assistant or call
`save_agent`.

`get_status` in an Agents account also returns, for each agent,
`findingsHeadline` (the finding the server chose to lead with, with its
severity and a summary) and `findingCount` (how many findings have not passed
yet). If the findings cannot be read, both are left out and the agent is still
listed.

## Read the calls Apostra made to your agent

Apostra records the calls it makes to your agent, and you can read each one that
went through a source bound to your agent when the call was made. A call
recorded with no source, or through a source that was not bound to your agent at
that time, is not shown. The **Activity** page shows them for one agent, in two
parts.

* **Certification runs.** Each [live certification run](https://docs.apostra.com/v3/certification.md#read-a-run-and-the-calls-apostra-made-to-your-agent)
  is one session, newest first. Its steps run from the first read of your
  products to the evaluation, in the order they happened. Each step shows when
  it happened, whether its calls succeeded, failed or are still pending, and a
  **View call** action for each call. The step that reads your products has no
  call to view, because Apostra reads them from its stored copy of your catalogue
  instead of calling your agent.
* **Other calls.** The calls that belong to no certification step, newest first,
  such as `get_adcp_capabilities` and `get_products`. Each has a **View call**
  action.

**View call** opens one call in place with a way back to the list. It shows what
Apostra sent, what your agent returned, the HTTP status, the status your agent
reported, how long the call took and the error. Apostra removes its own
credentials and the values under keys that look like credentials, such as
`token`, `secret` or `password`, and shows them as `[REDACTED]`. Each body is
capped at 32,768 characters and marked as cut short when it is longer. Apostra
keeps request and response bodies for 90 days. After that a call still shows its
timing and status, with no body.

You see every call Apostra made to your agent, whichever seller's storefront it
came from. Beside the calls, a certification run shows the facts listed under
[Read a run and the calls Apostra made to your agent](https://docs.apostra.com/v3/certification.md#read-a-run-and-the-calls-apostra-made-to-your-agent).
You never see another seller's prices, buyers or settings, or anything else that
was never sent to your agent. The history starts when your organization took the
agent. Moving the agent between accounts of one organization keeps it. A call
made before your organization took the agent, because Apostra staff assigned it
to you or it moved from another organization, is not shown. The seller whose
storefront the agent serves does not read this page.

On the Overview page, a certification finding that comes from a run has a
**View session in Activity** action. It opens the Activity page at that run.

To open the page, ask your assistant to open your agent's activity, or call
`open_agent_activity_page` with the agent's `agentId`. Only the account that owns
the agent can open it, and only while the agent is not archived. It changes
nothing. Archiving an agent does not remove its certification sessions: you can
still find and read them with `search` and `get`. To read the same runs and calls
without the page, use `search` and `get` with `kind: "session"`, as
[Read a run and the calls Apostra made to your agent](https://docs.apostra.com/v3/certification.md#read-a-run-and-the-calls-apostra-made-to-your-agent)
describes.

## Kinds of agent

| Kind | What it does |
| - | - |
| Sales agent | Sells a publisher's inventory to buyers. It needs a sales mode. |
| Creative agent | Defines creative formats and builds or renders creative for buyers and sellers. It has no sales mode. |
| Buyer agent | Buys on behalf of an advertiser, using the advertiser grants an organization gives it. |

The Connect an agent task registers sales, creative and buyer agents. A buyer agent
also needs a credential before it can call Apostra: follow
[Manage buyer agents](https://docs.apostra.com/v2/setup/buyer-agent-credentials.md).

## Sales modes

A sales agent declares how it sells. The mode follows the AdCP buying modes the
agent supports.

| Mode | Meaning |
| - | - |
| Wholesale | The agent lists its products as a catalog, and a buyer can browse and buy them as declared. |
| Composing | The agent builds products to answer a buyer's brief. |
| Both | The agent does both. |

When Apostra refreshes a connected sales agent's capabilities, the agent's own
declaration keeps the mode current. An organization administrator can confirm or
override the mode with `save_agent`, recording a reason.

## Test and certify your agent

A sales agent reaches buyers, testing and certification through a storefront.
The agent stays in your Agents account, and a storefront uses it as an
inventory source. If the agent is not meant for the marketplace, use a private
storefront: one only your organization uses. A new storefront is not shown to
other organizations until Apostra lists it, and nothing below asks Apostra to
list it. Apostra's certification buyer buys through each active source that uses
your agent, so an agent with no source cannot be certified.

Follow these steps in order. Steps 1 to 4 take an agent from registered to
certified. Step 5 is optional, and step 6 is a quick check you can run at any
point.

1. **Register the agent.** In your Agents account, create a sales agent as
   described in [Start building](https://docs.apostra.com/v3/connect-an-agent.md#start-building). See [Sales modes](https://docs.apostra.com/v3/connect-an-agent.md#sales-modes)
   for the choice it asks you to make.
2. **Create a private storefront.** In your organization account, call
   `save_account` with `accountType: "seller"`, a `name` that says it is for
   testing, an `operatingMode`, a `reason` and an `idempotencyKey`. An
   administrator of the organization approves the request on the website. The
   storefront must be in the same organization as the Agents account, and
   your organization's plan needs room for one more account. If it has none, the
   request is refused and says so. See
   [Manage organization accounts](https://docs.apostra.com/v3/account-access.md#manage-organization-accounts).
   The new storefront then has a setup checklist to finish before it can take a
   buy. See [Setup checklist and go-live](https://docs.apostra.com/v3/seller-readiness.md).
3. **Add the agent as a source.** Name the storefront account with
   `accountId` on every call from here. `search({ "kind": "agent", "accountId": 624 })` lists your organization's
   agents as `own` rows. Call `save_inventory_source` with only that agent's
   `agentId`. It opens the connection task, where you enter the agent's endpoint
   and credentials for this source. Credentials never pass through chat. You
   need to be signed in directly as an administrator of the storefront account.
   Your own agent needs no certification to connect and no approval from
   another account. See [Connect to a partner agent](https://docs.apostra.com/v3/seller-partner-connection-form.md#the-agents-a-seller-account-can-add),
   which also covers agents that another organization owns. Connecting your
   own agent to your own storefront does not by itself change your
   organization's plan. Your organization counts as offering agents to other
   organizations only once its Partner standing is active.
4. **Allow certification buys.** Turn on **Allow certification buys**, or send
   `certificationRequested: true` with `save_agent`. See
   [Allow certification buys](https://docs.apostra.com/v3/connect-an-agent.md#allow-certification-buys).
   Apostra then starts certification on its own, through its certification
   buyer, on each active source that uses the agent. See
   [When Apostra starts a run](https://docs.apostra.com/v3/certification.md#when-apostra-starts-a-run) and
   [What is certification?](https://docs.apostra.com/v3/certification.md).
5. **Optional: test as a buyer.** To see your agent the way a buyer does, create
   a buyer account in the same organization with `save_account` and
   `accountType: "buyer"`. Create a sandbox advertiser in it, which spends
   nothing. Your organization's storefronts are available to its own advertisers
   whether they are listed or not, but the storefront still has to be ready to
   take a buy. Name your storefront with `sellerAccountIds` when the buyer calls
   `request_proposals`. See
   [Sandbox advertisers and live spend](https://docs.apostra.com/v3/account-access.md#sandbox-advertisers-and-live-spend)
   and [Storefronts](https://docs.apostra.com/v2/buyer/storefronts/overview.md). This test is not a
   certification run, and it does not replace step 4.
6. **Check that the endpoint is alive.** On the agent's **Overview** page, open
   **Tests** in the checklist and choose the endpoint check. It calls the agent's endpoint with
   `get_adcp_capabilities` and `get_products` and a fixed discovery brief, and it
   creates no buy and spends nothing. It is offered while the agent has no
   source, and Apostra limits it to 10 runs an hour for each agent. Once the agent
   has a source, use **Test product discovery** in that source's diagnostics
   instead. A pass shows that the endpoint answers. It is not a certification
   result.

While an agent has no active source, the agent read says so with the finding
`certification.no_source`, and its action is step 2 and step 3 above. In a
Agents account the agent read lists the endpoint check (`endpoint-brief`)
first, and shows the brief and transaction tests (`brief-only`, `transaction`)
as unavailable, with the reason "Run this from a buyer account that can buy
through a storefront this agent is in." Those tests buy through a storefront.

> [!NOTE]
>
> An agent that another organization owns is a partner's agent, and a different
> route connects it: the partner publishes how publishers connect, and the agent
> must be certified first. An Agents account in a different organization from
> the storefront cannot use steps 2 and 3. Register the agent in an Agents
> account in the storefront's organization, or ask Apostra support.

## Allow certification buys

**Allow certification buys** is the control that decides whether Apostra sends
certification buys to a Sales agent. On means Apostra sends them. Off means it
sends no new ones; a certification buy already running finishes. Set it on the agent's page, or with one field,
`certificationRequested`, on `save_agent`. Both save the same setting: you save
the value you want, and saving the value the agent already has changes nothing.

With it off, Apostra sends no certification buys, so only your real traffic can
show your agent working. See
[The certification deadline](https://docs.apostra.com/v3/certification.md#the-certification-deadline)
for when buys start to depend on a pass.

On the agent's Overview page, under **Certification buys**, **Allow certification
buys** is a switch you can turn on or off. The page shows the switch only to
someone who can save it, and shows Apostra's own message if a save is refused.
Anyone else sees whether it is on. The Overview page that an MCP host opens (see
"Open the Overview page" below) shows the same switch. You can also ask your
assistant, or call `save_agent`; to turn it off, send
`certificationRequested: false`.

```json theme={null}
{
  "agentId": "AGENT_ID",
  "certificationRequested": true
}
```

| Value | Meaning |
| - | - |
| `true` | Certification buys are allowed. Apostra starts certification runs for the agent. |
| `false` | Apostra sends no new certification buys. Buys that are already running continue. |

`search` and `get` for `kind: "agent"` return `certificationRequested` for every
agent in the account, `false` until you set it.

* **Who can set it.** Only a directly authenticated administrator of the
  Agents account that owns the agent. Service tokens, delegated sessions and
  impersonation cannot, and another account's agent answers as not found.
* **Which agents.** Sales agents. Certification runs on live traffic for Sales
  agents only, so `true` on a Creative agent is refused. Saving `false` is
  always accepted.
* **What it does.** Apostra starts certification runs on its own for each
  active Source that uses the agent, with no one at Apostra acting. If no run
  starts within a day, ask Apostra support. See
  [When Apostra starts a run](https://docs.apostra.com/v3/certification.md#when-apostra-starts-a-run).
* **With a rename.** `displayName` and `certificationRequested` can be sent in
  one call. Each is saved on its own, so if a call fails partway, repeat it with
  the same values.

## See whether Apostra exempted an agent from certification

Apostra staff can exempt a Sales agent from certification until a date. The
exemption belongs to the agent, not to any one inventory source, and until that
date it counts wherever a certification pass counts: an inventory source can go
live on the agent, including a publisher in another organization connecting to
it for the first time, as if the agent had passed, and the agent takes new buys
for every use case. Its other checks still apply. When the exemption ends, the
agent takes new buys only for the use cases it has passed. See
[What a pass unlocks](https://docs.apostra.com/v3/certification.md#what-a-pass-unlocks) and
[The certification deadline](https://docs.apostra.com/v3/certification.md#the-certification-deadline). Only Apostra
staff set, extend or clear an exemption. You cannot set it, and `save_agent`
does not accept it.

`get` for `kind: "agent"` returns `certificationExemption` beside
`certificationRequested`:

| Value | Meaning |
| - | - |
| `{ "until": "2027-01-31T00:00:00.000Z" }` | Apostra exempted the agent from certification until that date and time (UTC). |
| `null` | The agent has no exemption, or its exemption has ended. |

The field is read-only. Apostra does not show the reason for an exemption or who
set it. To ask for one, contact Apostra support.

## Add a sign-up link to your connection setup

A sales agent you run for other publishers has a published connection setup: the
non-secret definition a publisher follows to connect. The setup can carry an
optional `signupUrl`, a public `https` page where a publisher who has no
credentials from you signs up with you.

* **What it is for.** A publisher either already has credentials from you or
  follows `signupUrl` to get them. You do not approve each publisher, and
  credentials are never sent through the assistant: the publisher enters them in
  the secure credential form.
* **What is accepted.** A public `https` URL with no credentials in it, no query
  string or fragment, and no private or loopback host. Anything else is refused
  when you save the setup.
* **Where it shows.** Your own read of the setup and the connection form a
  publisher sees when it connects to your agent.
* **Leave it out** if you hand out credentials another way.

## See where each agent stands

Call `get_status` in an Agents account to see every agent's **states** and
its **headline finding**. A state is a fact Apostra holds about the agent. The
states are independent: an agent can be certified without an owner test run, and
in one storefront as private and another as listed. They are not steps on a
ladder, and no state implies another.

| State | What it says |
| - | - |
| `states.endpointRegistered` | An endpoint is registered for the agent's production version. `null` for a buyer agent, which has no endpoint. `implementationHealth` on the agent read says whether Apostra has observed the implementation, and the two are read together. |
| `states.storefronts` | `{ total, listed, private }`: the storefronts with an active source that uses the agent, how many of them Apostra lists, and how many it does not. Sales agents only. An agent reaches buyers only through a storefront, so `total: 0` means it cannot be certified yet. |
| `states.certified` | Live certification passed on at least one path and failed on none, and the agent lacks no capability that is required from a date that has arrived. From 1 December 2026 that includes canonical creative formats, and from 1 February 2027 Reliable Reporting, the compact lifecycle and webhook signing: an agent without one is no longer certified on its date, and its headline finding names what it lacks. See [Getting ready for AdCP 4.0](https://docs.apostra.com/v3/adcp-4-readiness.md). `null` for creative and buyer agents, which have no certification today. |
| `states.listedForOtherOrganizations` | Another organization's Seller Account finds the agent when it searches partner sales agents: the agent has a published setup, and your account has active Partner standing. Sales agents only. |
| `states.latestTest` | `passed`, `failed`, or `null` when no test has run: creative conformance for a creative agent, the no-spend test or a transaction test for a sales agent. Live certification results are separate and do not count here. `null` for a buyer agent, because Apostra does not record a test run for buyer agents yet. |
| `states.credential` | `{ issued, authenticated }` for a buyer agent: a credential is bound to it, and that credential has made an authenticated call to Apostra. `null` for other kinds. |

A state that does not apply to an agent's kind is `null`. Apostra never reports
a state it has no record of: an agent with no test run has `latestTest: null`,
not a made-up value.

**The headline finding says what to do next.** Each agent carries
`findingsHeadline`, the one finding to act on first, and `get` for the agent
returns every finding with its fix. `get_status` offers it as `agent_next_step`
for the agent whose headline is most urgent: a blocking finding first, then one
Apostra has not been able to check yet, then the attention finding with the
nearest date. See [Findings: what needs your attention](https://docs.apostra.com/v3/connect-an-agent.md#findings-what-needs-your-attention) for what blocking,
attention and advisory mean.

> [!WARNING]
>
> **`stage`, `nextStage`, `finalStage` and `stuckOn` are deprecated.** They still
> come back with the values they had, and Apostra removes them no earlier than 3
> December 2026. Read `states` for what is true of an agent and the headline
> finding for what to do next. While an agent has no headline finding, `stuckOn`
> still names its next step, so no step is lost before the removal. While one
> does, the text of `get`, `search` and `get_status`, and the Overview page, show
> only the headline: they leave out `stuckOn`, the agent's `nextAction` and
> `certificationNextStep`. The fields themselves keep coming back in the
> structured result until they are removed.

The status also lists build calls for each kind of agent and links to the developer
resources: the Developer quickstart, these guides,
the AdCP specification, the Apostra GitHub repository and the `apostra-developer`
plugin for Claude Code and Codex.

An agent connected from a URL also carries `endpointControl`, `unverified` or
`verified`. While such an agent is not yet verified, the
`endpoint_control.unverified` finding, and `stuckOn` once the agent has passed
its first test until `stuckOn` is removed, name the file and entry to publish, as
[Prove your agent is yours](https://docs.apostra.com/v3/connect-an-agent.md#prove-your-agent-is-yours) explains.

The same `states` come back whenever you read an agent in an Agents account:
`get` with `kind: agent` and each result of `search` with `kind: agent` carry
them, with the same values `get_status` reports, beside the deprecated `stage`,
`nextStage`, `finalStage` and `stuckOn`. The text version of each read says the
states in a sentence. My agents and the Agent page show each agent's certification
stage and next step; the Agent page still shows the deprecated stage and what is
stuck until those fields are removed, and the web app's Agent page adds a button
for the next step. In any other kind of account an
agent read carries no states.

### Buyer agents

Every buyer agent in an Agents account has an agent record of the `buying`
kind, the name AdCP gives a buyer agent in `brand.json`. `save_buyer_agent`
creates the principal and the record together (`save_agent` registers sales and
creative agents only), and `get_status` lists the buyer agent beside your sales
and creative agents.

The record is a handle for tracking the agent. The principal stays the
credential, and what the agent may do stays as advertiser grants on your Buyer
account. Creating the record grants nothing and changes no credential.

A buyer agent's state is its credential: `states.credential` says whether a
credential is bound to it (`issued`) and whether that credential has made an
authenticated call to Apostra (`authenticated`). Until then the
`credential.issued` and `credential.authenticated` findings, and `stuckOn` until
it is removed, ask for
the credential (`save_buyer_agent` with `credentialHandoff: true`) or for the
first call. Apostra does not record a test run for buyer agents yet, so
`latestTest` stays `null`. Certification for buyer agents is not available yet,
so `certified` is `null` too; [How certification works](https://docs.apostra.com/v3/certification.md)
explains what it will take. Retiring a buyer agent
removes its record from the list; renaming it renames the record.

An organization with a buyer agent that was registered before the record
existed gets the record from Apostra when the organization has exactly one
Agents account. With several, save the agent from the account that should
hold it (rename it, or request its credential handoff) and the record is created
there.

## Findings: what needs your attention

Read an agent with `get` (`kind: "agent"`) to see its `findings`. A finding is
one thing Apostra checked about the agent, in the order of the setup checklist:
declarations, behaviour, tests, certification, then the AdCP 4.0 capabilities.
Each has an `outcome` of `passed`, `failing`, or `null` when there is no
decisive result: Apostra has not checked yet, or the check ran and was
inconclusive. The `summary` says which. An inconclusive certification use case
says when it ran, carries the reason the run recorded in `whatWeSaw`, and says
what you can do next in `howToFix`. `search` with `kind: "agent"` returns each agent's headline finding
(`findingsHeadline`) and `findingCount`, the number of findings that have not
passed. Your organization and Apostra staff, including support acting for your
organization, can read findings. A partner that only connects to your agent
cannot.

Every finding also names an `owner`, the role that has to act on it:

| `owner` | Who has to act |
| - | - |
| `agent_developer` | Whoever builds and runs the agent: its code, its declared capabilities, its settings, or the way it answers Apostra. The page shows it as "You" to this person. |
| `seller` | The seller whose storefront uses the agent, for a setting or decision only the seller can make. |
| `apostra` | Apostra, when the change is on Apostra's side. |
| `null` | Nobody has to act yet, for example a certification run still collecting live traffic, or a finding that passed. |

The two are often one company, but not always: a seller can use a partner's
agent. `owner` is a different question from `stops.by`, which says who enforces
a block.

A failing finding has a `severity` that says what is at stake:

| Severity | What it means for you |
| - | - |
| `blocking` | Something stops today. `stops` says what (`buying` or `certification`) and who stops it. Apostra's own code stops it, or a buyer's tools fail a buying operation. |
| `attention` | It will block on a date Apostra has published (`dueAt`), or it degrades something now without stopping it. |
| `advisory` | Nothing stops. You would be better off fixing it. |

A finding's `summary` says "cannot" only when its severity is `blocking`, and
only about what `stops` names.

One finding is the **headline**, marked `headline: true`, and its action is the
agent's `nextAction`. It is the first failing blocking finding. If none blocks,
it is the first finding with no decisive result yet: not checked, or
inconclusive. If every check has a decisive result, it
is the attention finding with the nearest `dueAt`, then any attention finding
with no date. An advisory finding never becomes the headline.

Every failing finding carries `whatWeSaw`, `howToFix` and `docsUrl`. `howToFix`
names the change to make, and where the change is in your agent rather than in
Apostra, the finding's `action` is `NONE`. The code below says where each
finding is explained, and the next section says who has to act on each.

| Code | What it checks | Severity |
| - | - | - |
| `declaration.adcp_v3` | You declare AdCP major version 3. | Attention. Buyers' tools read an agent without it as AdCP 2. |
| `declaration.supported_billing` | You list agent or operator billing. | Attention. |
| `declaration.connected_credential` | You accept the connected credential for every buyer. | Blocking. Certification skips an agent that requires operator authentication. |
| `declaration.account_requests` | You take buyer account requests. | Blocking. Certification skips an agent without `sync_accounts` and `list_accounts`. |
| `declaration.buying_modes` | You declare `media_buy.buying_modes` with `brief`, `wholesale` or both. See [Declare your buying modes](https://docs.apostra.com/v3/agent-requirements.md#declare-your-buying-modes). | Advisory. Reported only for now: it stops neither certification nor buying, and it never becomes the headline. |
| `declaration.creative_kind` | Your products declare a creative format Apostra can supply. | Attention. |
| `declaration.product_channels` | Your products declare AdCP channels, counted as storefront readiness counts them. | Advisory. It never becomes the headline. |
| `behaviour.responsiveness`, `behaviour.async_completion`, `behaviour.call_success_rate`, `behaviour.honours_request`, `behaviour.account_resolution`, `behaviour.lifecycle_agreement`, `behaviour.changes_announced`, `behaviour.ended_buys_not_active`, `behaviour.reachability` | The behaviour baseline's checks that can stop new buys. | Attention. A blocker stops the agent's certification pass counting; a flag stops nothing. |
| `behaviour.payment_terms`, `behaviour.idempotent_account_sync`, `behaviour.declarations_match_behaviour`, `behaviour.creative_changes_declared`, `behaviour.delivery_report_format`, `behaviour.machine_readable_errors` | The behaviour baseline's reported checks. `behaviour.creative_changes_declared` reads a flag when your agent does not declare which live creative changes it takes. See [Creative changes declared finding](https://docs.apostra.com/v3/certification.md#creative-changes-declared-finding). `behaviour.delivery_report_format` reads a flag when a source sends the AdCP 3.0 bare delivery report, or sends a delivery report that fails the schema. See [Delivery report format finding](https://docs.apostra.com/v3/certification.md#delivery-report-format-finding). | Attention. These checks stop nothing. |
| `claim.review` | Your organization has claimed the agent. Only an organization admin reads it failing, for an agent Scope3 mapped to the organization. | Blocking, for certification. See [Claim an agent Scope3 mapped to your organization](https://docs.apostra.com/v3/connect-an-agent.md#claim-an-agent-scope3-mapped-to-your-organization). |
| `certification.no_source` | An active inventory source uses the agent. | Blocking, for certification. Certification buys through the active sources that use the agent; with none it cannot start. See [Test and certify your agent](https://docs.apostra.com/v3/connect-an-agent.md#test-and-certify-your-agent). |
| `certification.no_passing_use_case` | At least one certification use case has passed. | Blocking. A publisher cannot complete the Successful transaction go-live step on your agent without it, unless Apostra has exempted the agent from certification. |
| `certification.use_case` | One use case's newest result, whatever its outcome. `subject` is the use case. An earlier result that differs is history on its run, not the finding. An inconclusive result that nobody on your side can act on does not replace a pass. | Attention when it failed. An inconclusive result has no outcome and no severity. |
| `certification.format_not_tested` | Whether certification planned a buy for every format option your products offer. A format option the latest run left out is listed with its product, channel and reason. See [Formats certification does not test](https://docs.apostra.com/v3/certification.md#formats-certification-does-not-test). | Attention when the latest run left out any format option. Nothing stops: your agent stays certified once any use case passes, and the formats left out stay bookable. |
| `certification.live_creative_changes` | Whether your agent handles the live creative changes certification makes on its test buy as it declared them: it takes a change it declared, and refuses a change it left out of its declared actions with an error code. See [Live creative changes finding](https://docs.apostra.com/v3/certification.md#live-creative-changes-finding). | Attention when the latest run saw your agent refuse a change it declared as self-serve, or accept, or answer without an error code, a change it left out. Nothing stops: the check never makes a use case fail and never withholds a certification pass. |
| `certification.storefront_accounts` | Whether your agent accepts the account request Apostra sends when a publisher whose own storefront uses your agent approves a buyer. It is judged on each inventory source of a storefront that is not a pure pass-through, with that publisher's credential. See [Use cases](https://docs.apostra.com/v3/certification.md#use-cases). | Attention when the latest check failed on any such source, because buyers billed through Apostra get no account there. Nothing stops yet. |
| `certification.create_without_creatives` | Whether your agent accepts a media buy created with valid packages and no creatives and holds it in `pending_creatives`, as AdCP 3.3 says it must. Apostra sends one such create when your agent is first certified, when what it declares changes, after a probe that did not pass, and weekly after a pass, and cancels the buy. When your agent refused it, or reported another status, the finding shows your agent's own error code and message, or the status it reported. See [Create without creatives finding](https://docs.apostra.com/v3/certification.md#create-without-creatives-finding). | Attention when the latest probe saw your agent refuse the create, or report the buy in any status other than `pending_creatives`. Nothing stops: the check never makes a use case fail and never withholds a certification pass. A create that timed out, never reached your agent, was held for a decision or gave no status is not judged. |
| `certification.probe_buy_not_cancelled` | A test buy certification created with no creatives is still booked on your agent 12 hours after it was sent, because your agent refused the cancel or kept the buy. It names the buy, the cancel attempts and your agent's own words. See [Create without creatives finding](https://docs.apostra.com/v3/certification.md#create-without-creatives-finding). | Attention. Nothing stops: the buy carries no creative and starts a day after it was sent, so it cannot deliver. A cancel Apostra could not send is Apostra's and is not shown here. |
| `certification.awaiting_creative_approval` | Your agent holds the certification creative for review, so certification waits for you to approve it. It names the use cases that wait and when the wait ends. See [Certification-ready sandbox](https://docs.apostra.com/v3/certification.md#certification-ready-sandbox). | Attention while the wait lasts. Nothing stops: a use case still waiting when the wait ends is inconclusive. |
| `reporting.sources` | Your inventory sources report on time. | Attention when any source needs reporting action. Nothing stops. |
| `partner.program` | The agent serves other organizations as a Partner. An organization admin reads it only for a claimed agent that has passed certification. | Advisory when your organization does not yet serve other organizations. It never becomes the headline. |
| `creative_conformance.step` | One step of the creative conformance test. `subject` is the step. | Attention when it failed. |
| `adcp_4.supported_versions`, `adcp_4.reliable_reporting`, `adcp_4.request_signing`, `adcp_4.webhook_signing`, `adcp_4.operator_identity`, `adcp_4.compact_lifecycle`, `adcp_4.canonical_creatives` | The AdCP 4.0 capability checks. | Attention with `dueAt` for a capability that becomes required on a date, advisory for one with no date, blocking once its date has arrived. See [Getting ready for AdCP 4.0](https://docs.apostra.com/v3/adcp-4-readiness.md). |
| `implementation.no_endpoint` | A production endpoint is registered for the agent. Raised for sales and creative agents. | Attention. Nothing refuses an agent for having none, but Apostra has nothing to call. See [Connect an agent from its URL](https://docs.apostra.com/v3/connect-an-agent.md#connect-an-agent-from-its-url). |
| `endpoint_control.unverified` | An agent Apostra connected from a URL is verified as yours. An agent that was not connected from a URL has no such finding. | Blocking, for certification. Certification, Partner standing, listing and use by another organization are refused until the agent is verified. See [Prove your agent is yours](https://docs.apostra.com/v3/connect-an-agent.md#prove-your-agent-is-yours). |
| `day_one_test.sales_validation` | A sales agent's latest owner test. Raised once an endpoint is registered. | Attention when the latest run failed. Advisory when no test has run: certification does not need one, so it never becomes the headline. See [Test and certify your agent](https://docs.apostra.com/v3/connect-an-agent.md#test-and-certify-your-agent). |
| `creative_conformance.not_run` | A creative agent has a conformance result. Raised once an endpoint is registered. | Not checked yet until the test has run, so it leads: the test is the only check a creative agent has. See [Creative conformance findings](https://docs.apostra.com/v3/connect-an-agent.md#creative-conformance-findings). |
| `credential.issued` | A buyer agent has a credential bound to it. | Attention. A buyer agent makes no authenticated call without one. See [Buyer agents](https://docs.apostra.com/v3/connect-an-agent.md#buyer-agents). |
| `credential.authenticated` | A buyer agent's credential has made an authenticated call to Apostra. Raised once a credential is bound. | Not checked yet until the first call, so it leads. See [Buyer agents](https://docs.apostra.com/v3/connect-an-agent.md#buyer-agents). |
| `implementation.change_detected` | Apostra tracks changes to your agent's implementation. It reads passed and, when your agent has changed, says when: "Your agent changed on 22 October; Apostra re-checked its capabilities." You do nothing: Apostra re-reads your agent's capabilities every hour and keeps the page current. | Never failing. |

The behaviour and declaration codes are explained in
[Agent requirements: declarations and behaviour](https://docs.apostra.com/v3/agent-requirements.md),
certification in [How certification works](https://docs.apostra.com/v3/certification.md#what-a-pass-unlocks).

### Who has to act on each code

| Code | `owner` |
| - | - |
| `declaration.*`, `behaviour.*`, `adcp_4.*` | `agent_developer`. |
| `claim.review` | `agent_developer`: an organization admin claims the agent. |
| `certification.no_source` | `agent_developer`: attach the agent to a storefront. |
| `certification.no_passing_use_case` | `agent_developer` while the agent is attached to no storefront, certification buys are off, a use case failed, or the agent holds our creatives for review. `null` while certification runs on live traffic. |
| `certification.use_case` | `agent_developer` when it failed or while your agent holds our certification creatives for review ("Your agent is holding our certification creatives for review"). For an inconclusive result from a skipped family, the owner of the skip reason in [Skip reasons](https://docs.apostra.com/v3/certification.md#skip-reasons). `null` while evidence is still arriving. |
| `certification.awaiting_creative_approval` | `agent_developer`. |
| `certification.format_not_tested` | `agent_developer` for a product with no channel certification can buy on. `apostra` for a format Apostra does not test yet. `null` when a later run covers it. |
| `certification.live_creative_changes`, `certification.storefront_accounts` | `agent_developer`. |
| `reporting.sources` | `seller`: the seller behind the source delivers the report. |
| `partner.program`, `implementation.no_endpoint`, `endpoint_control.unverified`, `day_one_test.sales_validation`, `creative_conformance.*`, `credential.*` | `agent_developer`. |
| Any finding that passed, and `implementation.change_detected` | `null`. |

A failed certification use case's `howToFix` names the change for the check that
failed, as [What each check judges](https://docs.apostra.com/v3/certification.md#what-each-check-judges)
describes it.

### Open the Overview page

In an MCP host such as Claude or ChatGPT, ask to open your agent, or call
`open_agent_page` with the agent's `agentId`. It opens the agent's Overview
page, which shows:

* **The headline finding first.** Its severity names it: Blocking, Needs
  attention, or Not ready yet when a check has not run. The page says what the
  finding stops, the date it becomes blocking when it has one, how to fix it,
  and links to the explanation. A page never reads as passed while any check has
  not run.
* **One button for each fix.** A finding that has not passed carries one button
  for its fix. Where the fix is a change to your agent's own code, the button
  opens the finding's explanation. Where you can do it on Apostra, the button
  does it: **Review and claim** opens the claim review for an agent Scope3
  mapped to your organization, **Check the proof of control** and **Run the test
  again** have Apostra read the agent at its URL again (the second also re-runs
  the endpoint check), **Start the conformance test** and **Run the conformance
  test again** run the creative conformance test, **Set up a credential** asks
  for a buyer agent's credential and then shows a link to finish setting it up,
  and **Open the inventory sources** opens that
  page. A button that changes something shows only to the person who directly
  administers the account that owns the agent; anyone else sees the
  explanation links and the buttons that only open a page. After a change, the
  page reads the agent again and shows what Apostra now sees.
* **States.** One line for each fact Apostra read about the agent: whether an
  endpoint is registered, how many storefronts use the agent and how many of
  them are listed, whether it is certified, whether other organizations can find
  it, the latest test, and for a buyer agent its credential. A fact that does not
  apply to the kind of agent has no line.
* **The checklist.** Every finding in the order above. Failing findings and
  findings Apostra has not checked yet are listed first, each with what we saw,
  how to fix it, when it was last checked and a link to the explanation. Findings
  that passed are collapsed under their own heading. Five findings show at a
  time.
* **Evidence.** Under the checklist, one item for each thing Apostra checks. Each
  opens to its full evidence: **Live certification** (the latest result for each
  use case, with its channel, when it was judged and, when it did not pass, the
  reason Apostra recorded); **Tests** (for a sales agent, the test plan with each
  test mode, whether it is available and why not, and the recent test runs with
  the outcome, the failed stage, who is accountable and the next step);
  **AdCP 4.0 readiness** and **Capability declarations** (the same checks as
  [Getting ready for AdCP 4.0](https://docs.apostra.com/v3/adcp-4-readiness.md) and the declarations the
  agent makes, with what Apostra saw and how to fix each); and, for a creative
  agent, **Creative conformance**.
* **Certification buys.** Whether the owner has allowed certification buys. For
  someone who can change the setting, this is a switch: turn it on or off and the
  page saves it with `save_agent`, then reads itself again, so what it shows is
  what Apostra saved. Anyone else sees only whether it is on. When Apostra has
  exempted the agent from certification until a date, one line gives that date.
  See
  [See whether Apostra exempted an agent from certification](https://docs.apostra.com/v3/connect-an-agent.md#see-whether-apostra-exempted-an-agent-from-certification).
* **Actions on two findings.** For an agent Scope3 mapped to your organization
  and you have not claimed, an organization admin sees **Review and claim**,
  which opens the claim review. For a claimed agent that has passed
  certification, an organization admin sees **Open Partner operations**, which
  opens the Partner page. No other finding has a button.
* **The agent and its endpoint.** Its name, kind, states, the organization it is Built by, the AdCP
  versions it declares, when Apostra last read its capabilities, its production
  revision and when it was deployed, and whether the implementation Apostra
  observes still matches.

The page shows what `get` returns for the agent, to the same people who
can read it, and opening it changes nothing. It leaves out internal fields, such
as source identifiers and the links to a run's diagnostics. Its two buttons open
other pages; its one write is the certification switch. It is available in
Agents accounts. The text Apostra writes for a finding (its summary, what we saw and
how to fix it) is in English whatever language the host uses.

### Open the Inventory sources page

In an MCP host such as Claude or ChatGPT, ask to open your agent's inventory sources, or call
`open_agent_sources_page` with the agent's `agentId`. It opens a page that shows how many inventory
sources the agent powers (connections, for an agent that is not a sales agent), and for each one its
name, the storefront it belongs to, its lane (wholesale or composing) and its latest health: healthy,
needs attention or unhealthy, with when Apostra last observed it, or that there is no recent
evidence. Each source also shows its own reporting state: no report due yet, on time, late and
recovering, needs action, or complete, or that none is available. The page shows each state as
Apostra reads it and never adds them up; [Source reporting health](https://docs.apostra.com/v3/agent-requirements.md#source-reporting-health) says what each state means. When the agent also serves other organizations, the page says how many more sources stay
private to their organizations; it never names them.

The page shows exactly what `get` returns for the agent, to the same people who can read it. It
changes nothing. Credentials, reachability, mappings and failures are not on this page: each source's
own [diagnostics](https://docs.apostra.com/v2/storefront/inventory-sources/diagnostics.md) carries them, and they do not change
the agent's certification. The tool is available in Agents accounts.

### Claim an agent Scope3 mapped to your organization

Scope3 can map an existing agent to your organization before you register it
yourself. That agent shows as unclaimed: it has an id, connections and history,
but your organization has not taken ownership. Until an organization admin
claims it, the agent takes no owner changes, cannot be certified and has no
Partner authority. A legacy connection that was already serving may keep
serving, and that is not a claim.

The `claim.review` finding says so, to organization admins only. Its action,
**Review and claim**, opens the claim review: you check what Scope3 mapped and
claim the agent. Claiming keeps the agent's id, revisions,
connections and history. A member who is not an organization admin, a service
credential and Scope3 support staff reading for you do not see the finding and
cannot claim the agent.

### Creative conformance findings

A creative agent's conformance test runs a fixed set of steps against its
endpoint. Each step is a `creative_conformance.step` finding with the step as
its `subject`: `passed`, `failing` with the agent's own error in `whatWeSaw`,
or `null` when the step was skipped. A failed step is attention, because
nothing stops a creative agent from working while a step fails.

## After you create an agent

Test it in the [sandbox](https://docs.apostra.com/v2/features/sandbox.md). A sales agent then goes on to
certification. A creative agent stops at tested, and a buyer agent has no
certification path yet. [What is certification?](https://docs.apostra.com/v3/certification.md) explains
what makes a sales agent ready, what each check judges and what every result
means. The [Agents](https://docs.apostra.com/v2/concepts/agents.md) page describes the certification state
each agent shows.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.