> For the complete documentation index, see [llms.txt](https://docs.heeler.com/mrecEO40m5D6bt7Pq5pE/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.heeler.com/mrecEO40m5D6bt7Pq5pE/reference/agent-files-api.md).

# Agent Files API

The Agent Files scan API — POST an agent file or bundle and get back a safety score, assessed intent, and findings, synchronously.

The Agent Files API scans agent files and bundles for agent-targeting risk — prompt injection, data exfiltration, destructive actions, privilege escalation, secrets exposure, code execution, obfuscation, deception, and unsafe external references. Use it to vet a skill or MCP config **before** installing it, to gate agent-targeted files (`SKILL.md`, `.cursorrules`, `mcp.json`, agent prompt files) in CI, or to triage a suspicious file inline.

It complements the in-platform [Agent Files](/mrecEO40m5D6bt7Pq5pE/findings/agentic-supply-chain-agent-files.md) inventory: the inventory continuously scores the agent files already in your repositories; this API scores a file or bundle **on demand**.

{% hint style="info" %}
The scan is **synchronous and stateless** — nothing is persisted server-side; the report exists only in the response.
{% endhint %}

{% hint style="info" %}
**Prefer not to script it?** `heelercli scan-agent-file` wraps this endpoint with `--fail-on` and `--fail-on-intent` gates, and `heelercli ci --checks agent-files` discovers and scans every agent file in a repository. Both need CLI 1.0.21 or later — see the [CLI Command Reference](/mrecEO40m5D6bt7Pq5pE/reference/cli-command-reference.md#commands).
{% endhint %}

## `POST /api/agent_files/scan`

Scan a single agent file or a `.zip` bundle (e.g. an unpacked skill directory).

**Authentication** — send a Heeler API token (prefix `h4r-`) as a bearer token. Create one under **Administration → Access → API Keys**. Calls count against your key's budget and carry the usual rate limit headers — see [Rate Limits](/mrecEO40m5D6bt7Pq5pE/reference/rate-limits.md).

```
Authorization: Bearer h4r-...
```

**Request** — `multipart/form-data` with one field:

<table><thead><tr><th width="120">Field</th><th width="110">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>file</code></td><td>binary</td><td>A single agent file, or a <code>.zip</code> bundle of files.</td></tr></tbody></table>

**Size limits** — up to 3 files, 250 KB per file, 750 KB total uncompressed, and 1 MB uploaded. A violation returns `413` naming the offending file and limit.

```bash
# Single file
curl -sS -X POST https://app.heeler.com/api/agent_files/scan \
  -H "Authorization: Bearer <api_key>" \
  -F "file=@/tmp/SKILL.md"

# Zipped bundle (e.g. a packed skill directory)
curl -sS -X POST https://app.heeler.com/api/agent_files/scan \
  -H "Authorization: Bearer <api_key>" \
  -F "file=@/tmp/bundle.zip"
```

## Response

`200 OK` returns a **ScanReport** with two fields:

* **`summary`** — upload-wide rollup: `file_count`, `scored_count`, `judged_count`, `worst_score`, `worst_band`, `aggregate_assessed_intent`.
* **`files`** — one entry per file (including skipped ones), each with its score, verdict, score breakdown, and findings.

### Score and verdict

<table><thead><tr><th width="180">Field</th><th width="240">Values</th><th>Meaning</th></tr></thead><tbody><tr><td><code>score</code></td><td>0–100</td><td>Safety score — <strong>100 = safest, 0 = worst</strong>; <code>null</code> if not scored.</td></tr><tr><td><code>band</code></td><td>info · low · medium · high · critical</td><td>Qualitative bucket derived from the score.</td></tr><tr><td><code>assessed_intent</code></td><td>benign · suspicious · malicious</td><td>The judge's holistic read; <code>null</code> if not judged.</td></tr></tbody></table>

### Findings

Each file carries **static findings** (deterministic rules — `rule_id`, `asset_type`, `severity`, `confidence`, `locator`, `evidence`) and **LLM-judge findings** (a `category`, `severity`, `confidence`, `locator`, `rationale`, and `evidence`). LLM categories are:

`prompt_injection` · `data_exfiltration` · `destructive_action` · `privilege_escalation` · `secrets_exposure` · `code_execution` · `remote_code_execution` · `obfuscation` · `deception` · `unsafe_external_reference` · `other`

### Example

```json
{
  "summary": { "file_count": 2, "scored_count": 1, "worst_score": 35,
               "worst_band": "high", "aggregate_assessed_intent": "suspicious" },
  "files": [
    {
      "relative_path": "install.sh", "kind": "agent_file",
      "score": 35, "band": "high", "assessed_intent": "suspicious",
      "static_findings": [
        { "rule_id": "remote-pipe-to-shell", "asset_type": "external_system",
          "severity": "high", "confidence": "high", "locator": "install.sh:3",
          "evidence": "curl -fsSL https://example.com/install.sh | bash" }
      ],
      "llm_findings": [
        { "category": "remote_code_execution", "severity": "high", "confidence": "medium",
          "locator": "install.sh:3",
          "rationale": "Pipes a remotely fetched script straight into a shell.",
          "evidence": "curl -fsSL https://example.com/install.sh | bash" }
      ]
    },
    { "relative_path": "logo.png", "kind": "agent_file",
      "content_skipped": true, "skip_reason": "binary content" }
  ]
}
```

## Status codes

<table><thead><tr><th width="100">Code</th><th>Meaning</th></tr></thead><tbody><tr><td><code>200</code></td><td>Scan completed — report in the body.</td></tr><tr><td><code>400</code></td><td>Upload empty or could not be extracted (malformed/unsafe zip).</td></tr><tr><td><code>401</code></td><td>Missing, expired, or invalid authentication token.</td></tr><tr><td><code>413</code></td><td>Upload exceeded the size limit.</td></tr><tr><td><code>422</code></td><td>Validation error — <code>file</code> missing or malformed.</td></tr><tr><td><code>429</code></td><td>Rate limit exceeded. Carries <strong><code>Retry-After</code></strong> — see <a href="/mrecEO40m5D6bt7Pq5pE/reference/rate-limits.md">Rate Limits</a>.</td></tr><tr><td><code>502</code></td><td>The scanner ran but failed to produce a result.</td></tr><tr><td><code>503</code></td><td>Scanner temporarily unavailable, or scan capacity is saturated. A saturated response carries a <strong><code>Retry-After</code></strong> header giving the seconds to wait; a scanner-down response does not. Back off on the header where it is present.</td></tr></tbody></table>

## Worked example

See this as part of securing your AI coding agents end to end:

{% content-ref url="/pages/IBFvawl27EPDOZqk2Tar" %}
[Secure AI Coding Agents](/mrecEO40m5D6bt7Pq5pE/solutions-and-use-cases/secure-your-ai-coding-agents.md)
{% endcontent-ref %}

## Related

* [AI Supply Chain (Agent Files)](/mrecEO40m5D6bt7Pq5pE/findings/agentic-supply-chain-agent-files.md) — the continuous in-platform inventory and scoring.
* [CLI Command Reference](/mrecEO40m5D6bt7Pq5pE/reference/cli-command-reference.md) — `scan-agent-file` and the `ci` agent-files check, the command-line wrappers for this endpoint.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.heeler.com/mrecEO40m5D6bt7Pq5pE/reference/agent-files-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
