Supported Document Types

  • PDF (native text and scanned/image-based)
  • Word documents (.docx, .doc)
  • Scanned images (JPEG, PNG, TIFF) via OCR
  • Excel spreadsheets (.xlsx) for tabular extraction
  • Plain text and Markdown

Agent Configuration

# agents/doc-agent.yaml
name: doc-agent
model: gpt-4o
temperature: 0.0
tools:
  - pdf_reader
  - docx_reader
  - ocr_tool
  - file_writer
system: |
  You extract structured data from documents.
  Always return JSON unless asked otherwise.
  Normalise dates to ISO 8601 (YYYY-MM-DD).
  Normalise currency amounts to floats with 2 decimal places.
  Flag any field you are not confident about with a "confidence": "low" marker.

Invoice Data Extraction

import json, pathlib
from openclaw import Agent

agent = Agent.from_config("agents/doc-agent.yaml")

def extract_invoice(pdf_path: str) -> dict:
    result = agent.run(
        f"Read the invoice at '{pdf_path}' and extract:\n"
        "- invoice_number\n- invoice_date (ISO 8601)\n"
        "- vendor_name\n- vendor_vat\n- line_items (list of {description, qty, unit_price})\n"
        "- subtotal\n- tax_amount\n- total\n- currency\n"
        "Return ONLY valid JSON."
    )
    return json.loads(result)

invoice = extract_invoice("docs/invoice-2024-001.pdf")
print(f"Total: {invoice['currency']} {invoice['total']}")

OCR Processing for Scanned Documents

def process_scanned(image_path: str, doc_type: str = "auto") -> dict:
    """Process a scanned document image using OCR + AI extraction."""
    result = agent.run(
        f"OCR the image at '{image_path}', then extract all key-value fields. "
        f"Document type hint: {doc_type}. "
        "Correct common OCR errors (e.g., '0' vs 'O', '1' vs 'l'). "
        "Return structured JSON with a 'raw_ocr_text' field included."
    )
    return json.loads(result)

Document Classification

DOCUMENT_CATEGORIES = [
    "invoice", "contract", "receipt", "report",
    "form", "letter", "id_document", "other"
]

def classify_document(path: str) -> str:
    result = agent.run(
        f"Classify the document at '{path}' into one of: "
        f"{', '.join(DOCUMENT_CATEGORIES)}. "
        "Return ONLY the category name as a single word."
    )
    category = result.strip().lower()
    return category if category in DOCUMENT_CATEGORIES else "other"

PII Detection and Redaction

GDPR / CCPA: Always redact PII before storing documents in logs or third-party systems. The agent can detect and replace PII in bulk.
def redact_pii(text: str) -> str:
    """Detect and redact PII from document text."""
    result = agent.run(
        "Redact all PII from the following text. "
        "Replace names with [NAME], emails with [EMAIL], "
        "phone numbers with [PHONE], SSN/tax IDs with [TAX_ID], "
        "dates of birth with [DOB], and addresses with [ADDRESS].\n\n"
        f"TEXT:\n{text}"
    )
    return result

def batch_redact(input_dir: str, output_dir: str) -> int:
    input_path = pathlib.Path(input_dir)
    output_path = pathlib.Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)
    count = 0
    for txt_file in input_path.glob("*.txt"):
        original = txt_file.read_text(encoding="utf-8")
        redacted = redact_pii(original)
        (output_path / txt_file.name).write_text(redacted, encoding="utf-8")
        count += 1
    return count

Document Routing by Content

ROUTING_MAP = {
    "invoice":   "accounts-payable@company.com",
    "contract":  "legal@company.com",
    "report":    "management@company.com",
    "id_document": "hr@company.com",
}

def route_document(path: str) -> str:
    category = classify_document(path)
    destination = ROUTING_MAP.get(category, "general@company.com")

        

Frequently Asked Questions

Which document formats can OpenClaw agents process?

PDF (PyPDF2, pdfplumber, or PyMuPDF for text extraction; Camelot for tables), DOCX (python-docx), TXT/MD (direct read), Images (pytesseract OCR for PNG/JPG), HTML (BeautifulSoup), CSV/Excel (pandas). For scanned PDFs, use OCR (Tesseract or cloud OCR APIs like Google Vision). Avoid proprietary formats without libraries (e.g., Apple Pages) unless you can export to DOCX first.

How accurate is document classification for routing?

With a well-tuned LLM prompt, classification accuracy is ~90–95% for clear document types (invoices vs. contracts vs. reports). Accuracy drops for ambiguous or hybrid documents (e.g., "proposal with embedded contract terms"). Use confidence thresholds: if the LLM's confidence is below 80%, route to a human reviewer instead of auto-classifying. Provide a few-shot examples in the prompt ("An invoice contains line items, totals, and vendor info") to improve accuracy.

Can the agent extract structured data from unstructured documents?

Yes. Use prompt engineering with JSON mode: “Extract invoice number, date, total, and vendor from this text. Return as JSON.” For higher accuracy, use form recognizers: Azure Form Recognizer, AWS Textract, or Google Document AI. These services are trained on millions of documents and outperform general LLM extraction for standardized forms (invoices, receipts, tax forms). LLMs work best for semi-structured or entirely custom document layouts.

How do I handle sensitive documents securely?

Enable encryption at rest for document storage (AES-256), use TLS for transit, and restrict file access with IAM policies (least-privilege principle). For PII-heavy documents (medical records, financial statements), consider on-premise processing rather than cloud APIs to avoid data exfiltration. Redact sensitive fields before logging or passing to LLMs: replace SSNs, credit card numbers, etc., with placeholders. Audit all document access with timestamps and user IDs.

# In a real system, trigger your email/ticketing API here return f"Routed '{pathlib.Path(path).name}' ({category}) → {destination}"