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

# Your account's agent and hosted orchestrators

> How a hosted buyer agent runs (on demand or always on), which Buyer account it belongs to, how get_status points to a Buyer account's own agent, and how to create a hosted orchestrator that works across your accounts with save_buyer_agent.

A hosted buyer agent is a buyer agent Apostra runs for you. There are two
kinds:

* **An account's own agent.** Each Buyer account has one agent of its own. It
  belongs to that account, and it is the account's assistant in Apostra.
* **A hosted orchestrator.** An agent your organization creates that belongs to
  no account. It works across your organization's accounts through the
  advertiser access you give it.

An external buyer agent, one you run yourself and connect to Apostra, is
neither. Both kinds are `buyer_agent` objects, read with `search` and `get` and
changed with `save_buyer_agent`, the same as an external agent.

> [!NOTE]
>
> Hosted buyer agents are in beta and are switched on per organization, together
> with [chatting with your buyer agent](https://docs.apostra.com/v3/chat-with-your-buyer-agent.md). Until
> they are on for your account, `buyer_agent` reads leave out `accountId` and
> `hosting`, `get_status` leaves out `agent`, and `save_buyer_agent` refuses to
> create a hosted agent. Ask your Apostra contact to turn them on.

> [!NOTE]
>
> Apostra does not create an account's own agent for each Buyer account yet. Until
> it does, `get_status` returns `agent: null` and says the account has no agent
> yet.

## Reading how an agent runs and who it belongs to

`get(kind: "buyer_agent")` and `search(kind: "buyer_agent")` return two fields
on each agent:

| Field | Values | Meaning |
| - | - | - |
| `accountId` | A Buyer account id, or `null` | The account this agent belongs to. `null` for a hosted orchestrator or an external agent. |
| `hosting` | `on_demand`, `always_on`, or `null` | How the agent runs, which decides how its time is charged. `null` for an external agent. |

`hosting` is the customer's choice of how the agent's time is paid for.
**On demand**, the default, is charged by the hours the agent spends on work it
was asked to do. **Always on** is a flat daily rate in place of those hours.
Apostra never moves an agent between the two by itself. Choosing always on is
not available yet, so every hosted agent reads `on_demand`, and agent work is
not metered yet.

## Finding a Buyer account's own agent

In a Buyer account, `get_status` returns `agent`, a pointer to the account's
own agent, so you find it in one call without a search:

| Field | Meaning |
| - | - |
| `agent.principalId` | The agent's id. Send it as the `id` of `get(kind: "buyer_agent")` or `save_buyer_agent`. |
| `agent.displayName` | The agent's name. |
| `agent.hosting` | `on_demand` or `always_on`. |
| `agent.lifecycleState` | `active`, `suspended` or `retired`. |

While the account has no agent yet, `agent` is `null`, never an empty object,
and the status text says why. If Apostra cannot read the agent at that moment,
`agent` is left out and the text says so; call `get_status` again, or
`search(kind: "buyer_agent")`.

## Creating a hosted orchestrator

An organization administrator creates one with `save_buyer_agent`, without an
`id`:

```json theme={null}
{
  "kind": "hosted",
  "displayName": "Cross-account planner",
  "idempotencyKey": "6f1c2a52-5d1e-4b77-9a0e-3b8f1f2c9d41"
}
```

* `idempotencyKey` is required. Send a new UUID for each agent. If the call is
  retried with the same key and the same `displayName`, it returns the agent the
  first call created, as it is now, instead of a second agent. The same key with
  a different `displayName` is refused with `CONFLICT`.
* The new agent has `accountId: null` and `hosting: "on_demand"`.
* It has no advertiser access yet. Give it access across your accounts with
  `save_buyer_agent` and `access`, as for any buyer agent.
* Apostra starts the agent's runtime separately. Until its runtime is running,
  the agent cannot take messages; the chat says so.

Only a directly signed-in organization administrator may create one, because it
changes your bill. Creating a hosted agent in an Agents account is not
available: connect a buyer agent you run yourself instead. `idempotencyKey` is
only for hosted creation; an external create that sends one is refused.

## What you cannot change on an account's own agent

An account's own agent exists because its account does:

* **It is retired with its account.** `save_buyer_agent` with
  `lifecycleState: "retired"` is refused with `VALIDATION_ERROR`. Suspend it
  instead (`lifecycleState: "suspended"`): that switches it off without
  removing it, so it stops working until you resume it.
* **Its access is the account's advertisers.** Apostra keeps it to every
  advertiser in the account, with read and write access, so
  `save_buyer_agent` with `access` is refused with `VALIDATION_ERROR`. In any
  conversation it can still do only what the person talking to it may do, and
  scheduled and event runs that nobody is watching only read.
* `kind: "hosted"` without an `id` always creates an orchestrator, never an
  account's own agent.


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