{
  "$comment": "GENERATED by backend scripts/apiAudit/generateMcpTools.js. Do not edit by hand.",
  "server": {
    "name": "immut",
    "version": "0.2.0",
    "url": "https://backend.immut.io/mcp",
    "transport": "streamable HTTP, stateless. POST only; GET and DELETE return 405.",
    "authentication": "Authorization: Bearer imut_live_... or x-api-key: imut_live_... (x-api-key is accepted on /mcp only; /api/v1 requires Bearer)."
  },
  "toolCount": 28,
  "notes": [
    "protect_path (read a file from the server disk) is NOT part of the hosted connector. The flag that enables it is ignored whenever NODE_ENV is production, so it exists only for a server you run beside yourself. The hosted equivalent is protect_file, which takes the bytes.",
    "reject_staged permanently deletes the stored bytes and the row. It is the only destructive tool.",
    "get_certificate returns metadata only on the hosted server. The PDF bytes are not sent to an MCP client; download it from the app or GET /api/v1/certificates/{id}."
  ],
  "tools": [
    {
      "name": "ack_agent_instruction",
      "title": "Report that you carried out an instruction",
      "description": "Tell immut you have ACTED on one instruction from get_agent_instructions. Call it only after the action is really done — a human clicking a button is not evidence the file was handled, which is why this is a separate call from creating the instruction. Pass the runId of the sweep that applied it so the two records line up. Use cancelled if you could not act and will not retry (for example the file no longer exists).",
      "access": "write",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/instructions/",
      "arguments": {
        "instructionId": {
          "type": "string",
          "required": true,
          "description": "Id from get_agent_instructions"
        },
        "status": {
          "type": "enum",
          "required": true,
          "description": "applied = you did it; cancelled = you will not, and will not retry",
          "values": [
            "applied",
            "cancelled"
          ]
        },
        "runId": {
          "type": "string",
          "required": false,
          "description": "runId of the sweep that applied it (recommended)"
        }
      }
    },
    {
      "name": "annotate_document",
      "title": "Describe a document",
      "description": "Record what a document is and who it involves, so it can be found later by counterparty and ordered by its own date. This is the only way to classify a file that was uploaded through the web app or protected before it had a classification. ⛔ MERGES rather than replaces, so sending one field never blanks the others. ⛔ Returns 409 if a PERSON set the classification: a human decision is not overwritten. ⚠️ `abstract` describes what the document SAYS and is refused with 403 unless the organisation has enabled abstracts. `documentDate` is the date you read off the page and is NOT proven by immut, unlike the protection date. Never present the two as the same kind of fact.",
      "access": "write",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/documents/",
      "arguments": {
        "documentId": {
          "type": "string",
          "required": true,
          "description": "The document to describe"
        },
        "parties": {
          "type": "string",
          "required": false,
          "description": "Named counterparties, e.g. [\"Acme Corp\"]"
        },
        "documentDate": {
          "type": "string",
          "required": false,
          "description": "The date ON the document, ISO 8601. Agent-read, NOT proven"
        },
        "abstract": {
          "type": "string",
          "required": false,
          "description": "One or two lines on what it holds. Needs org consent"
        },
        "docType": {
          "type": "string",
          "required": false,
          "description": "contract | ip_disclosure | policy | board | financial | corporate | other"
        },
        "docState": {
          "type": "string",
          "required": false,
          "description": "executed | issued | draft | template | proposal | superseded | unknown"
        },
        "reason": {
          "type": "string",
          "required": false,
          "description": "One citable reason for the classification"
        }
      }
    },
    {
      "name": "approve_staged",
      "title": "Protect a staged file (human decision)",
      "description": "Protect a file that was waiting for a decision. ⛔ ONLY after a person has explicitly said yes to THIS file, by name, in this conversation. You may never call this on your own judgement — the file is in the queue because judgement was not enough. Writes the ledger record NOW, so the proof carries today's date, not the date it was staged. Read the network in the result and tell the person: only a mainnet proof is permanent.",
      "access": "write",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/review/",
      "arguments": {
        "documentId": {
          "type": "string",
          "required": true,
          "description": "Id from list_review_queue"
        }
      }
    },
    {
      "name": "create_folder",
      "title": "Create an immut folder",
      "description": "Create a folder in a workspace (optionally under a parent) so documents are organised, e.g. \"Contracts\" or \"Intellectual property\". Returns the folder id to pass to protect_path/protect_file.",
      "access": "write",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/folders",
      "arguments": {
        "name": {
          "type": "string",
          "required": true,
          "description": ""
        },
        "workspace": {
          "type": "string",
          "required": true,
          "description": ""
        },
        "parentFolder": {
          "type": "string",
          "required": false,
          "description": ""
        }
      }
    },
    {
      "name": "create_workspace",
      "title": "Create an immut workspace",
      "description": "Create a new immut workspace (requires the workspaces:write scope). Succeeds only if the plan has a free workspace slot; otherwise returns an \"upgrade to add a workspace\" message (relay it to the user).",
      "access": "write",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/workspaces",
      "arguments": {
        "name": {
          "type": "string",
          "required": true,
          "description": ""
        }
      }
    },
    {
      "name": "get_agent_instructions",
      "title": "Decisions the human made in immut",
      "description": "Decisions a person made in the immut app that YOU must now carry out. CALL THIS AT THE START OF EVERY SWEEP, before you look at any files. `protect` = upload that path on this sweep; `reject` = leave it alone and record the decision declined_by_human. These are the human's answers about files they were shown; do not second-guess them. Mark each one done with ack_agent_instruction once you have actually acted — not when you have read it. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/instructions",
      "arguments": {
        "status": {
          "type": "enum",
          "required": false,
          "description": "Defaults to pending, which also excludes instructions that have expired",
          "values": [
            "pending",
            "applied",
            "cancelled"
          ]
        }
      }
    },
    {
      "name": "get_agent_run",
      "title": "One sweep in full",
      "description": "One sweep and the documents it protected. This is the ONLY tool that returns decisions[] in full for a run: the per-file record of what the agent chose NOT to protect and why. Also returns unreadableGroups[], the metadata-only summary of files it could not open. decisions[] is consent-gated, so an absent array means the customer never opted in to sending it, NOT that nothing was excluded. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/runs/",
      "arguments": {
        "runId": {
          "type": "string",
          "required": true,
          "description": "The immut id of the run, from list_agent_runs"
        },
        "docPage": {
          "type": "number",
          "required": false,
          "description": "Page of the joined document list"
        },
        "docLimit": {
          "type": "number",
          "required": false,
          "description": "Page size, max 100 (default 50)"
        }
      }
    },
    {
      "name": "get_agent_status",
      "title": "Has immut heard from this agent?",
      "description": "Whether immut has heard from this organisation's agent recently. Returns hasEverRun, lastRunAt, silentDays, thresholdDays and isAbsent. ⚠️ lastRunAt is when immut last HEARD from the agent, which is NOT when it last ran: a sweep that ran and failed to report looks identical to one that never happened. So this tells you whether reporting is working — never present it as evidence that any particular file is or is not protected. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/status",
      "arguments": {}
    },
    {
      "name": "get_certificate",
      "title": "Get the court-ready certificate (PDF)",
      "description": "Fetch the shareable, court-ready certificate PDF for a protected document (the artifact you hand to an investor, acquirer or auditor). Returns metadata only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": null,
      "arguments": {
        "documentId": {
          "type": "string",
          "required": true,
          "description": ""
        }
      }
    },
    {
      "name": "get_document",
      "title": "Get one protected document",
      "description": "Get the details of a single protected document by id (name, folder, proof, network, dates). Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/documents/",
      "arguments": {
        "documentId": {
          "type": "string",
          "required": true,
          "description": ""
        }
      }
    },
    {
      "name": "get_proof",
      "title": "Get proof details (+ salt)",
      "description": "Get a proof’s status and details by id; pass includeSalt to also return the proof nonce needed to independently recompute a salted commitment. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/proofs/",
      "arguments": {
        "proofId": {
          "type": "string",
          "required": true,
          "description": "Document/proof id"
        },
        "includeSalt": {
          "type": "boolean",
          "required": false,
          "description": "Also return proofNonce (salt) for independent verification"
        }
      }
    },
    {
      "name": "get_staged_file",
      "title": "One file waiting for a decision",
      "description": "Details of a single staged file so a person can decide about it — what it is, why it was held, and where it would be filed if approved. It is NOT protected and has no proof. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/review/",
      "arguments": {
        "documentId": {
          "type": "string",
          "required": true,
          "description": "Id from list_review_queue"
        }
      }
    },
    {
      "name": "get_usage",
      "title": "Get upload usage this period",
      "description": "Show how many files have been protected this billing period (by channel) and the period dates. Requires the billing:read scope. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/billing/usage",
      "arguments": {}
    },
    {
      "name": "get_user",
      "title": "Get one organization user",
      "description": "Get one organization member by id. Requires the users:read scope. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/users/",
      "arguments": {
        "userId": {
          "type": "string",
          "required": true,
          "description": ""
        }
      }
    },
    {
      "name": "list_agent_decisions",
      "title": "What the agent decided NOT to protect",
      "description": "Query, across every sweep, the files the agent decided not to protect, with the reason it gave, the doc type it judged, and when the sweep ran. Use it for \"what did my agent leave alone last month and why\". ⚠️ Read meta.consent before reporting an empty list: decisions are consent-gated, so never_consented means the customer never opted in to sending them, which is NOT the same as nothing being excluded. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/decisions",
      "arguments": {
        "decision": {
          "type": "string",
          "required": false,
          "description": "One of the 11 decision codes; an unknown code is rejected"
        },
        "docType": {
          "type": "string",
          "required": false,
          "description": "Filter by doc type"
        },
        "docState": {
          "type": "string",
          "required": false,
          "description": "Filter by doc state"
        },
        "workspace": {
          "type": "string",
          "required": false,
          "description": "Workspace id"
        },
        "objective": {
          "type": "string",
          "required": false,
          "description": "The objective the sweep served"
        },
        "from": {
          "type": "string",
          "required": false,
          "description": "ISO 8601, on the sweep finish time"
        },
        "to": {
          "type": "string",
          "required": false,
          "description": "ISO 8601, on the sweep finish time"
        },
        "search": {
          "type": "string",
          "required": false,
          "description": "Matches the file path and the reason"
        },
        "page": {
          "type": "number",
          "required": false,
          "description": "Page number (default 1)"
        },
        "limit": {
          "type": "number",
          "required": false,
          "description": "Page size, max 100 (default 50)"
        }
      }
    },
    {
      "name": "list_agent_runs",
      "title": "Sweep history",
      "description": "The sweeps this organisation's agent has reported, newest first. Use it to answer \"when did my agent last run\", \"how many files did it review last month\", or to find a runId to drill into. Returns counts and coverage per run. decisions[] is omitted here for size, so use get_agent_run for one run or list_agent_decisions to query across runs. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/runs",
      "arguments": {
        "workspace": {
          "type": "string",
          "required": false,
          "description": "Workspace id"
        },
        "mode": {
          "type": "enum",
          "required": false,
          "description": "Only sweeps of this kind",
          "values": [
            "interactive",
            "unattended"
          ]
        },
        "objective": {
          "type": "string",
          "required": false,
          "description": "Only sweeps that served this objective"
        },
        "protectedOnly": {
          "type": "boolean",
          "required": false,
          "description": "true excludes sweeps that protected nothing"
        },
        "from": {
          "type": "string",
          "required": false,
          "description": "ISO 8601, on the sweep finish time"
        },
        "to": {
          "type": "string",
          "required": false,
          "description": "ISO 8601, on the sweep finish time"
        },
        "page": {
          "type": "number",
          "required": false,
          "description": "Page number (default 1)"
        },
        "limit": {
          "type": "number",
          "required": false,
          "description": "Page size, max 100 (default 20)"
        }
      }
    },
    {
      "name": "list_documents",
      "title": "List / count protected documents",
      "description": "List and COUNT the protected documents (files) in a workspace, optionally filtered by folder or a name search. Use this to answer \"how many files do I have\" or to show what has been protected. Returns the total count plus a page of documents (name, folder, proof tx, network, date). Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/documents",
      "arguments": {
        "workspace": {
          "type": "string",
          "required": true,
          "description": "Workspace id"
        },
        "folder": {
          "type": "string",
          "required": false,
          "description": "Folder id to count/list within (omit for the whole workspace)"
        },
        "search": {
          "type": "string",
          "required": false,
          "description": "Filter by file name, title, or the agent reason"
        },
        "uploadChannel": {
          "type": "enum",
          "required": false,
          "description": "agent = only what the AI agent protected",
          "values": [
            "web",
            "api",
            "agent"
          ]
        },
        "docType": {
          "type": "string",
          "required": false,
          "description": "Agent classification doc type"
        },
        "docState": {
          "type": "string",
          "required": false,
          "description": "Agent classification doc state"
        },
        "objective": {
          "type": "string",
          "required": false,
          "description": "The objective the agent was working to"
        },
        "runId": {
          "type": "string",
          "required": false,
          "description": "Only documents protected by this sweep"
        },
        "needsFolder": {
          "type": "boolean",
          "required": false,
          "description": "true = agent-protected files still at the workspace root"
        },
        "party": {
          "type": "string",
          "required": false,
          "description": "Exact counterparty name, e.g. \"Acme Corp\". Not a substring: Acme will not match Acme Holdings"
        },
        "hasClassification": {
          "type": "boolean",
          "required": false,
          "description": "false = documents nobody has described yet. The backfill starting point"
        },
        "documentDateFrom": {
          "type": "string",
          "required": false,
          "description": "ISO 8601, on the date read OFF the document (unproven)"
        },
        "documentDateTo": {
          "type": "string",
          "required": false,
          "description": "ISO 8601, on the date read OFF the document (unproven)"
        },
        "sort": {
          "type": "enum",
          "required": false,
          "description": "createdAt = when immut proved it. documentDate = the date on the page, unproven",
          "values": [
            "createdAt",
            "documentDate"
          ]
        },
        "order": {
          "type": "enum",
          "required": false,
          "description": "Default desc. Use asc for a chronological story",
          "values": [
            "asc",
            "desc"
          ]
        },
        "minConfidence": {
          "type": "number",
          "required": false,
          "description": "Lowest classification confidence to include"
        },
        "maxConfidence": {
          "type": "number",
          "required": false,
          "description": "Highest classification confidence to include"
        },
        "from": {
          "type": "string",
          "required": false,
          "description": "ISO 8601. Only documents protected on or after this"
        },
        "to": {
          "type": "string",
          "required": false,
          "description": "ISO 8601. Only documents protected on or before this"
        },
        "page": {
          "type": "number",
          "required": false,
          "description": "Page number (default 1)"
        },
        "limit": {
          "type": "number",
          "required": false,
          "description": "Page size, max 100 (default 20)"
        }
      }
    },
    {
      "name": "list_folders",
      "title": "List immut folders",
      "description": "List folders in a workspace so you can file a document in the right place. Omit parentFolder for top-level; pass a folder id for its children, or \"all\" for every folder at all depths. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/folders",
      "arguments": {
        "workspace": {
          "type": "string",
          "required": true,
          "description": "Workspace id"
        },
        "parentFolder": {
          "type": "string",
          "required": false,
          "description": "Parent folder id, or \"all\" for every folder"
        }
      }
    },
    {
      "name": "list_review_queue",
      "title": "Files waiting for a human decision",
      "description": "Files that were staged because an agent could not tell whether they should be protected. A staged file has NO proof and NO ledger record, is not counted as protected anywhere, and is deleted if nobody decides within 90 days. This is the ONLY tool that returns them. Never describe anything in this list as protected. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/review",
      "arguments": {
        "page": {
          "type": "number",
          "required": false,
          "description": ""
        },
        "limit": {
          "type": "number",
          "required": false,
          "description": "Page size, max 100"
        }
      }
    },
    {
      "name": "list_users",
      "title": "List organization users",
      "description": "List the members of the organization (name, email, role). Requires the users:read scope. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/users",
      "arguments": {}
    },
    {
      "name": "list_versions",
      "title": "List a document’s versions",
      "description": "List the version history of a protected document (each revision, when it was proven). Read-only. Use to show how a file changed over time.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/documents/",
      "arguments": {
        "documentId": {
          "type": "string",
          "required": true,
          "description": ""
        }
      }
    },
    {
      "name": "list_workspaces",
      "title": "List immut workspaces",
      "description": "List the immut workspaces this key can access. Use this first to get the workspace id that every other tool needs. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/workspaces",
      "arguments": {}
    },
    {
      "name": "protect_file",
      "title": "Protect a file on immut (by bytes)",
      "description": "Protect a file by passing its bytes as base64. This server is remote and cannot read your filesystem, so bytes are the only way in. Do NOT transcribe a large file into base64 here (it is slow and error-prone): for anything substantial, upload it directly with multipart POST /api/v1/documents, or install the immut skill so it can read the file locally. Returns the proof. Set review=true instead if you are NOT sure the file should be protected — that stages it for a person and writes no proof.",
      "access": "write",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": null,
      "arguments": {
        "filename": {
          "type": "string",
          "required": true,
          "description": "Original file name incl. extension"
        },
        "contentBase64": {
          "type": "string",
          "required": true,
          "description": "Base64-encoded file bytes"
        },
        "workspace": {
          "type": "string",
          "required": true,
          "description": "Workspace id"
        },
        "folder": {
          "type": "string",
          "required": false,
          "description": "Destination folder id (omit to file at workspace root)"
        },
        "runId": {
          "type": "string",
          "required": false,
          "description": "Id of the sweep this upload belongs to. Use the SAME value on every file in one sweep and on the matching report_run call — it is what links a run to the files it protected."
        },
        "agentClassification": {
          "type": "string",
          "required": false,
          "description": "What you judged about this file, recorded against the proof. Every field optional — send only what you actually determined, and never invent a verdict you did not reach."
        },
        "review": {
          "type": "boolean",
          "required": false,
          "description": "true = do NOT protect it; stage it for a human to decide. No proof is written. Use when you cannot tell whether the file is evidence for the objective."
        },
        "sourcePath": {
          "type": "string",
          "required": false,
          "description": "Where the file lives on the customer's machine. Only used with review=true, so the human can see what they are deciding about and the file is not staged again next sweep."
        }
      }
    },
    {
      "name": "protect_new_version",
      "title": "Protect a new version of an existing document (by bytes)",
      "description": "Protect an UPDATED version of a document already on immut — proves when the file changed. This server is remote and cannot read your filesystem, so pass the new bytes as base64 along with the existing documentId. Use when a protected file has been revised (e.g. a contract re-signed, a policy updated). Do NOT transcribe a large file into base64 here (it is slow and error-prone): for anything substantial use multipart POST /api/v1/documents/{id}/version directly, or install the immut skill so it can read the file locally. Find the documentId with list_documents.",
      "access": "write",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": null,
      "arguments": {
        "documentId": {
          "type": "string",
          "required": true,
          "description": "Id of the existing immut document to add a version to"
        },
        "filename": {
          "type": "string",
          "required": true,
          "description": "Original file name incl. extension"
        },
        "contentBase64": {
          "type": "string",
          "required": true,
          "description": "Base64-encoded bytes of the NEW version"
        },
        "runId": {
          "type": "string",
          "required": false,
          "description": "Id of the sweep this upload belongs to. Use the SAME value on every file in one sweep and on the matching report_run call — it is what links a run to the files it protected."
        },
        "agentClassification": {
          "type": "string",
          "required": false,
          "description": "What you judged about this file, recorded against the proof. Every field optional — send only what you actually determined, and never invent a verdict you did not reach."
        }
      }
    },
    {
      "name": "read_document",
      "title": "Read a protected document",
      "description": "Fetch the decrypted contents of a document this organisation already owns, so you can review it and then describe it with annotate_document. Use it for files nobody classified at upload time, for example ones a person uploaded through the web app. ⚠️ Requires the documents:content scope, which agent keys do NOT get by default: an admin grants it deliberately, because it is the difference between a key that sees metadata and one that reads documents. Every read is recorded in the customer's audit log. Staged files cannot be read here. This server is hosted, so the bytes travel through immut to reach you. Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": null,
      "arguments": {
        "documentId": {
          "type": "string",
          "required": true,
          "description": "The document to read"
        }
      }
    },
    {
      "name": "reject_staged",
      "title": "Reject a staged file — DELETES it (human decision)",
      "description": "Reject a file that was waiting for a decision. ⛔ THIS PERMANENTLY DELETES the stored file and its record from immut. It cannot be undone. ONLY after a person has explicitly said no to THIS file, by name, in this conversation — never on your own judgement. Deletion is deliberate: immut keeping a document the customer declined is the problem this queue would otherwise create. immut also records the decision so the file is not staged again on the next sweep.",
      "access": "write",
      "destructive": true,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/review/",
      "arguments": {
        "documentId": {
          "type": "string",
          "required": true,
          "description": "Id from list_review_queue"
        }
      }
    },
    {
      "name": "report_run",
      "title": "Report a completed sweep to immut",
      "description": "Log one completed sweep (a pass over the sources looking for files to protect). Call this at the END OF EVERY sweep, including a sweep that protected nothing or stopped early — immut uses these to notice when an agent stops reporting, so a skipped call looks the same as a broken agent. Idempotent on runId: re-posting the same runId updates that run rather than creating a second. Use the SAME runId you passed to every protect call in this sweep — that is what links the run to the files it protected. OPTIONAL, AND ONLY WITH THE HUMAN'S EXPLICIT YES: `decisions` lists the files you decided NOT to protect and why. Sending it means immut stores the names of documents it was never asked to protect, and a filename alone can be sensitive, so ask first and default to not sending. On a no, omit the field entirely — an empty array is NOT the same as absent: immut reads an empty array as \"the agent looked and excluded nothing\", which is a claim you did not make.",
      "access": "write",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/v1/agent/runs",
      "arguments": {
        "runId": {
          "type": "string",
          "required": true,
          "description": "Unique id for this run (stable across retries of the same run)"
        },
        "workspace": {
          "type": "string",
          "required": false,
          "description": "Workspace id this sweep covered"
        },
        "mode": {
          "type": "enum",
          "required": false,
          "description": "interactive = a human was present; unattended = started by a schedule",
          "values": [
            "interactive",
            "unattended"
          ]
        },
        "objective": {
          "type": "string",
          "required": false,
          "description": "Objective id only, e.g. \"fundraise\" (never a label or notes)"
        },
        "trigger": {
          "type": "string",
          "required": false,
          "description": "What started this run, e.g. \"host scheduled task\""
        },
        "startedAt": {
          "type": "string",
          "required": false,
          "description": "ISO-8601"
        },
        "finishedAt": {
          "type": "string",
          "required": false,
          "description": "ISO-8601"
        },
        "counts": {
          "type": "string",
          "required": false,
          "description": "What the sweep did. waiting = files awaiting a human decision"
        },
        "coverage": {
          "type": "string",
          "required": false,
          "description": "How much of what was found actually got read"
        },
        "connectorsReached": {
          "type": "string",
          "required": false,
          "description": "Sources successfully read this run"
        },
        "connectorsUnreachable": {
          "type": "string",
          "required": false,
          "description": "Sources that could not be read this run"
        },
        "network": {
          "type": "enum",
          "required": false,
          "description": "",
          "values": [
            "testnet",
            "mainnet",
            "mixed",
            "none"
          ]
        },
        "reportFilename": {
          "type": "string",
          "required": false,
          "description": "Name of the run report written alongside"
        },
        "decisions": {
          "type": "string",
          "required": false,
          "description": "ONLY with the human's explicit yes. Per-file decisions, INCLUDING files you did not protect. Put the ones that produced no document first — a protected file already carries its reasoning on the document itself. Max 500 stored per run."
        },
        "unreadableGroups": {
          "type": "string",
          "required": false,
          "description": "Files you could not open, grouped by folder and type. NEVER include a filename here — this field is metadata only and is not covered by the decisions consent. Max 200 groups."
        }
      }
    },
    {
      "name": "verify_proof",
      "title": "Verify an immut proof (keyless)",
      "description": "Verify a proof by its ledger transaction hash via the public keyless endpoint — use to confirm a proof (e.g. checking a diligence pack). Read-only.",
      "access": "read",
      "destructive": false,
      "hostedOnProduction": true,
      "restEndpoint": "/api/public/verify/",
      "arguments": {
        "txHash": {
          "type": "string",
          "required": true,
          "description": "Ledger transaction hash"
        }
      }
    }
  ]
}
