Read any common document/data file — PDF, Word (.docx), Excel (.xlsx/.xls), PowerPoint (.pptx), images (OCR), CSV/TSV, plain text, JSON/YAML/TOML, HTML/XML, and most source-code files. Use the `read_document` tool.
60
71%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Fix and improve this skill with Tessl
tessl review fix ./agent/src/skills/doc-reader/SKILL.mdReturn extracted text from any supported file in a single unified JSON envelope. The tool dispatches by file extension — you always call the same tool regardless of format.
| Category | Extensions | Notes |
|---|---|---|
.pdf | Text pages extracted in ms; scanned/image pages fall back to OCR | |
| Word | .docx | Paragraphs + table cells |
| Excel | .xlsx, .xls | All sheets, first 100 rows per sheet as preview |
| PowerPoint | .pptx | Slide text content |
| Images | .png/.jpg/.jpeg/.gif/.bmp/.webp/.tiff | OCR only |
| CSV / TSV | .csv, .tsv | Raw text with encoding fallback |
| Plain text | .txt/.md/.log/.rst | Encoding fallback |
| Config | .json/.yaml/.yml/.toml/.ini/.cfg/.env | Raw text |
| Markup | .html/.htm/.xml | Raw text (no HTML stripping) |
| Source code | .py/.js/.ts/.tsx/.go/.rs/.java/.cpp/.c/.sql/.sh/... | Raw text |
| Unknown extension | anything else | Best-effort read as UTF-8/GBK text |
Blocked (rejected at /upload): executables (.exe/.dll/.so/...) and
archives (.zip/.tar/...). Ask the user to unpack archives locally first.
Always call the tool directly — do not run Python from bash.
read_document(file_path="uploads/paper.pdf")
read_document(file_path="uploads/annual_report.pdf", pages="1-10")
read_document(file_path="uploads/contract.docx")
read_document(file_path="uploads/sales.xlsx")
read_document(file_path="uploads/deck.pptx")
read_document(file_path="uploads/chart.png") # image → OCR
read_document(file_path="uploads/config.yaml")
read_document(file_path="uploads/notes.md")The pages parameter only applies to PDF; other formats ignore it.
All formats share this shape:
{
"status": "ok",
"file": "paper.pdf",
"format": "pdf",
"char_count": 52000,
"truncated": true,
"text": "..."
}Format-specific extra fields:
| Format | Extra keys |
|---|---|
pdf | total_pages, pages_read, ocr_pages, ocr_engine, ocr_quality, skipped_pages |
docx | paragraphs, tables |
excel | sheets (array of {name, rows, cols}) |
pptx | slides |
text | encoding, size |
Content longer than 15000 chars is truncated; for PDFs use the pages
parameter to read slices.
1. read_document(file_path="paper.pdf") → full text
2. Extract abstract, methodology, conclusion → summarize1. read_document(file_path="contract.docx") → paragraphs + tables
2. Flag key clauses (termination, liability, payment, IP)1. read_document(file_path="sales.xlsx") → all sheet previews
2. If user wants trade journal analysis specifically, pivot to
`analyze_trade_journal` tool instead (see trade-journal skill).1. read_document(file_path="scan.png") → OCR text
2. If OCR returns empty, tell the user; don't fabricate.The read_document tool automatically uses OCR for PDF pages with insufficient extractable text.
Use min_text_per_page to control when OCR is triggered (default: 50 characters):
read_document("scanned_report.pdf", min_text_per_page=10) # More aggressive OCR
read_document("mixed_pdf.pdf", min_text_per_page=100) # Less aggressive OCRTwo OCR engines are built in — no extra packages needed beyond the engine SDK:
| Engine | Type | Requires | Install |
|---|---|---|---|
rapid | Local (offline) | rapidocr_onnxruntime | pip install rapidocr_onnxruntime |
llm-vision | Cloud | A vision-capable LLM model + API key | No extra install — uses your existing LLM provider config |
The llm-vision engine works with any OpenAI-compatible vision model (GPT-4o, Qwen-VL, Gemini, Claude, GLM-4V, etc.). It reuses your existing LANGCHAIN_PROVIDER / LANGCHAIN_MODEL_NAME / API key configuration — no separate provider mapping needed. If you explicitly set VIBE_TRADING_OCR_ENGINE=llm-vision, your model choice is trusted; a real API error from the provider is clearer feedback than a heuristic guess.
To override the model used for OCR (without changing your agent's main model):
VIBE_TRADING_OCR_LLM_MODEL=qwen3.7-plusSet VIBE_TRADING_OCR_ENGINE to select the engine:
auto (default): use local engines only, never cloud (privacy: document pages never leave the machine)rapid: force RapidOCR (local, ONNX)llm-vision: force LLM vision OCR (cloud — pages are sent to your configured LLM provider)none: disable OCR entirelyPDF responses include OCR metadata:
ocr_engine: name of the OCR engine used (e.g. "rapid", "llm-vision") or nullocr_pages: number of pages processed via OCRskipped_pages: number of pages skipped (no OCR engine available)ocr_quality: object with quality_flag (good/degraded/no_ocr_engine/no_ocr_needed), ocr_pages, and text_density (chars per page)text
with a note field — tell the user to install rapidocr-onnxruntime or
set VIBE_TRADING_OCR_ENGINE=llm-vision with a vision-capable model.analyze_trade_journal instead.8643fcd
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.