Docling-Serve Integration¶
Overview¶
docling-serve exposes the Docling conversion pipeline as a REST API. Docling Graph can delegate the document conversion step to such an instance instead of converting locally: the server performs OCR/layout analysis and returns the DoclingDocument, and the rest of the pipeline (chunking, LLM extraction, graph conversion, export) runs unchanged.
Why use it:
- No local conversion models — the client machine doesn't download or load Docling's OCR/layout/VLM model stack.
- Shared infrastructure — a GPU-backed docling-serve cluster can serve many lightweight docling-graph clients.
- Consistent conversions — every pipeline run converts documents with the same centrally managed service.
Scope: only conversion is remote. LLM extraction still uses whatever backend/inference you configured. The VLM extraction backend (backend="vlm") processes source documents directly and locally, so docling-serve has no effect there.
Configuration¶
Python API¶
from docling_graph import PipelineConfig
config = PipelineConfig(
source="document.pdf",
template="templates.BillingDocument",
# Convert on a remote docling-serve instance
docling_serve_url="http://localhost:5001",
docling_serve_api_key="my-key", # only if the server requires one
docling_serve_timeout=300, # per-document job deadline in seconds
# For deployments behind an auth proxy (e.g. bearer tokens) instead of
# X-Api-Key — sent on every request:
# docling_serve_headers={"Authorization": "Bearer <token>"},
)
config.run()
CLI¶
uv run docling-graph convert document.pdf \
--template "templates.BillingDocument" \
--docling-serve-url http://localhost:5001
config.yaml¶
Environment Variables¶
When no URL is set explicitly, Docling Graph falls back to environment variables — convenient for cluster deployments where every client should use the same instance:
export DOCLING_SERVE_URL="http://docling-serve.internal:5001"
export DOCLING_SERVE_API_KEY="my-key" # optional
export DOCLING_SERVE_HEADERS='{"Authorization": "Bearer <token>"}' # optional, JSON object
Precedence: CLI flag > config.yaml / PipelineConfig > environment variable. The API key and custom headers are never written to metadata.json.
How It Works¶
Docling Graph uses the official Docling service client (docling.service_client) and the server's asynchronous task API (requires docling-serve >= 1.0.0):
- Local files are uploaded (and URL sources submitted for the server to fetch itself) as an async conversion task.
- The client polls the task status over HTTP until the job finishes — no long-held connection, so load-balancer idle timeouts and the server's synchronous wait cap don't abort large documents. Transient errors (HTTP 500/502, and 429/503 with a Retry-After header) are retried automatically.
- The DoclingDocument JSON result (
to_formats: ["json"]) is fetched and parsed, and the pipeline continues exactly as with local conversion (includingchunks.json, DocLang export, and provenance).
The docling_config pipeline selection still applies and maps to the server-side pipeline:
docling_config |
docling-serve pipeline |
|---|---|
ocr (default) |
standard (server defaults: OCR + table structure) |
vision |
vlm |
Timeouts and Large Documents¶
docling_serve_timeout is the approximate deadline for one document's conversion job, from submission to terminal status. Conversion runs asynchronously on the server and the client polls until this deadline — server queue time counts toward it, so on a busy shared instance raise it accordingly. On timeout, the job may still be running server-side.
config = PipelineConfig(
source="500_page_report.pdf",
template="templates.Report",
docling_serve_url="http://localhost:5001",
docling_serve_timeout=1800, # 30 minutes
)
Connect/read timeouts and transient-error retries are handled automatically and bounded separately (an unreachable server fails after ~10 seconds, not the full deadline).
Trying It Locally¶
Run a local instance with the official container image:
Then point Docling Graph at it:
export DOCLING_SERVE_URL="http://localhost:5001"
uv run docling-graph convert document.pdf --template "templates.BillingDocument"
Troubleshooting¶
🐛 Failed to reach docling-serve¶
The instance is unreachable. Check the URL, network access, and that the service is running (curl <url>/health). For custom/corporate CAs, set SSL_CERT_FILE — the client's HTTP stack (httpx) does not read REQUESTS_CA_BUNDLE (Docling Graph bridges it automatically when only REQUESTS_CA_BUNDLE is set).
🐛 docling-serve returned HTTP 401/403¶
The server has authentication enabled. Provide the key via DOCLING_SERVE_API_KEY (or docling_serve_api_key); it is sent as the X-Api-Key header. Deployments behind an auth proxy (e.g. bearer tokens) can send arbitrary headers via DOCLING_SERVE_HEADERS (or docling_serve_headers) instead.
🐛 docling-serve returned HTTP 402 (usage limit exceeded)¶
The service's usage quota is exhausted (managed/SaaS deployments). The error details carry the current usage and limit.
🐛 docling-serve returned HTTP 404¶
If the URL is correct, the server may predate the v1 async task API — remote conversion requires docling-serve >= 1.0.0 (curl <url>/version).
🐛 conversion did not finish within ...s (job deadline)¶
Conversion (including server queue time) took longer than docling_serve_timeout. Raise the timeout, or check the server's queue/load — the job may still be running server-side.
🐛 Failed to parse DoclingDocument response¶
The client and server versions may disagree on the response schema — upgrade the older side (client: the docling package; server: docling-serve).
🐛 docling-serve returned HTTP 422¶
Docling Graph always requests in-body results (no presigned artifact storage). If a deployment mandates presigned/artifact-storage results and rejects in-body targets, conversion fails with a 422 — check the server's target configuration.
Next Steps¶
- Docling Settings - OCR vs Vision pipeline selection
- Configuration Basics - All configuration options
- Input Formats - Reusing pre-converted DoclingDocument JSON