Agent

Report ONE completed sweep, at the end of every sweep, attended or unattended

POSThttps://backend.immut.io/api/v1/agent/runs

Required 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)

FieldTypeRequiredDescription
runIdstringyesyour own unique id for this sweep (required; reuse it to retry the same report)
workspacestringnoworkspace id
startedAtstringnoISO 8601
finishedAtstringnoISO 8601 (defaults to now)
modestringnointeractive | unattended
objectivestringnothe objective this sweep served
triggerstringnowhat started it, in plain words
countsstringnoreviewed, protected, waiting, leftAlone, failed, unreadable
coveragestringnoenumerated, opened, notOpened. What you could actually read, not what you hoped to
connectorsReachedstringnoarray of the sources you genuinely reached this run
decisionsstringnoOPTIONAL, 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.
unreadableGroupsstringnoOPTIONAL. 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

StatusMeaning
200Success
400BadRequest
401Unauthorized
403Forbidden
429RateLimited

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