Running Agent Discovery

Add a source, run scans, and triage what they find with the Arthur Platform

Introduction

This guide expands the "How you can run it" section of Overview of Agent Discovery. It walks through running Agent Discovery end to end with the Arthur Platform: adding a source, testing the connection, running scans, and acting on what the scans find. It also summarizes the standalone mode for teams that want an inventory without the full Platform.

The steps are the same for every source type. Source-specific settings (credentials, regions, query syntax) are covered on each integration's own page and are out of scope here.

Prerequisites

Before you add a source, you need three things in place.

  1. An Arthur workspace with Governance access. Agent Discovery lives under Governance > Discovery in the Platform sidebar. Your role must allow you to manage discovery sources and act on findings. See Groups, Roles & Permissions.
  2. The Arthur Engine running in your environment. The Arthur Engine is two services, and discovery needs both. The ML Engine runs the scans: it holds the connectors, signs in to each source, and reads what the source returns. The GenAI Engine holds the task representation of every discovered agent: each agent a scan finds becomes a task there, and that task is the record the Platform reads. Scans do not run in Arthur's cloud. Deploy both before you expect any scan to run. See Self-Host the Arthur Engine.
  3. A read-only credential for each system you want to scan. Discovery only lists or searches. Create a dedicated credential with the minimum permissions the source needs, and keep it ready to paste when you add the source. Arthur stores the credential separately from the source's query and schedule, and never writes it to logs or error messages.

The ML Engine needs outbound HTTPS to each source, to the GenAI Engine, and to the Platform. Nothing needs inbound access.

How discovery runs

The Platform schedules scans and shows the results. Everything that touches your systems, and every record of what was found, lives on the Arthur Engine inside your environment.

flowchart LR
    A["Platform<br/>schedules a scan job<br/>per config, on its schedule"] -->|scan job| B["ML Engine<br/>gets the credential,<br/>reads your source"]
    B -->|records| C["GenAI Engine<br/>holds each agent<br/>as one stable task"]
    C -->|tasks| D["Platform<br/>fetch job uploads,<br/>matches applications"]
    D --> E{Registered?}
    E -->|yes| F["Application updated<br/>same task, new evidence"]
    E -->|no| G["Unregistered agent<br/>lands in Needs triage<br/>you register or mute"]

The Platform never holds the source open and never sees the raw response. The ML Engine fetches the credential at scan time, reads the source, and hands back a list of agents in a fixed shape. The GenAI Engine turns each agent into a task and keeps it. The task is the agent's record in Arthur: it carries the agent's name, where it was found, and the evidence from each scan. The same agent resolves to the same task on every scan, so repeated scans update one record instead of creating a new one, and traces sent later for that agent land on the same task. Anything that does not match a registered application lands in Needs triage on the Discovery page for you to register or mute. One class needs no scan at all: anything that already sends OTEL traces to your Arthur Engine has a task, and a task no one has linked to a registered application shows up as a discovered agent on its own.

Step 1: Add a discovery source

A discovery source is one system Arthur is allowed to read from. Each source has two parts that you set up separately.

Sources are grouped into five classes on the Discovery targets tab: Engine (OTEL), Cloud, SIEM, Endpoint, and Network & Gateway. Each class card shows its status, the sources under it, and how many agents it has found. The Engine class is always Continuous and has nothing to configure. The others read Not configured until you add a source, Reporting once a scan has run, or No sensor when nothing can report for that class yet.

PartWhat it holdsWhy it is separate
Discovery sourceThe connection: which vendor, where it lives, and the credentialA credential is stored once and reused by every scan of that source, and is never written to logs
Source configWhat to look for, how often, and how far back: the query, the schedule, the lookback window, and the engine that runs itOne source can have several configs, each on its own schedule, and the configs carry no credentials

