Skip to content

Agent Output

Emit queryable findings, assets, and capability-defined records from your agents, then triage and link them in the platform.

Agent Output is the structured side of what an agent produces — typed records it emits as it works, so an engagement’s results can be filtered, linked, and reported on instead of read line by line. The two built-in record types are finding and asset, and a capability can define its own.

Turn it on with one line in the manifest:

capability.yaml
produces: true

That gives the agent three tools — report_item, update_item, and link_items (records are items in the tools and API) — and enables the built-in finding and asset types. When the agent discovers something, it reports it:

report_item(
item_type="finding",
data={"title": "SQL injection in /login", "severity": "high"},
)

The record lands in the project, tied to the session and trace span that produced it. The tools are opt-in: a capability with no produces config receives none of them.

produces in the manifest selects which record types the agent can emit:

producesResult
trueBuilt-in finding and asset
false or omittedNo output tools
finding / [finding, asset]Selected built-ins
{ name: "module:Class" }Capability-defined types (see below)

A finding is something the agent discovered that matters; an asset is something it identified in scope. Both require a title; the rest of the payload is validated against the type’s schema and stored as queryable data. Unknown fields are dropped.

A finding carries severity and impact:

FieldTypeNotes
titlestrRequired. Short, specific.
severitycritical | high | medium | low | infoDefaults to info.
descriptionstrWhat was observed and why it matters.
categorystrCWE/OWASP bucket or domain category.
evidencestrRequest/response, command output, or a file path.
metadatadictMachine-readable context.

An asset describes something in scope and has no severity:

FieldTypeNotes
titlestrRequired.
asset_typestrhost, service, file, account, endpoint, model, artifact.
identifierstrHostname, IP, URL, path, account id, or artifact URI.
descriptionstrContext or provenance.
metadatadictMachine-readable context.

To address a record later — to update it or link it — give it a ref, a short name unique within the project:

report_item(
item_type="asset",
data={"title": "web-1", "asset_type": "host", "identifier": "10.0.0.5"},
ref="web-1",
)

When findings and assets don’t fit — an attack surface, a harvested credential, a model artifact — declare a Pydantic model and point produces at it:

surfaces.py
from pydantic import BaseModel
class AttackSurface(BaseModel):
host: str
open_ports: list[int]
notes: str | None = None
capability.yaml
produces:
attack_surface: 'surfaces:AttackSurface'

The build extracts the model’s JSON Schema, and the runtime hands the agent a report_item typed to your fields — the agent provides host and open_ports directly, and the platform validates every record on the way in:

report_item(
item_type="attack_surface",
data={"host": "10.0.0.5", "open_ports": [22, 443]},
)

Reports aren’t final. update_item patches a record or moves it through triage, and link_items connects records with a typed relationship:

update_item("web-1", status="verified", notes="Reachable, credentialed access confirmed.")
link_items("sqli-login", "web-1", relationship="affects")

Triage status is one of open, triaged, verified, resolved, or dismissed — a typical review runs open → triaged → verified → resolved, but the platform enforces no ordering, so you can set any value at any time. Status lives in a separate overlay from the record’s data, so triage state and the agent’s original report never overwrite each other.

In the platform, a project’s records live on the Agent Output page — one tab per type (findings, assets, then any capability-defined types), each a filterable table. A single session’s records also appear under that session’s Output tab. Filter by type, severity, or triage status to build the view you need.

Records inherit the visibility of the session that produced them: output from a private session is readable only by people who can see that session, while project-level records are visible to the whole project.

A reported record is written to the platform directly and logged to the agent’s trace at the same time. If the direct write fails — a transient network error, say — the record still lands in the trace as a backup, so a flaky connection doesn’t lose data.

produces is one of the capability manifest fields; the forms above are its full grammar. The report_item, update_item, and link_items tools — with complete parameter signatures — are documented in the dreadnode.tools reference.