Framework-neutral Python SDK for building LAREX Action processors.
Project description
LAREX Action SDK
This SDK is work in progress. The public API can still change before LAREX Actions and the SDK are considered stable.
Framework-neutral Python SDK for building LAREX Action processors with signed dispatch verification, typed payloads, and cooperative run cancellation.
The core package verifies LAREX dispatch requests, parses typed run/input payloads, sends heartbeats, downloads selected files, uploads result manifests, and helps processors acknowledge cancellation cleanly. FastAPI support is available as an optional convenience extra.
Installation
uv add "larex-action-sdk[fastapi]"
For framework-neutral usage only:
uv add larex-action-sdk
FastAPI Processor
import os
from larex_actions import ActionContext
from larex_actions.fastapi import create_larex_action_app
async def process(ctx: ActionContext) -> None:
action_input = await ctx.pull_input()
for page in action_input.pages:
async with ctx.step(f"Processing {page.name}", progress_percent=25):
await ctx.check_cancelled()
results = ctx.result_builder()
if page.xml:
xml_bytes = await ctx.download_bytes(page.xml[0])
results.add_xml_bytes(
page_id=page.id,
content=xml_bytes,
file_name=f"{page.name}-processed.xml",
)
await ctx.submit_page_results(page.id, results, f"Finished {page.name}")
await ctx.complete(message="Done")
app = create_larex_action_app(
processor_id="my-processor",
dispatch_secret=os.environ["LAREX_DISPATCH_HMAC_SECRET"],
handler=process,
max_concurrent_runs=1,
)
Incremental page submissions require LAREX to advertise
capabilities.incrementalPageResults. The SDK refuses the submission when an
older server does not advertise it. Existing processors can continue to call
await ctx.complete(results, "Done") once with a bulk result.
Custom File Results
LAREX servers that advertise capabilities.customFileResults accept arbitrary
durable files. Check the capability before doing expensive postprocessing and
add project-level bytes or paths to a result builder:
if not ctx.capabilities.custom_file_results:
raise RuntimeError("This LAREX server does not support custom file results")
results = ctx.result_builder()
results.add_file_bytes(
content=ner_jsonl,
file_name="named-entities.jsonl",
mime_type="application/x-ndjson",
)
results.add_file_path(
report_path,
file_name="report.txt",
mime_type="text/plain",
)
await ctx.complete(results, "Postprocessing complete")
Omit page_id for project-level files. Pass page_id=page.id when associating a
file with a page. Incremental page submissions require every file—including a
custom file—to carry the same page ID as the submission. The client raises
CustomFileResultsUnsupported before uploading if the server did not advertise
support.
max_concurrent_runs bounds simultaneous in-process handlers for CPU/GPU-heavy
processors. Additional signed dispatches remain accepted and wait for a slot.
/ready returns 503 while every slot is occupied; /health remains a liveness
endpoint. For crash-durable queuing, run the handler in an external worker system
instead of relying on FastAPI background tasks.
Result callbacks retry connection failures and transient HTTP responses (408,
429, 502, 503, and 504) automatically. Path-based files are reopened for
every attempt. The defaults are four attempts with exponential backoff and jitter;
processors can tune result_max_attempts, result_retry_backoff, and
result_retry_max_backoff on ActionClient or ActionClient.from_dispatch(...).
The FastAPI adapter always exposes /dispatch and /health. Set
LAREX_ACTION_ROUTE_PREFIXES to also expose prefixed routes when a reverse
proxy keeps an external path prefix:
LAREX_ACTION_ROUTE_PREFIXES=/kraken,/ocr
With that setting, the same processor also accepts /kraken/dispatch,
/kraken/health, /ocr/dispatch, and /ocr/health. LAREX must sign and call
the same path the processor receives; do not strip the prefix in the reverse
proxy before the request reaches the processor.
Target-Aware Runs
LAREX can dispatch page, region, and textline targeted runs. The SDK exposes the requested target on both dispatch and pulled input payloads:
payload_target = ctx.payload.target
action_input = await ctx.pull_input()
input_target = action_input.target
Processors still receive full page files according to the Action YAML inputs. Target metadata contains selected region/textline ids only. LAREX sends full page images/XML and lets processors resolve geometry from PAGE XML, including whether to crop, mask, pad, deskew, or process the full image.
Processors return normal PAGE XML via ResultBuilder.add_xml_bytes(...) or
add_xml_path(...). For region or textline targeted runs, LAREX imports only the
selected target scope from the returned PAGE XML.
Framework-Neutral Dispatch Verification
from larex_actions import DispatchVerifier
payload = DispatchVerifier(
processor_id="my-processor",
dispatch_secret=secret,
).verify(
method=request_method,
path_and_query=request_path_and_query,
headers=request_headers,
body=request_body,
)
You can then pass payload.model_dump(mode="json", by_alias=True) to your own
queue/worker system and use ActionClient.from_dispatch(payload) in async workers.
Cooperative Cancellation
LAREX cancellation is cooperative. The processor keeps polling the heartbeat
endpoint and LAREX responds with cancelRequested: true when the run should stop.
- Use
await ctx.check_cancelled()at safe interruption points. ctx.check_cancelled()performs a heartbeat request, so avoid calling it in a hot inner loop without pacing.await ctx.heartbeat(..., raise_on_cancel=True)also raisesActionCancelledwhen a cancellation is pending.await ctx.run_subprocess(...)polls for cancellation while a child process is running, sends a finalstatus="cancelled"heartbeat, and terminates the child process gracefully before escalating tokill.- Once cancellation has been requested, the SDK refuses result uploads and acknowledges cancellation instead.
Security
- Dispatch requests are verified with the
X-LAREX-Action-*HMAC headers. - Timestamps and nonces are checked to reduce replay risk.
- The FastAPI adapter rejects dispatch bodies larger than
max_dispatch_body_bytes. - Per-run bearer secrets and dispatch HMAC secrets are never included in model reprs.
- Processor YAML must still declare the inputs and outputs LAREX should expose or accept.
Development
uv sync --all-extras
uv run ruff format .
uv run ruff check .
uv run pyright
uv run pytest
uv build
Releases are published with PyPI Trusted Publishing from GitHub Actions. Release
candidate tags containing rc publish to TestPyPI; published GitHub releases
publish to PyPI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file larex_action_sdk-0.10.1.tar.gz.
File metadata
- Download URL: larex_action_sdk-0.10.1.tar.gz
- Upload date:
- Size: 39.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa07b09ad42b9064335d84c7a0a8be08cafc3fc45d4b4250585bbf3e06129fe8
|
|
| MD5 |
456f251d3eccdf723ce4b643d895ee0e
|
|
| BLAKE2b-256 |
28f6b859fbe3583344638715f349eccf740ac7aca72ba7109c743a6086b68ee3
|
Provenance
The following attestation bundles were made for larex_action_sdk-0.10.1.tar.gz:
Publisher:
publish.yml on OCR4all/larex-action-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
larex_action_sdk-0.10.1.tar.gz -
Subject digest:
fa07b09ad42b9064335d84c7a0a8be08cafc3fc45d4b4250585bbf3e06129fe8 - Sigstore transparency entry: 2218178611
- Sigstore integration time:
-
Permalink:
OCR4all/larex-action-sdk@144726f899577b12031466d9fd65af2989a4bfd7 -
Branch / Tag:
refs/tags/v0.10.1 - Owner: https://github.com/OCR4all
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@144726f899577b12031466d9fd65af2989a4bfd7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file larex_action_sdk-0.10.1-py3-none-any.whl.
File metadata
- Download URL: larex_action_sdk-0.10.1-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f92f4ed175ebcbf5886f4d9251e5546b5aa22eafa74a09432e103fc9f8ff427d
|
|
| MD5 |
cdb62138f35b8e67a1e376997972dad0
|
|
| BLAKE2b-256 |
5a80ea14b195418cad482f14b169aca7b37f70d60adeadc3e3efaf3fc7d95aaa
|
Provenance
The following attestation bundles were made for larex_action_sdk-0.10.1-py3-none-any.whl:
Publisher:
publish.yml on OCR4all/larex-action-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
larex_action_sdk-0.10.1-py3-none-any.whl -
Subject digest:
f92f4ed175ebcbf5886f4d9251e5546b5aa22eafa74a09432e103fc9f8ff427d - Sigstore transparency entry: 2218178635
- Sigstore integration time:
-
Permalink:
OCR4all/larex-action-sdk@144726f899577b12031466d9fd65af2989a4bfd7 -
Branch / Tag:
refs/tags/v0.10.1 - Owner: https://github.com/OCR4all
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@144726f899577b12031466d9fd65af2989a4bfd7 -
Trigger Event:
release
-
Statement type: