Skip to content

Planning and selection

plan() is the local-only half of docgate. It does not invoke a provider, perform a network request, or access credentials. Use it to inspect intended work before execution.

import docgate

plan = docgate.plan(
    "bundle.pdf",
    need="degree certificate",
    selection="top_k",
    max_paid_pages=2,
)

print(plan.explain())
print(plan.candidate_pages)
print(plan.estimated_cost)  # Decimal('0') in the current planner

What the plan contains

DocPlan describes the detected format, page count, text-layer coverage, candidate pages, page-level instructions, local page signals, and a bounded peak-memory estimate. Each PagePlan identifies an engine, reason, possible render pixel limit, and whether the page will be read.

For PDFs, local signals include whether embedded text exists, character count, image count and pixel area, declared page dimensions, keyword hits, and a deterministic relevance score. For local document formats, signals come from the extracted text.

Selection policies

Policy Reads Use it when
all (default) Every logical page Completeness matters more than cost.
candidates Pages with local keyword evidence from need Text-layer evidence can identify relevant pages.
top_k The highest-ranked max_paid_pages pages You need a strict cap on selection.

Candidates are pages with one or more case-insensitive terms from need in local text. Ranking is deterministic: relevance, then image pixel area, then page number. This is a local signal, not semantic search; an image-only page may have no keyword evidence.

top_k requires max_paid_pages. With all or candidates, max_paid_pages limits only non-text-layer work; usable text-layer pages still remain eligible for free local extraction.

Pages excluded by a selection policy are included in the eventual receipt as UnknownReason.SKIPPED_BY_PLAN. They are not silently discarded.

Choose an initial engine

For a PDF page without usable embedded text, the planner defaults to Engine.OCR. You can label such pages with a different preferred engine in the plan:

from docgate import Engine, plan

document_plan = plan("scan.pdf", prefer=Engine.VISION)

Provider order during execution still determines the actual fallback ladder.