Agent
Report ONE completed sweep, at the end of every sweep, attended or unattended
POST
https://backend.immut.io/api/v1/agent/runsRequired scope: documents:write
This is how immut learns the agent ran at all: without it a sweep that protected nothing is indistinguishable from an agent that never started. Idempotent: upserts on workspace + runId, so a retried post is safe. Report only what was actually observed; never estimate a count. Uses documents:write, which every agent key already carries, so no new key is needed.
Request body
Content type: application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
runId | string | yes | your own unique id for this sweep (required; reuse it to retry the same report) |
workspace | string | no | workspace id |
startedAt | string | no | ISO 8601 |
finishedAt | string | no | ISO 8601 (defaults to now) |
mode | string | no | interactive | unattended |
objective | string | no | the objective this sweep served |
trigger | string | no | what started it, in plain words |
counts | string | no | reviewed, protected, waiting, leftAlone, failed, unreadable |
coverage | string | no | enumerated, opened, notOpened. What you could actually read, not what you hoped to |
connectorsReached | string | no | array of the sources you genuinely reached this run |
decisions | string | no | OPTIONAL, and only with the human's explicit opt-in. Per-file decisions INCLUDING the files you decided NOT to protect: [{path, decision, docType, docState, servesObjective, confidence, folderConfidence, reason}]. Sending it means immut stores the names of documents it was never asked to protect, so ask first, default to off, and omit the field entirely on a no. An empty array is not the same as absent. decision must be one of: stored, unchanged_since_check, already_registered_elsewhere, declined_by_human, classified_pending_approval, read_not_selected, skipped_draft_wip, skipped_no_match, skipped_out_of_scope, upload_failed, undetermined_unreadable. Anything else is dropped. At most 500 are stored per run; send the ones that produced no document first, since a protected file already carries its reasoning on the document itself. |
unreadableGroups | string | no | OPTIONAL. Files you could not open, grouped so the customer can see the shape of what was missed without immut holding a list of their filenames: [{folder, extension, count, totalBytes, earliest, latest}]. METADATA ONLY. Never send a filename here. It is deliberately outside the decisions consent gate for that reason, and a group with no folder is dropped. At most 200 groups per run. |
Responses
| Status | Meaning |
|---|---|
200 | Success |
400 | BadRequest |
401 | Unauthorized |
403 | Forbidden |
429 | RateLimited |
Example
curl -X POST "https://backend.immut.io/api/v1/agent/runs" \
-H "Authorization: Bearer $IMMUT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"runId":"<runId>","workspace":"<workspace>","startedAt":"<startedAt>","finishedAt":"<finishedAt>","mode":"<mode>","objective":"<objective>","trigger":"<trigger>","counts":"<counts>","coverage":"<coverage>","connectorsReached":"<connectorsReached>","decisions":"<decisions>","unreadableGroups":"<unreadableGroups>"}'
Generated from the immut API contract, version 1.9.0. Machine-readable: this page as markdown · everything in one file · OpenAPI