Attach PDFs, images, audio recordings, Office documents, spreadsheets, slides, and text files to any enrichment, schema generation, sample generation, AI schema edit, or playground request. Files reach the model either as native bytes (for PDF-, vision-, and audio-capable models) or as server-extracted text inlined into the prompt — no manual OCR, transcription, conversion, or chunking required.
Each supported MIME type has an admin-configured delivery mode. The mode determines how the file reaches the model.
The original bytes are passed to the model as BinaryContent. The model reads the file directly — no server-side preprocessing.
Requires a model with the matching capability flag (supports_pdf_input for PDFs,supports_vision for images,supports_audio_input for audio). The model picker is automatically filtered to only show compatible models.
A server-side extractor runs once at upload time and caches the resulting text. On every subsequent LLM call the cached text is inlined into the user prompt.
No model capability required — works with every model. Plain text and Markdown skip the extractor and decode the raw bytes directly.
19 formats ship enabled by default. System administrators can flip any format between binary andinline_text mode, change its label, or disable it entirely from Model Management → Document policies.
| Format | Extensions | Default mode | Capability / extractor |
|---|---|---|---|
| PDF document | binary | supports_pdf_input | |
| PNG image | .png | binary | supports_vision |
| JPEG image | .jpg, .jpeg | binary | supports_vision |
| MP3 audio | .mp3 | binary | supports_audio_input |
| WAV audio | .wav | binary | supports_audio_input |
| M4A audio | .m4a | binary | supports_audio_input |
| OGG audio | .ogg, .oga | binary | supports_audio_input |
| FLAC audio | .flac | binary | supports_audio_input |
| Plain text | .txt | inline_text | raw decode |
| Markdown | .md, .markdown | inline_text | raw decode |
| Word (legacy .doc) | .doc | binary | docx2txt |
| Word (.docx) | .docx | binary | python-docx |
| OpenDocument text | .odt | binary | odfpy |
| Rich Text Format | .rtf | binary | striprtf |
| EPUB ebook | .epub | binary | ebooklib |
| HTML | .html, .htm | binary | beautifulsoup |
| CSV | .csv | binary | csv (stdlib) |
| Spreadsheet (.xlsx) | .xlsx | binary | openpyxl |
| Presentation (.pptx) | .pptx | binary | python-pptx |
When you attach more than one file to sample generation, the first question is what they are to each other — and getting that wrong silently produces a nonsense sample. So it is asked explicitly before anything is generated.
A contract and its amendment, a spec and its datasheet: the files are read together as one entity.
Ten invoices, ten CVs. The narrowest type covering all of them is derived, and the sample's values come from one chosen document rather than being blended across all ten — a sample stitched from ten sources describes nothing real.
Nine invoices and a holiday photo: rather than guessing, the job pauses and asks whether to exclude the odd one out. Files with nothing in common at all fail the job outright, with that as the reason.
The same pause-and-ask mechanism covers any other ambiguity the planner hits: the job stops, surfaces its questions, and resumes with your answers — in the app as a dialog, and over the API and MCP as an explicit answer step. A wrong assumption is cheaper to prevent than to discover in the generated schema.
One thing documents do not exempt you from: a schema generated from your files starts with the ambiguity check on, exactly like any other. That check asks whether a property name admits more than one meaning — a question about how the schema is worded, not about where this run's values came from. Your document settled the values once; the schema goes on to be reused against entities it never covered.
(organization_id, sha256).inline_text formats, the extractor runs at upload time and the resulting text is cached on the attachment row. Subsequent LLM calls reuse the cached text — no re-extraction cost. binary formats skip this step.DELETE /api/attachments/{id} — a handy post-enrichment cleanup step. Deletion is org-scoped and returns { success, id, filename }.Attachments can be uploaded and deleted programmatically, not just from the web UI: the n8n connector uploads via native multipart, the Make.com and MCP connectors upload via the base64 JSON route, and any client can use the REST API directly (DELETE /api/attachments/{id} for cleanup).
When you attach a binary file with a capability requirement (PDF, image, or audio), the model picker is filtered to only show models that declare that capability. If you attach multiple files with different requirements, only models satisfying all requirements appear.
The API enforces the same rule: pairing an incompatible model with a binary attachment returns 400 model_lacks_attachment_capability, so integrations that bypass the UI get a clear pre-flight error instead of a provider failure mid-job. Inline-text attachments never impose a requirement.
| Attached files | Eligible models |
|---|---|
| 1 PDF | supports_pdf_input |
| 1 PNG | supports_vision |
| 1 MP3 | supports_audio_input |
| 1 PDF + 1 PNG | supports_pdf_input AND supports_vision |
| 1 DOCX (binary mode, no capability) | All models — native byte support is assumed when no capability flag is set |
| 1 TXT or 1 MD (inline_text mode) | All models — text is inlined into the prompt |
Attachments are billed as input tokens reported by the model provider — Entity Enricher does not charge a separate per-document fee. The cost depends on the file type and the selected model.
Consume model-specific input tokens. Anthropic charges around 1700 tokens per PDF page; OpenAI prices vision inputs by tile count; audio-capable models meter audio input in proportion to its duration. Check your model's pricing card in Models & Pricing.
The extracted text consumes input tokens at the standard text rate. Large documents are capped at 500 KB of extracted text — longer content is truncated.