> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eigenpal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Search Files

> Investigate a ZIP archive with a question and return an answer plus file citations. Read-only: the step opens files in the archive and never writes back. ZIP is the only accepted format in this version. Optionally scope the search to a folder prefix and cap how many files and investigation turns may run.

`ai.search-files`: Investigate a ZIP archive with a question and return an answer plus file citations. Read-only: the step opens files in the archive and never writes back. ZIP is the only accepted format in this version. Optionally scope the search to a folder prefix and cap how many files and investigation turns may run.

Use `ai.search-files` when a run already has a ZIP bundle and you need a cited
answer from the files inside it — for example “which contracts mention
assignment?” or “is there a signed amendment in this packet?”. The step is an
investigation primitive, not an extractor: it does not return structured
fields from a schema, and it does not modify the archive.

Point `archive` at a workflow file input (`{ "$fileId": "file_..." }`) or a
previous step’s file output. Nested ZIP members stay opaque until you extract
them and pass the extract output into another search or list step. Encrypted
ZIP entries are rejected. See [Upload files](/guides/upload-files) for hosted
multipart, on-prem, headless, and Agent sandbox limits.

Git-backed Agents do **not** run this step. ZIP attachments in a sandbox are
inspected with filesystem tools, not `ai.search-files`.

## Citations and grounding

Treat the three outputs as different kinds of evidence:

* **Inspected-path guarantee.** `citations[].path` is always a file the step
  actually opened. It is taken from `filesInspected`. The step never cites a
  path it did not read.
* **Excerpts are copies.** When `citations[].excerpt` is present, it is a
  contiguous substring copied from the inspected file text. Invented or
  paraphrased excerpts are dropped; the citation then keeps the path only.
* **The answer is LLM-generated.** Citations constrain which files and excerpts
  may be returned. They do not prove every sentence in `answer`.

The step may return an answer with no citations only when it did not open any
files and the answer comes from archive listing metadata (paths and sizes).
After any successful file read, the step requires at least one citation to an
inspected file.

ZIP-only. Encrypted entries are rejected. At most **10,000** central-directory
entries. Reads share the same per-entry (**64 MiB**), per-reader (**512 MiB**),
and process-wide concurrent inflation (**512 MiB**) budgets as archive extract.
Nested ZIP members stay opaque until you extract them and pass that file into
another search. Hosted vs headless vs Agent sandbox: [Upload files](/guides/upload-files).

Downstream steps can read:

```yaml theme={null}
# {{ steps.search_files.output.answer }}
# {{ steps.search_files.output.citations }}
# {{ steps.search_files.output.filesInspected }}
```

```yaml theme={null}
inputs:
  - name: bundle
    type: file

steps:
  - name: search_files
    type: ai.search-files
    with:
      archive: "{{ input.bundle }}"
      query: "Which contracts mention assignment of receivables?"
      root: contracts/
```

## Configuration

Configuration goes inside the step's `with:` block.

<ParamField path="archive" type="string" required>
  Template expression or file reference for the ZIP archive to inspect. ZIP is the only accepted format in this version.
</ParamField>

<ParamField path="query" type="string" required>
  Natural-language question to answer from files inside the archive.
</ParamField>

<ParamField path="root" type="string">
  Optional folder prefix inside the archive. When set, only files under this path are in scope.
</ParamField>

<ParamField path="provider" type="string">
  Provider ID from eigenpal.config.yaml. Falls back to the tenant default LLM provider when omitted.
</ParamField>

<ParamField path="model" type="string">
  Model override (advanced).
</ParamField>

<ParamField path="reasoningEffort" type="&#x22;none&#x22; | &#x22;minimal&#x22; | &#x22;low&#x22; | &#x22;medium&#x22; | &#x22;high&#x22; | &#x22;xhigh&#x22; | &#x22;max&#x22;">
  Reasoning effort for models that support it. Omit to use the selected model's default.
</ParamField>

<ParamField path="maxIterations" type="integer" default="12">
  Maximum investigation turns. Default 12, capped at 50.
</ParamField>

<ParamField path="maxFiles" type="integer" default="50">
  Maximum files the step may open. Default 50, capped at 200.
</ParamField>

## Output

<ResponseField path="answer" type="string" required>
  The investigation answer. Citations point at inspected files; the answer text itself is model-generated.
</ResponseField>

<ResponseField path="citations" type="array<object>" required>
  Citations to files the step inspected. Excerpts, when present, are copied from inspected text.

  <Expandable title="citations properties">
    <ResponseField path="path" type="string" required>
      Archive-relative path of a file the step inspected and cited.
    </ResponseField>

    <ResponseField path="excerpt" type="string">
      Optional excerpt copied from the inspected file text. Omitted when no verbatim excerpt was supplied.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField path="filesInspected" type="array<string>" required>
  Archive-relative paths of files the step opened during investigation.
</ResponseField>