To add a source:

  1. Open Governance > Discovery in the Platform sidebar. On the Discovery targets tab, choose Configure sources, or the + on the class card you want to add to.
  2. Pick the source type and enter its connection details and credential. The fields differ by vendor; the integration page for that vendor lists them.
  3. Choose Test Connection. The Platform sends a short test job to your ML Engine, which signs in to the source with the credential you entered and returns a preview of what it can see. A failed test names the cause (bad credential, missing permission, unreachable host) so you can fix it before saving.
  4. Add at least one config: give it a name, set the query (if the source type takes one), pick the schedule, and set the lookback window.
  5. Save. The source appears under its class card on the Discovery targets tab. The card reads Reporting after the first successful scan.

Setting the lookback window. The lookback window is how far back each scan reads. Nothing is carried over between scans, so set it to at least the scan interval. A 6-hour schedule with a 6-hour lookback covers everything; a 6-hour schedule with a 1-hour lookback misses five hours out of every six. Some source types list the whole system on every scan and ignore the window.

Choosing the engine. If you run more than one Arthur Engine, each config is bound to one of them. Pick the engine that has network access to the source.

Step 2: Run scans

Scans run on the schedule you set in each config. You do not have to trigger anything after saving a source. The first scan starts at the next scheduled time, or sooner if you run one by hand.

Scheduled scans. The Platform runs a background scheduler that creates one scan job per config whenever that config's schedule comes due. One config failing does not affect its siblings, and a scan that fails partway through keeps the agents it already collected.

Manual scans. Use Scan now on the Scans tab, or Run scan on the Discovery targets tab, to run outside the schedule, for example right after adding a source or after a team tells you they deployed something new. A manual scan fans out one job per configured source on every engine in scope and completes when all of them finish. The Engine (OTEL) class is never scanned; it reports continuously.

What happens during a scan. Each scan runs in the order below, with the Platform only ever handling the config and the results, never the credential and never the source itself.

  1. The Platform creates a scan job for the config and queues it for the bound ML Engine. The job carries the query, lookback window, and source settings. It does not carry the credential.
  2. The ML Engine picks up the job, fetches the credential from the Platform, and calls the source with its native API: a list call for a cloud platform, a search for a SIEM, an inventory read for an endpoint manager.
  3. The ML Engine checks each returned record against the discovery output contract. Every agent must have at least an external ID, a name, and a last-seen time. A source whose query returns the wrong columns fails the scan with a message naming the column.
  4. The ML Engine sends the records to the GenAI Engine, which resolves each one to a task. If a task with that identity already exists, it is updated; if not, one is created. The GenAI Engine marks the task with its provenance: which source found it and when. This is the step that decides identity. The same external ID always resolves to the same task, so an agent seen on 20 scans is still one agent in the inventory.
  5. A fetch job on the ML Engine reads those tasks from the GenAI Engine and uploads them to the Platform, where each one is matched against your registered applications. The Platform only ever sees tasks, never the raw scan output. Matches update the registered application; everything else appears as an unregistered agent.
  6. The scan records its outcome: succeeded or failed, how many records it published, and an error code if it failed.

Checking scan status. The Scans tab lists every run, one row per source attempt: when it finished, the source, the trigger (scheduled or manual), how many agents it found, its status, and a link to its logs. Run history in the page header opens the same list. The Discovery targets tab also shows when the last scan ran and how many agents are new since it. When a run fails, the log names the cause. The common ones:

Error codeMeaningWhat to check
authentication_failedThe source rejected the credentialWhether the credential was rotated or revoked
permission_deniedThe credential signs in but cannot list or searchThe role or scope on the credential
not_configuredA field or query is wrongThe outcome message names the field or column
provider_errorThe source returned an error or was unreachableNetwork access from the ML Engine to the source
cancelledThe scan hit its timeout or the engine shut downRaise the timeout if it happens every time
internal_errorAn unexpected engine errorSend the engine log to Arthur support

Step 3: Triage discovered agents

After a scan completes, open Governance > Discovery and the Discovered agents tab. Needs triage lists every agent found that is not yet registered or muted, with its count; Muted lists the ones you have set aside. Narrow the list with the filters above the table: Runs on, Source class, Found by, Evidence, and More filters. A filtered view has its own URL, so you can share a view with the team that owns a group of agents.

Each row shows:

