API reference
This is the canonical reference for the public Python API. CI compares every function heading below with the installed callable signature; update this page in the same change as any public signature.
How-to: Guide. Integration contract for generated code: For agents.
Extraction
Extractor(schema, model=None, instructions=None, *, style='direct', agent=None, model_settings=None, timeout=None, instrument=False, retry_policy=None, max_input_bytes=None, url_timeout=None)
Reusable synchronous extraction session. Enter it with with; then call
extract(input_file, *, media_type=None) or
extract_with_usage(input_file, *, media_type=None). The agent, model provider
client, and URL-fetch client are constructed once and closed on context exit.
model accepts either a known model string or a configured
pydantic_ai.models.Model. style selects how the model inspects the input
(direct, search, or code; see Common arguments) and
applies to every call in the session; search and code sessions build their
harness agent and temporary workspace once on enter and remove both on exit.
As an advanced alternative, agent accepts a fully
configured Pydantic AI Agent; it is mutually exclusive with model, and its
output is revalidated against schema. Non-direct styles cannot be combined
with an injected agent.
AsyncExtractor(schema, model=None, instructions=None, *, style='direct', agent=None, model_settings=None, timeout=None, instrument=False, retry_policy=None, max_input_bytes=None, url_timeout=None)
Async session counterpart. Enter it with async with; then await extract or
extract_with_usage. It shares one async HTTP client and one agent across
calls, including concurrent calls made on the entering event loop. Close it
manually with aclose() only when a context manager is impractical.
RetryPolicy(max_retries=0, backoff=1.0, max_backoff=60.0)
Frozen session retry configuration. Only transient ModelError failures are
retried. The backoff and bounded provider Retry-After behavior match the
one-shot function arguments.
ExtractionStyle
direct (default) sends resolved media to the model in one shot. search and
code are text-only agentic styles powered by
Pydantic AI Harness. Pass the enum
(ExtractionStyle.SEARCH) or the string ("search"). Non-text inputs and a
missing harness extra fail before the model call.
extract(schema, model, input_file=None, instructions=None, *, style='direct', media_type=None, max_input_bytes=None, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
model also accepts an agent, and an agent that declares an
output_schema can be passed as schema instead — extract(invoices, "doc.pdf")
is the same call as extract(Invoice, invoices, "doc.pdf"). An agent that
resolves to one local model runs as a normal one-shot call using the agent’s
model, instructions, and style; an agent with subagents or a remote endpoint
runs as a swarm and its outputs are reduced. Omitting input_file
raises ValueError; the parameter is optional only so the agent form can shift
it left. The same applies to the three siblings below.
Extract one input synchronously and return an instance of schema.
extract_async(schema, model, input_file=None, instructions=None, *, style='direct', media_type=None, max_input_bytes=None, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Async counterpart to extract. It uses Agent.run and returns an instance of
schema.
extract_with_usage(schema, model, input_file=None, instructions=None, *, style='direct', media_type=None, max_input_bytes=None, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Extract one input synchronously and return (output, Usage). It has the same
retry behavior as extract; Usage describes the successful model call.
extract_with_usage_async(schema, model, input_file=None, instructions=None, *, style='direct', media_type=None, max_input_bytes=None, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Async counterpart to extract_with_usage; returns (output, Usage).
extract_many(schema, model, input_files, instructions=None, *, style='direct', media_type=None, max_input_bytes=None, max_concurrency=5, return_exceptions=False, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Run concurrent extractions from synchronous code. Results preserve input order.
When return_exceptions=True, per-item exceptions appear in the result list.
Do not call this function from a running event loop; use
extract_many_async instead.
extract_many_async(schema, model, input_files, instructions=None, *, style='direct', media_type=None, max_input_bytes=None, max_concurrency=5, return_exceptions=False, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Async counterpart to extract_many; it has the same arguments, result ordering,
and per-item retry behavior.
iter_extract_many_async(schema, model, input_files, instructions=None, *, style='direct', media_type=None, max_input_bytes=None, max_concurrency=5, return_exceptions=False, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Return an async iterator of (input_index, result) pairs in completion
order. Inputs are consumed lazily, at most max_concurrency items are
scheduled, and results are available before the complete batch finishes.
Simultaneous completions are yielded in input-index order.
This is the streaming counterpart to extract_many_async, which waits for every
item and returns a list in input order. Keep the original input_files
sequence (or a name on ExtractionInput) if you need to map input_index back
to a path.
With return_exceptions=False, the first failure cancels and awaits outstanding
work before being raised. With return_exceptions=True, item exceptions are
yielded in the result position and streaming continues.
async for index, result in iter_extract_many_async(
schema=PdfInfo,
model="openai:gpt-5",
input_files=paths,
return_exceptions=True,
max_concurrency=5,
):
if isinstance(result, Exception):
print(f"{index} failed: {result}")
else:
print(index, result.summary)
extract_many_with_results(schema, model, input_files, instructions=None, *, style='direct', media_type=None, max_input_bytes=None, max_concurrency=5, return_exceptions=False, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Run a batch and return per-item ExtractionResult objects
instead of bare schema instances. It has the same arguments, input ordering,
concurrency, and retry semantics as extract_many, and each result carries
token usage, attempt count, duration, model/media metadata, and a sanitized
source label. With return_exceptions=True, failed items appear as
Exception values in place. Use total_usage to
aggregate token usage across the returned results.
extract_many_with_results_async(schema, model, input_files, instructions=None, *, style='direct', media_type=None, max_input_bytes=None, max_concurrency=5, return_exceptions=False, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Async counterpart to extract_many_with_results; it has the same arguments,
result ordering, and per-item retry behavior.
total_usage(results)
Sum token usage across batch extraction results, for example the list returned
by extract_many_with_results or extract_many_with_results_async. Returns a
single Usage whose fields are the totals of the successful items.
Swarm
A swarm runs several agents over one input and reduces their outputs. The input is fetched and decoded once, so a swarm costs one load and N model calls. Each agent is told its position in the swarm so it works independently instead of assuming a peer covered a section.
Use a swarm when one pass under-recalls: a long document, a schema with many optional fields, or a job worth cross-checking with a second model. One document that one model handles well does not need one.
SwarmMember
SwarmMember(model, instructions=None, style=None) is one agent, where model
is a model identifier, a configured pydantic-ai Model, or a RemoteAgent. Its
instructions and style override the swarm-wide values, so a search reader
and a direct reader can share the same swarm. A bare model identifier or a
configured pydantic-ai Model is accepted anywhere a SwarmMember is.
SwarmResult
Returned by extract_swarm_with_results*. output is the reduced instance,
agents holds each agent’s ExtractionResult or the
exception it raised in agent order, usage sums the successful agents, and
reduce is the strategy that produced output.
resolve_swarm_members(agents, size=None)
Expand the agents argument into one SwarmMember per agent. A single agent
plus size fans it out size times (1..16); a list is used as-is and size
may not contradict its length. Defined agents are flattened first,
so a parent with subagents contributes one member per leaf.
extract_swarm(schema, agents, input_file, instructions=None, *, size=None, style='direct', reduce='merge', media_type=None, max_input_bytes=None, max_concurrency=None, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Run the agents concurrently over one input and return the reduced schema
instance. max_concurrency defaults to min(5, agents). Agent failures are
tolerated as long as one agent succeeds; if every agent fails, the first
failure is raised. Raises RuntimeError from a running event loop.
extract_swarm_async(schema, agents, input_file, instructions=None, *, size=None, style='direct', reduce='merge', media_type=None, max_input_bytes=None, max_concurrency=None, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0)
Async counterpart to extract_swarm.
extract_swarm_with_results(schema, agents, input_file, instructions=None, *, size=None, style='direct', reduce='merge', media_type=None, max_input_bytes=None, max_concurrency=None, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0, on_agent_start=None, on_agent=None)
Same run, returning a SwarmResult. on_agent_start(index,
total) and on_agent(index, total, result) report progress as agents start
and finish.
extract_swarm_with_results_async(schema, agents, input_file, instructions=None, *, size=None, style='direct', reduce='merge', media_type=None, max_input_bytes=None, max_concurrency=None, max_retries=0, retry_backoff=1.0, retry_max_backoff=60.0, on_agent_start=None, on_agent=None)
Async counterpart to extract_swarm_with_results.
Agents
An agent packages what a swarm member would otherwise repeat at every call
site — model, style, instructions, and output schema — so a caller imports a
specialist instead of re-specifying it. Agents compose: a parent with
subagents flattens into one swarm member per leaf, so an agent is accepted
anywhere agents is.
define_agent(description, *, model=None, style=None, instructions=None, output_schema=None, subagents=())
Define a local agent. description is required. model is optional only when
subagents is non-empty (a pure group). output_schema must be a
pydantic.BaseModel subclass. Returns a frozen DefinedAgent.
define_remote_agent(url, description, *, auth=None, headers=None, path='/extract', output_schema=None)
Define an agent served over HTTP. Returns a frozen RemoteAgent. url may be
a callable (sync or async) so a rotating deployment URL is resolved per
request; headers and auth likewise. See Remote agent
protocol.
flatten_agent(agent)
Expand one agent into the SwarmMember list it contributes: its own model
first (when it has one), then each subagent’s members, depth first.
resolve_output_schema(agent)
Return the agent’s output_schema, or raise ValueError naming the agent when
it declared none.
load_agent(spec)
Load one agent from a directory, a Python file, or a module:attribute path. A
DefinedAgent / RemoteAgent passes through unchanged. A file or module must
expose the agent as a module-level name (agent for files, the named attribute
for module:attribute).
load_agents(spec)
Load several agents from a comma-separated string or a sequence of specs.
load_agent_directory(directory)
Load an agent from a directory laid out as:
invoices/
agent.py # defines `agent = define_agent(...)`
instructions.md # used when the agent declared no instructions
subagents/
line_items.py # each defines `agent = ...`
totals/ # nested directories load recursively
Entries beginning with . or _ are skipped and subagents load in sorted
order. A directory with subagents but no agent.py becomes a group agent named
after the directory; a directory with exactly one subagent resolves to it.
Remote agent protocol
RemoteAgent posts to url + path with
{"schema": <JSON Schema>, "input": {"data": <base64>, "mediaType": <MIME>}, "instructions": ..., "style": ...}
and reads {"output": ..., "usage": {...}} — a bare object is treated as the
output, and {"error": "..."} (at any status) raises RemoteAgentError.
usage is accepted in either inputTokens or input_tokens spelling. HTTP
408/409/425/429/5xx and transport failures are retryable and honour
max_retries.
The agent URL goes through the same SSRF host allowlist as document URLs, so a
local agent server needs OPENEXTRACT_ALLOW_PRIVATE_URLS=1.
openextract.auth
Outbound auth header providers for define_remote_agent(auth=...). Each is
resolved per request, so a refreshed credential is picked up without redefining
the agent.
| Helper | Header |
|---|---|
bearer(token) |
Authorization: Bearer <token> |
basic((username, password)) |
Authorization: Basic <base64> |
vercel_oidc() |
Bearer token read from VERCEL_OIDC_TOKEN |
bearer and basic accept the value itself or a callable (sync or async)
returning it.
Swarm reduce
A swarm runs several agents over one input and folds their outputs into a
single result. The fold strategy is SwarmReduce; the reducers are public so a
caller can combine outputs it gathered itself.
SwarmReduce
merge (default) unions list fields and fills each scalar field from the first
agent that produced a value. vote keeps the most frequent non-empty value per
field, breaking ties toward the earlier agent; list fields have no majority, so
they fall back to merge. first returns the first successful agent’s output
untouched. Pass the enum (SwarmReduce.VOTE) or the string ("vote").
normalize_reduce(reduce='merge')
Return a valid SwarmReduce for an enum member or string, or raise
ValueError naming the allowed strategies.
reduce_outputs(values, reduce='merge')
Fold a sequence of same-schema Pydantic model instances into one instance.
merge and vote reduce the dumped payloads and re-validate the combined
value, so the return value always satisfies the schema; a combination that no
longer validates raises SchemaValidationError. An empty values raises
ValueError.
Choosing a batch API
| API | Returns | Order | When to use |
|---|---|---|---|
extract_many / extract_many_async |
list[T] (or exceptions in place) |
Input order | You want the full batch before continuing. |
iter_extract_many_async |
(input_index, result) as items finish |
Completion order | Large or generator inputs; start work before the last item completes. |
extract_many_with_results / _async |
list[ExtractionResult[T]] |
Input order | Per-item usage, attempts, duration, and sanitized source labels. |
extract_many and extract_many_with_results raise RuntimeError from a
running event loop; use the _async siblings or the iterator instead. See
examples/batch/stream_batch_extract.py
for a side-by-side run.
Input and result contracts
ExtractionInput
A frozen dataclass wrapping a single media source with optional per-item media metadata. Passing one to any extraction API (or mixing them into a batch) is equivalent to passing the raw source directly.
| Field | Type | Description |
|---|---|---|
source |
str \| os.PathLike[str] \| bytes \| BinaryIO |
Local path, HTTP(S) URL, Path, raw bytes, or binary file-like object. |
media_type |
str \| None |
Per-item MIME type. Required for bytes and file-like sources when no batch-wide override is supplied. |
name |
str \| None |
Optional safe source label recorded on ExtractionResult.source. |
Batch item media types resolve per item: an ExtractionInput.media_type wins
over the batch-wide media_type argument, which remains the fallback for raw
items.
ExtractionResult
A frozen, generic dataclass returned by extract_many_with_results*. It never
retains raw media, credentials, query strings, fragments, or provider
internals; source is sanitized.
| Field | Type | Description |
|---|---|---|
output |
T |
The validated schema instance. |
usage |
Usage |
Token usage from the successful model call. |
attempts |
int |
Model-call attempts including retries; always >= 1 on success. |
duration |
float |
Wall-clock seconds for the item, including retries. |
model |
str \| None |
Model identifier that produced the output, when known. |
media_type |
str \| None |
Media type requested for the item, when provided. |
source |
str \| None |
Sanitized source label; None for unnamed bytes/file-like inputs. |
warnings |
tuple[str, ...] |
Extensible diagnostics channel; currently always empty. |
Common arguments
| Argument | Type | Description |
|---|---|---|
schema |
type[BaseModel] |
Pydantic model class describing the desired output. |
model |
str \| Model |
pydantic-ai model identifier or configured model instance. |
input_file |
str \| os.PathLike[str] \| bytes \| BinaryIO \| ExtractionInput |
Local path, HTTP(S) URL, Path, bytes, binary file-like object, or ExtractionInput. |
instructions |
str \| None |
Optional model guidance. |
style |
ExtractionStyle \| str |
How the model inspects the input. direct (default) sends media in one shot. search gives the model sandboxed file tools (read/grep) against a text document. code lets the model write Python against a text document via Pydantic AI Harness. search needs pydantic-ai-harness; code needs pydantic-ai-harness[codemode]. |
media_type |
str \| None |
Required for bytes and file-like inputs without a per-item type; overrides inference for paths and URLs. Item-level ExtractionInput.media_type wins in batch calls. |
max_input_bytes |
int \| None |
Per-input byte cap; None uses OPENEXTRACT_MAX_INPUT_BYTES or the 50 MiB default. |
max_retries |
int |
Extra attempts after transient ModelError; defaults to 0. |
retry_backoff |
float |
Base seconds for exponential backoff with up to 25% jitter. |
retry_max_backoff |
float |
Maximum delay, including provider Retry-After; defaults to 60.0. |
Batch functions also accept:
| Argument | Type | Description |
|---|---|---|
input_files |
Iterable[str \| os.PathLike[str] \| bytes \| BinaryIO \| ExtractionInput] |
One input per extraction; items may carry their own media type. |
max_concurrency |
int |
Positive maximum number of in-flight extractions; defaults to 5. |
return_exceptions |
bool |
Return per-item exceptions in place instead of failing fast. |
Usage
Usage is a frozen dataclass returned by the two usage helpers.
| Field | Type | Description |
|---|---|---|
input_tokens |
int |
Prompt tokens consumed. |
output_tokens |
int |
Completion tokens consumed. |
total_tokens |
int |
Total reported tokens. |
Configuration
The Python library reads provider configuration from the existing process
environment and does not load .env files. The openextract CLI and bundled
examples load .env explicitly as an application-level convenience.
Session model_settings are passed directly to Pydantic AI using its typed
ModelSettings contract. timeout is an explicit shortcut for the model
request timeout and overrides a timeout entry in model_settings.
url_timeout separately controls URL input fetching. instrument=True enables
Pydantic AI instrumentation; an InstrumentationSettings instance provides
fine-grained control.
Extractor is bound to the thread that enters it and is not thread-safe.
AsyncExtractor is bound to one event loop; concurrent calls within that loop
are supported. Neither session can be reopened after it is closed.