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

# Reading an inventory source: adapter, powering Agent and test runs

> How a seller account reads whether an inventory source is an Apostra-hosted adapter, which Agent powers it, and its latest source tests.

Three facts about an inventory source are readable from V3 without a second tool: whether the source is
Apostra's hosted adapter, which Agent powers it, and how its latest tests went. The first is on every
source. The other two are opt-in, so a `get` that names neither returns exactly what it returned before.

## Is the source an adapter

Every source carries `isAdapterSource`, a boolean. It is on each row of
`search({ "kind": "inventory_source" })` and on the `object` of
`get({ "kind": "inventory_source", "id": "SOURCE_ID" })`.

`isAdapterSource` is `true` when the seller account is routed through an official Apostra-hosted adapter
and this source is that adapter's source. It is `false` for every other source, including an external
sales agent you connected yourself. A caller that wants to tell an Apostra-hosted source from an external
one reads this field instead of working it out from the source's name or endpoint.

Whether Apostra operates a source can also depend on how it executes. A source with
`executionType: "MANAGED_SALES_AGENT"` is operated through an Apostra-managed ad-server connection, and an
adapter source is operated through a hosted adapter, so a caller that means "Apostra runs this source"
treats either as true. `isAdapterSource` answers only the adapter half.

The field is `isAdapterSource` and not a single `managed` flag for two reasons. The server already computes
this exact boolean, so the field reports an existing answer rather than a new rule. And `managed` already
means something else on a source: `connection.state: "managed"` says the source is provisioned through its
own flow and has no credentials of yours to enter.

## Which Agent powers the source

Call `get` with `kind: "inventory_source"`, the source's `id` and `include: ["poweredByAgent"]`. The result
carries `poweredByAgent`, which is one of three things:

```json theme={null}
{ "poweredByAgent": null }
```

```json theme={null}
{ "poweredByAgent": { "state": "ACTIVE", "agentId": "AGENT_ID" } }
```

```json theme={null}
{ "poweredByAgent": { "state": "REVOKED" } }
```

| Value | Meaning |
| - | - |
| `null` | No Agent is mapped to this source. An Agent in another organization that has not been authorized for this seller also reads as `null`. |
| `{ "state": "ACTIVE", "agentId" }` | An Agent powers the source and its mapping is in force. `agentId` is the Agent's id. |
| `{ "state": "REVOKED" }` | An Agent was mapped to the source and no longer is: the mapping or its authorization was revoked, or the Agent was archived. |

There is no other state. "Nothing is mapped" is `null`, not a state of its own.

The field carries the Agent's id and nothing else. To read the Agent itself, including its certification and
diagnostics, call `get({ "kind": "agent", "id": "AGENT_ID" })`.

## The latest source tests

Call `get` with `kind: "inventory_source"`, the source's `id` and `include: ["testRuns"]`. The result carries
`testRuns`, the five most recent tests recorded for this source, newest first. A source that has never been
tested returns an empty list.

```json theme={null}
{
  "testRuns": [
    {
      "id": "501",
      "toolName": "run_inventory_source_discovery_test",
      "status": "passed",
      "productCount": 12,
      "steps": [
        {
          "key": "get_products-0",
          "label": "Discover products",
          "status": "completed",
          "operation": "get_products",
          "message": null
        }
      ]
    }
  ]
}
```

| Field | Meaning |
| - | - |
| `id` | The run's id. |
| `toolName` | Which test ran: `run_inventory_source_discovery_test` for the read-only product discovery check, or `execute_inventory_source_test_campaign` for the no-spend sandbox campaign test. |
| `status` | `planned`, `partial`, `passed` or `failed`. |
| `productCount` | How many products the test discovered, or `null` when the run did not record a count. |
| `steps` | What the test did, in order. Each step has a `key`, a `label`, a `status` (`completed`, `failed` or `not_checked`), the `operation` it called or `null`, and a `message`, or `null` when the step has nothing to add. |

`get` reads recorded tests. It does not run one, and it does not probe the source. A test belongs to a
source when it was recorded for that source's id or key, so a test recorded without either does not appear.

## Where to ask for them

Both includes belong to `kind: "inventory_source"`. They are refused on any other kind, including
`kind: "seller"`, and a Buyer Account cannot request them.

## When a read fails

There is no "unknown" value. If Apostra cannot work out `poweredByAgent` or `testRuns`, for example because
a lookup timed out, the call fails with `SERVICE_UNAVAILABLE` and returns neither include, so you never act
on a guess. Retry the same call.

## Related

* [Source diagnostics Page](/v3/seller-source-diagnostics-page) opens the diagnostics view for a source.
* [Sellers on the V3 tool surface](/v2/setup/v3/tool-reference) lists every `get` kind and include a seller account reads.


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