# File search

Search across files you have attached to the agent and return matching lines with context.

## Overview

`file_search` builds a line-level index of every file attached to the tool and exposes a single function the LLM can call with a query. Each hit comes back with the filename, line number, snippet, and score — so the model can quote it accurately or follow up with a more specific search.

This is **not** a vector store. It runs keyword + fuzzy matching in-process, which keeps latency low (no embedding round-trip) and makes it easy to reason about why a result was returned. Good for: briefs, transcripts, CSVs, source code, runbooks, logs. Not great for: large knowledge bases, semantic Q&A across thousands of docs — use the RAG node for that.

## Attaching files

Two ways to attach a file:

1. **In the tool modal** — drag-and-drop or click to browse. Files are uploaded to your account via `/api/v1/files/upload` and pinned to the tool definition.
2. **In the workflow run** — files passed in by a `file_picker` trigger or a previous node land on the run context and are searchable by the agent at runtime.

Supported text-ish extensions: `.txt`, `.md`, `.csv`, `.json`, `.log`, `.py`, `.js`, `.ts`, `.tsx`, `.jsx`, `.html`, `.xml`, `.yaml`, `.yml`, plus best-effort PDF extraction (first 20 pages). Files larger than ~200 KB are truncated; binary formats other than PDF are skipped.

## Configuration

| Field | Values | Notes |
| --- | --- | --- |
| Files | List of uploaded files | Attach any number; each is re-indexed on the first call per run. |
| Match mode | `keyword`, `fuzzy`, `both` | Default `both`. See below. |

**Modes**

- `keyword` — case-insensitive substring match. Strictest, fastest, zero false positives.
- `fuzzy` — `difflib` similarity ratio (threshold 0.55). Catches typos and near-matches.
- `both` — run both, merge, rank by combined score. Recommended default.

The LLM may also override the mode per-call by passing `mode` in its arguments. `top_k` is capped at 25 (default 5).

## Example

Tool attached: `q3-briefs.md`, `competitor-notes.txt`.

User turn: *"Did we say anything about Acme's new pricing?"*

The model issues:

```json
{ "query": "Acme pricing", "top_k": 5, "mode": "both" }
```

Response fed back to the model:

```json
{
  "query": "Acme pricing",
  "mode": "both",
  "matches": [
    {
      "file": "competitor-notes.txt",
      "line_number": 42,
      "snippet": "Acme moved to seat-based pricing on Oct 14, $29/seat/mo.",
      "score": 2.84,
      "keyword_hits": 1,
      "fuzzy_ratio": 0.84
    },
    { "file": "q3-briefs.md", "line_number": 117, "snippet": "...", "score": 2.12 }
  ]
}
```

The model then writes a one-line answer quoting the snippet.

## Best practices

- **Name files for retrieval.** Filenames appear in the LLM's tool output. `pricing-2026-q1.md` is much easier for the model to cite than `doc1.md`.
- **Keep snippets short.** Each line in your file becomes one indexable unit. Wrap long paragraphs at sentence boundaries so the snippet returned to the LLM is self-contained.
- **Cap `top_k` in the prompt.** The default is 5, max is 25. Tell the model *"call file_search with top_k=3"* if you want shorter context.

## Gotchas

- PDFs only extract their first 20 pages. Split long PDFs before uploading.
- DOCX is not supported in v1 — convert to PDF or MD first.
- The index is rebuilt on the first call per execution, then cached for the rest of the run. Adding a file mid-run won't be visible until the next execution.
- If no files match the configured paths, the tool returns `{"matches": [], "message": "No indexable files attached..."}` — the model will usually apologize rather than search again.

---

*Source: https://agentbuilder.systalink.sn/docs/tool-file-search — human documentation.*
*Other language: [/docs-md/fr/tool-file-search.md](/docs-md/fr/tool-file-search.md).*
*Machine-readable index: [/llms.txt](/llms.txt).*
