Documentation
AssayUse Assay from your agent
Updated
Assay runs an MCP server so an AI agent can query usage, read captured content, curate datasets and erase subjects. Usage and content are separate abilities, exactly as they are for people.
Content tools send raw customer data to the MCP client, and from there to that client's model provider, its transcript and its logs. Treat every MCP client you give content access to as an additional processor of that data.
Two ways in
Through Scalpels. If your agent uses the Scalpels MCP server with the Call installed apps ability, it can list Assay among your team's MCP-enabled products and relay tool calls to it as you. Assay applies your role: team Owners and Admins arrive as Admins (usage plus content by default), and Members arrive as Members (usage only).
Directly, with a credential. Assay's MCP credentials are created by an operator from the command line; there is no screen for them. Run the command inside the Assay environment, for example from Laravel Cloud's command runner:
# Usage only
php artisan bfc:credential:mint external_consumer reporting-agent --purpose=mcp --abilities=assay.usage --local
# Usage and content
php artisan bfc:credential:mint external_consumer curation-agent --purpose=mcp --abilities=assay.usage,assay.content --local
The second argument names the agent. The command prints the secret once (Save this credential - shown once: ...). Give it to the MCP client as a bearer token in the Authorization header. Abilities are literal: a credential with only assay.usage sees no content tools. An agent that works with content should carry both.
Installation credentials issued for reporting applications are refused by the MCP endpoints.
Endpoints
| Path | What it serves |
|---|---|
/mcp |
Read-only tools. Write and destructive tools are refused here. |
/mcp/destructive |
Every tool your abilities allow, including flagging, dataset changes and subject erasure. |
Point an agent that only reports at /mcp. Use /mcp/destructive only for an agent that should curate or erase.
Tools
The app argument is an application's name in Assay: the subject reference its installation credential was issued for.
Usage tools (assay.usage)
| Tool | Endpoint | What it does |
|---|---|---|
usage_summary |
both | Sums one usage metric between from and to, grouped by app, environment, operation, provider, model, agent or subject. |
top_runs |
both | Lists runs ordered by one usage metric. |
reliability_summary |
both | Failure, failover and tool-failure rates. |
run_tree |
both | Up to 500 metadata-only nodes of one run tree in one app. |
These tools never return messages, bodies, tool arguments or results, notes or exception messages.
Content tools (assay.content)
| Tool | Endpoint | What it does |
|---|---|---|
run_content |
both | Returns the captured bodies and messages of one run in one app. |
search_runs |
both | Searches captured content within one app and returns matching runs. |
dataset_list |
both | Lists datasets with their item counts. |
dataset_export |
both | Returns a 15-minute download link for a dataset's JSONL export, never the JSONL itself. Only the same credential can use the link. |
flag_run |
destructive | Sets a run's labels (up to 25), rating (pass, fail, 1 to 5) and note. |
label_run |
destructive | Replaces a run's labels and keeps its rating and note. |
dataset_create |
destructive | Creates a dataset, with optional retention_days or no_expiry. |
dataset_add |
destructive | Adds an immutable snapshot of a run to a dataset. |
delete_subject |
destructive | Erases one subject in one app. See below. |
Erasing a subject
delete_subject is two-phase. The first call, with app and subject, makes no changes: it returns a preview with the number of matching runs and a confirmation. Calling the tool again with the same arguments plus that confirmation as confirm performs the erasure, once. What erasure does is described in Access, retention and erasure.
Cost questions
Assay reports usage, not money. Its MCP instructions tell agents that, for a cost question, they should fetch the provider's current published prices, cite the URL and the date they retrieved it, and label the answer a current-list-price estimate of observed successful usage. That estimate excludes failed attempts, dropped telemetry and metrics the provider did not report, so it is a lower bound.