Skip to main content

Agents over the data

The Investigator: a propose-only agent that assembles the evidence for a hold and streams a draft disposition.

MethodPathScopeSummary
POST/ai/analyst/askreadAsk Analyst
POST/ai/investigator/runreview + readRun Investigator
GET/ai/red-team/packsreadList Red Team Packs
POST/ai/red-team/packs/{pack_id}/{decision}readDecide Red Team Pack
POST/ai/red-team/runreadRun Red Team
GET/ai/runsreadList Runs
GET/ai/runs/{run_id}readGet Run

Try it​

curl -sf -H "Authorization: Bearer $VIGIL_KEY" "$VIGIL_URL/ai/runs?limit=5"

Routes​

POST /ai/analyst/ask​

Ask Analyst. Scope: read.

Stream a Fleet Analyst answer to one question over the caller's org's gold and silver tables.

Request body:

{
"question": "string"
}
FieldTypeRequiredNotes
questionstringyes

Response 200:

"any"

POST /ai/investigator/run​

Run Investigator. Scope: review + read.

Stream an Investigator run for one enforcement action in the caller's org.

Request body:

{
"action_id": 0
}
FieldTypeRequiredNotes
action_idintegeryes

Response 200:

"any"

GET /ai/red-team/packs​

List Red Team Packs. Scope: read.

The org's runtime packs, newest first, each with its steps and the coverage record from the run that produced it.

ParameterInRequiredTypeNotes
statusquerynostring | null
limitquerynointeger

Response 200:

[
{
"id": 0,
"name": "string",
"origin": "string",
"status": "string",
"steps": [
{}
],
"coverage": {},
"created_at": "string"
}
]

POST /ai/red-team/packs/{pack_id}/{decision}​

Decide Red Team Pack. Scope: read.

Accept or reject a proposed pack. Sets the status and nothing else; the frozen packs in api/scenarios.py change only by a commit.

ParameterInRequiredTypeNotes
pack_idpathyesinteger
decisionpathyesstring

Response 200:

{
"id": 0,
"name": "string",
"origin": "string",
"status": "string",
"steps": [
{}
],
"coverage": {},
"created_at": "string"
}

POST /ai/red-team/run​

Run Red Team. Scope: read.

Stream a Red Team run: three new packs at the weakest detector, run against the sandbox agent, saved as proposed.

Response 200:

"any"

GET /ai/runs​

List Runs. Scope: read.

ParameterInRequiredTypeNotes
limitquerynointeger

Response 200:

[
{
"id": 0,
"agent": "string",
"input": {},
"status": "string",
"tokens_in": 0,
"tokens_out": 0,
"cost_usd": 0,
"output_text": "string | null",
"started_at": "string",
"finished_at": "string | null",
"proposals": [
{
"id": 0,
"run_id": 0,
"action_id": 0,
"kind": "string",
"body": {},
"status": "string",
"created_at": "string"
}
]
}
]

GET /ai/runs/{run_id}​

Get Run. Scope: read.

ParameterInRequiredTypeNotes
run_idpathyesinteger

Response 200:

{
"id": 0,
"agent": "string",
"input": {},
"status": "string",
"tokens_in": 0,
"tokens_out": 0,
"cost_usd": 0,
"output_text": "string | null",
"started_at": "string",
"finished_at": "string | null",
"proposals": [
{
"id": 0,
"run_id": 0,
"action_id": 0,
"kind": "string",
"body": {},
"status": "string",
"created_at": "string"
}
]
}

Generated from openapi.json (VIGIL 0.2.0). Scopes follow the router dependencies in VIGIL_SPEC.md section 4.2.