ColumnWhat it tells you
EvidenceHow much the source knows about the agent, as a strength rating such as Limited, and whether it is Stale (the source has stopped reporting it)
AgentThe agent as the source reported it. Open it for the full evidence
Runs onThe source config that found it and the platform behind it, for example a Vertex AI Agent Engine project or a Jamf Pro fleet. Unknown means the agent came from traces that no discovery config matched
Found byWhich Arthur Engine reported it, and how long ago
ActionsRegister, or the bell icon to mute. Select several rows with the checkboxes to act on them together

Open an agent to see the full evidence. For an agent found through traces, that includes the tools it calls and the models it uses. For an agent found on an endpoint, it includes the machine and the installed version. For an agent found in a SIEM, it includes the query and window that matched.

An agent that a source stops reporting is not removed from the list. Its evidence turns Stale, which is itself a signal worth a look.

You can also read the list programmatically with GET /api/v1/workspaces/{workspace_id}/agents/unregistered. See Agent Discovery for request examples.

Step 4: Act on what you find

Every discovered agent ends up in one of two states. Decide which after you have read its evidence, not before. Start triage on the Discovery targets tab walks you through the agents that need a decision one at a time; the Discovered agents tab lets you work the list in any order.

Register brings the agent under Arthur governance. The task the GenAI Engine already holds for it is linked to a registered application in your workspace, so policies, monitoring, and alerts apply to it from that point on. If the owning team later adds tracing, the traces land on the same task; nothing needs merging. Choose Register on the agent's row, or use PUT /api/v1/workspaces/{workspace_id}/agents.

Mute acknowledges the agent without governing it. Use it for an agent you have reviewed and decided does not need Arthur, such as a sandbox or a tool the owning team is retiring. A mute requires a reason, and the reason stays with the agent so the next reviewer knows why it was set aside. Choose the bell icon on the row, or select several rows and mute them together. Muted agents move to the Muted view, where they can be unmuted and registered later.

Muting is not approval. A muted agent is still unmonitored. Review the Muted view on the same cadence as your other governance reviews, because an agent that was harmless when muted can gain new tools or start calling new models.

Re-scan after acting. Registering or muting takes effect immediately, but the next scan is what confirms the agent is still there. Run a manual scan if you want that confirmation now.

Follow up with the owner. Each agent records which source found it, where it runs, and when it was last seen. That is usually enough to find the team responsible and ask them to adopt tracing, which gives Arthur far more to work with than discovery alone.

Running without the Platform

The ML Engine can also run discovery on its own, as a single container that scans the sources named in a YAML file and sends each agent to Splunk HEC or an HTTPS webhook. It needs no Platform and no GenAI Engine, so there is no task representation of what it finds: the inventory lives in your SIEM, and Steps 3 and 4 of this guide do not apply. Source and config concepts are the same. See Run Standalone Agent Discovery on Kubernetes.

Troubleshooting

SymptomLikely causeWhat to do
Test Connection failsWrong credential, missing permission, or the ML Engine cannot reach the sourceRead the message; it names which. Check the credential's role, then outbound access from the engine
Source saved, but no scan has runNo Arthur Engine is online, or the config is bound to an engine that is downCheck the Engine card on the Discovery targets tab; a green dot next to the engine means it is reporting. Scans queue until an engine picks them up
Scan succeeded with zero agentsLookback window shorter than the interval, a query that matches nothing, or the source has no agents in the scoped region or groupWiden the window, run the query in the source's own console, or widen the scope
Same agent appears twiceTwo sources see it with different external IDs (for example, a cloud platform and a gateway log)Expected in v1. Register the one with the richer evidence and mute the other with a reason that names it
Agent registered, but traces still land on an unregistered agentThe tracing service.name does not match the discovered agent's keyAlign the service name in the application's tracing config with the name discovery reported
Scan takes hours or times outLookback window too wide, or a query that scans too muchNarrow the window or the query. Raise the scan timeout only if the scan is close to finishing
Agent vanished from the listIt was registered or muted by someone else, or it has a new external IDCheck the Muted view and the registered applications list first

References

Related pages:


Did this page help you?