openreading

Every provider fails somewhere · route around it

The unified interface for every reading.

Every document-processing provider fails somewhere. Textract, Google Document AI, Reducto, PyMuPDF, Tesseract, all of them. openreading puts one API in front of the lot, and they all return the same result format. Switching, cascading or racing them is a config change.

Open-source today. Run it on your machine, with your choice of backend.

Apache 2.0 · open-source core Install from source 15 backend adapters
Works with
anthropic-claudeaws-textractazure-document-intelligencechunkrdoclinggoogle-document-aigoogle-geminimistral-ocrnuextractopen-ocrpulsepymupdfqwen-vlreductotesseract
Features ↓

Features

Available capabilities, plus one future direction.

Product

How it works, in order: the output, the grid, strategies, agents.

Product · The output

Your documents. Your backends. One response contract.

One response contract, with content that depends on the backend. Text, pages, tables, geometry, and confidence are optional; a field-only result can use typed_fields without pages. Available bounding boxes use page-relative [0,1] coordinates. A shared shape does not promise identical readings or complete content.

Response JSON · schema 0.3
Local captureBundled bank statement
{
  "schema_version": "0.3",
  "status": {"state": "succeeded"},
  "backend": {"id": "pymupdf", "type": "oss_library", "output_paradigm": ["block_tree"]},
  "document": {
    "page_count": 1,
    "pages": [
      {
        "page_number": 1,
        "width": 612,
        "height": 792,
        "unit": "pdf_point",
        "blocks": [
          {
            "type": "text",
            "native_type": "text",
            "text": "First National Bank",
            "reading_order": 0,
            "bbox": {"x": 0.0588, "y": 0.0265, "w": 0.2085, "h": 0.0243, "page": 1}
          }
        ]
      }
    ]
  },
  "usage": {"pages_processed": 1},
  "warnings": [{"code": "confidence_unavailable", "field": "block_confidence"}]
}

PyMuPDF and Tesseract read the same bank statement. Textract uses separate test data. Responses are shortened and numbers rounded for readability. Other providers show capabilities, not extraction results. These are static examples, not live calls or accuracy benchmarks.

openreading does not make any provider better at reading your document.

It gives you a shared contract, and makes failure handling an explicit strategy.

Product · The 3×3

Three operations. One shared contract.

Parse reads documents through a supported backend. Compare shows where outputs agree or differ. Strategy runs the backend order and quality checks you specify. And each feature works for three audiences: a human at a terminal, a program, or an agent.

CLI a human at a terminal API Python · HTTP, one contract Agent an LLM acting on typed output
parse supported inputs, one schema openreading parse on a file, a directory, a glob, or URLs run() / run_batch() · POST /v1/parse, /v1/batch uses the CLI or API; inspects status.state and warnings[]
compare where readings differ openreading compare on files, or on two folder runs compare() · POST /v1/compare typed verdicts, built to be branched on
strategy the decision, encoded parse --strategy + validate / plan / explain / replay / calibrate run(path, strategy="x") · backend.id: "strategy:x" for HTTP parse requests inspect attempts and decisions with explain; replay recorded decisions offline

The CLI, Python API, and your HTTP server share the vendored JSON Schemas. Agents can use those interfaces today. Native MCP tools and triage are not shipped.

Product · Strategies

Failure handling you write once, in YAML.

A strategy is a named plan for trying backends and checking their results. For example, start with a PDF text parser, then run OCR when the quality check rejects its output.

openreading.yaml · local backends
version: 1

policy:
  backends: [pymupdf, tesseract]

strategies:
  scan_aware:
    try: [pymupdf, tesseract]
    escalate_when: looks_bad
    max_time: "2m"

A gate is a check that accepts a result or moves to the next backend. Here, looks_bad checks signals such as garbled text and mostly empty pages. It does not guarantee that extracted values are correct.

Install the Tesseract system binary before using this example. Validate the file with openreading strategy validate, then run openreading parse examples/1040-1988.pdf --strategy scan_aware. Follow the local-first tutorial ↗ for setup, traces, and replay.

Product · Agents

Typed results your agent can inspect.

An agent uses the same CLI, Python API, or HTTP server as your application. openreading help serves the manual directly from the code, including examples and exit codes.

Status appears in status.state, warnings carry codes, and comparison reports expose headline.verdict: equivalent, divergent, or mixed. A strategy trace records attempts and decisions for inspection.

Native openreading mcp tools and triage are not shipped. Today, start with the CLI help chapter ↗ and CLI guide.

Product · Intent · Not shipped

Intent is a future direction, not a shipped feature.

The proposed intent layer would let you identify which extracted fields matter to your task. For example, you could ask for closer checking of an invoice total than its mailing address.

That layer is not available today. The OSS engine provides the parsing, comparison, and strategy mechanisms underneath it. Use explicit backends and quality checks you can inspect.

Ways to run it

One open-source engine. Use the CLI, Python library, or your own HTTP server.

Open-source today. Run it your way.

Open-source today. Run it your way.

01 · CLI

Run a command.

Parse a file, process a folder, compare saved outputs, or run a named strategy. The CLI returns structured JSON you can save and inspect.

Available in core

02 · PYTHON

Call the library.

Use openreading.run, route, compare, and run_batch in your application. Bring your own documents and backend configuration.

Available in core

03 · HTTP

Start your server.

openreading serve starts an HTTP process on your machine. Your application calls the parse, batch, route, comparison, and job endpoints.

Available in core

LATER · COMMERCIAL

Commercial offerings come later.

Hosted processing, managed deployments, and account-based products are not available. The current release is the open-source engine you operate yourself.

Not available

Core does not bundle a web UI or send documents through OpenReading infrastructure. A hosted backend is a vendor API, such as Textract, called with your credentials. Local backends run in your environment.

Get started

Start with a bundled example and a local backend. No provider key required.

Get started · CLI & Python

Install from source. Parse your first document.

Use Git and uv to install the current checkout. PyMuPDF reads the bundled example locally; you do not need a provider account.

shell · from a fresh directory
git clone https://github.com/openreading-ai/openreading-core
cd openreading-core
uv sync --all-extras --dev
uv run openreading backends
uv run openreading parse examples/john_smith_1000_2026_01.pdf --backend pymupdf > parsed.json
uv run openreading compare parsed.json parsed.json --format diffs
python · inside the same environment
import openreading

doc = openreading.run(
    "examples/john_smith_1000_2026_01.pdf",
    backend="pymupdf",
)
print(doc["status"]["state"])
# succeeded

The comparison above checks a saved result against itself without another backend call. Compare two different readings ↗ to compare different backends, add OCR, and build a strategy. Tesseract requires a separate system binary; hosted backends require your vendor credentials.

For an HTTP interface, run uv run openreading serve yourself. Core does not include serve-ui, managed hosting, or a commercial account.

Reference

Everything in one place, for people and for the LLM helping them.

Reference

The guide is your way in. The code is the reference.

Status

What is ready, and what is not. Never blurred.

Status · OSS release

Available in core. Clearly separate from what comes later.

FeatureStatus
Parse supported documents into a shared response schemaAvailable
Batch files, folders, and globsAvailable
Compare saved outputs or run named backends for comparisonAvailable
Strategies: cascade, race, explain, replay, and calibrateAvailable
Local backends and adapters for vendor APIsAvailable
CLI, Python API, and an HTTP server you runAvailable
Code-owned guides and the guided OSS tutorialAvailable
Execution ledger, resume, and benchmark harnessAvailable
Native MCP tools and triageNot shipped
Intent-driven extractionNot shipped
Commercial hosting, managed deployments, and account-based productsNot shipped

Install the current core checkout from source. Backend availability depends on its dependencies, credentials, and supported formats. openreading backends reports local setup; a configured backend is not proof that its vendor accepted your key.

FAQ

The questions everyone asks, answered the way they get asked.

FAQ

Straight answers to the usual questions.

What do I actually get if I just install it?

The CLI, Python library, and an HTTP server you start with openreading serve, plus backend adapters, strategies, comparison, and batch processing. Install the dependencies and configure the backends you want to use. A web UI is not bundled. Install and check core ↗

It is not a client for a service of ours. It calls the providers directly and nothing routes through us. What it leaves out is what only matters when someone else runs it for you: user accounts, provisioned provider keys, uptime and administration.

Are my documents going through your servers?

Not when you run it yourself. The package talks to the providers directly, and the local parsers do not leave your machine at all.

Commercial hosted editions are not available. If you choose a vendor API, that vendor receives your document directly. Review its terms and configure your own credentials. Bring your own key ↗

Why not just call Reducto or Textract directly?

Do that, if you will only ever use one provider. The work shows up with provider two: converting a second output format, handling a second set of errors, a second async model, a second set of retries.

You still call the vendor directly through openreading, with your key and your account. You control where credentials are configured, such as environment variables or your local environment file. Core does not provision vendor accounts. Configure your backends ↗

This is a wrapper.

Yes. Adapters normalize available geometry to page-relative coordinates and keep original coordinates in bbox_native when supplied. Numeric block confidence uses [0,1], but scores from different backends are not interchangeable probabilities. Extracted-field confidence can also retain vendor strings.

Sync, polling, and supported webhook workflows use one Job state machine. Missing output stays absent, and warnings explain some limitations. Check the content you need: neither an empty warning list nor the experimental channel_provenance map proves completeness. Explore the response contract ↗

What happens when a provider changes their API?

The break lands in one connector, not in your code. Connectors are tested against recorded responses plus injected failures, and real API behaviour is checked in a separate keyed lane.

Adapter changes land in the open-source repository. Pin a revision for your application and run your own checks before upgrading. Find the reference guides ↗

Our data cannot leave our environment.

After installation, pymupdf and tesseract can read local files without a key or network call. docling and qwen-vl send documents to the endpoints you configure. Operate those endpoints inside your environment if your documents must stay there.

Core certifies nothing on your behalf. The default backend list is a routing preference, not an access-control boundary. Configure default routing ↗

We already have a parser.

Keep it. If it has an adapter, run compare against another backend over your own documents. Otherwise, convert its output to the response schema before comparing saved results. The report shows where readings differ, not which one is correct.

Agreement is not proof of correctness. Use labeled ground truth to measure accuracy; comparison alone shows differences. Read comparison findings ↗

Start with the open-source engine.

Parse the bundled example, inspect the result, and build a strategy you can explain. Commercial offerings will come later.

Your machine. Your backends. One shared contract.

Hosted waitlist

Join the waitlist for hosted OpenReading: durable execution, precise cost controls, and enterprise readiness. The open-source engine is available now.

Form not loading? Open it in a new tab.