caravan-rpc (Python)
Runtime SDK for the Caravan application-definition compiler.
Status: 0.1.1. Functional runtime with @wagon, provide, client, CARAVAN_RPC_PEERS env-var dispatch (inproc / HTTP / Lambda Function URL via SigV4), peer-mode self-call guard, base64-encoded bytes over the wire, and Caravan-shipped resource adapters (BlobStore, MessageQueue) for S3 / Redis / RabbitMQ / SQS.
What is Caravan?
Caravan is an application-definition compiler. The same source code deploys across packaging (inproc / container / lambda) × placement (compose / Fargate / Lambda) × composition (oss-local / cloud-managed) axes by yaml-line changes alone — no source-code edits.
Read the thesis and the PoC RPC SDK spec.
Install
pip install caravan-rpc>=0.1.1
Optional extras (each pulls in its backend client only when needed):
pip install "caravan-rpc[aws,redis,rabbit,lambda]>=0.1.1"
# aws — boto3 for S3BlobStore + SqsQueue.
# redis — redis-py for RedisStreamQueue.
# rabbit — pika for RabbitMQQueue.
# lambda — botocore SigV4 signer for Lambda Function URL client dispatch.
# all — convenience meta-extra.
Three-point structural contract
User code interacts with Caravan through three SDK entry points; everything else is compiler-managed:
from caravan_rpc import wagon, provide, client
# 1. @wagon declares an interface as a Caravan seam — a synchronous
# abstraction boundary that yaml can flip between inproc / HTTP /
# Lambda dispatch per target.
@wagon
class LLMExtraction:
def extract(self, ocr_text: str, file_bytes: bytes) -> InvoiceExtraction: ...
# 2. provide() registers a concrete impl at process startup.
class GeminiExtractor:
def extract(self, ocr_text, file_bytes):
...
provide(LLMExtraction, GeminiExtractor())
# 3. client() dispatches a call — inproc, HTTP, or Lambda per the
# `CARAVAN_RPC_PEERS` env var the compiler emits per target.
def run(pdf_bytes: bytes, ocr_text: str):
extractor = client(LLMExtraction)
return extractor.extract(ocr_text, pdf_bytes)
bytes arguments are JSON-encoded as base64 over the wire (set via pydantic.ConfigDict(ser_json_bytes="base64") on the codec's TypeAdapter). Binary payloads — PDFs, images — cross HTTP / Lambda cleanly without UTF-8 decode failures.
Dispatch modes
CARAVAN_RPC_PEERS is a per-deploy-unit JSON map the compiler emits:
{
"LLMExtraction": {"mode": "http", "url": "http://llm-extractor:8080"},
"OCRText": {"mode": "inproc"},
"ValidateExtraction": {"mode": "lambda", "function_url": "https://...lambda-url.ap-southeast-1.on.aws/"}
}
inproc→client(I).methodreturns the registered impl's bound method directly (zero overhead, no-config-inert).http→ returns a callable that POSTs to/_caravan/rpc/<iface>/<method>with a Bearer token.lambda→ SigV4-signed POST to the Lambda Function URL (requires[lambda]extra).
Peer-mode self-call guard: when CARAVAN_RPC_ROLE=peer-<Interface> matches the served interface, client(I) falls through to the local impl instead of an HTTP dispatcher pointing back at this same container. Peer containers share the consumer's CARAVAN_RPC_PEERS, so without the guard requests would loop.
Peer-mode entry: python -m caravan_rpc.serve
Caravan emits compose peer services that invoke this module:
python -m caravan_rpc.serve --interface LLMExtraction \
--impl invoice_processing.extraction:GeminiExtractor \
--port 8080
The CLI imports the impl, calls provide(), then serves @wagon methods on /_caravan/rpc/<iface>/<method>. Same wire contract the client(I) HTTP dispatcher targets.
Resource adapters
Caravan-shipped impls of common resource seams (BlobStore, MessageQueue):
from caravan_rpc.resources import auto_register_resources, BlobStore
from caravan_rpc import client
def main():
with open("config/app.yaml") as f:
cfg = yaml.safe_load(f)
auto_register_resources(yaml_fallback=cfg)
blob = client(BlobStore)
blob.put("input.pdf", pdf_bytes)
Backend selection is driven by explicit Caravan-emitted markers:
CARAVAN_BLOB_BACKEND=s3+S3_BUCKETset →S3BlobStore(real AWS or MinIO viaS3_ENDPOINT_URL).CARAVAN_BLOB_BACKEND=local-fs→LocalFsBlobStorerooted at the path fromyaml_fallback.blob_storage.base_path(default/data/blobs).- Marker unset → consult
yaml_fallback. Non-caravan local-dev path.
CARAVAN_BLOB_BACKEND=s3 with no S3_BUCKET loud-fails at startup (catches the "user forgot to populate .env.hybrid from tofu output" footgun).
MessageQueue selects on QUEUE_URL scheme: redis:// → RedisStreamQueue, amqp:// → RabbitMQQueue, https:// → SqsQueue.
Versions
- 0.1.1: peer-mode self-call guard;
CARAVAN_BLOB_BACKENDexplicit marker; bytes serialized as base64 (was utf-8 default in pydantic, which crashed on binary payloads). SDK version bumped alongside Rust 0.1.1 for matching wire-protocol semantics. - 0.1.0: first functional release.
@wagon/provide/clientwithCARAVAN_RPC_PEERSenv-var dispatch; HTTP + Lambda SigV4 client dispatchers;caravan_rpc.servepeer CLI;caravan_rpc.lambda_handlerfor Function URL event v2.0; resource adapters. - 0.0.1: PyPI name reservation placeholder.
See development_plan.md for the full milestone history.
License
Apache-2.0. See LICENSE.
Release files for caravan-rpc 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| caravan_rpc-0.1.1.tar.gz | 25.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| caravan_rpc-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 57.0 kB
Release files / caravan_rpc-0.1.1.tar.gz
| Download URL | caravan_rpc-0.1.1.tar.gz |
|---|---|
| Size | 25.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
51e175945b87311c7592513da9438083eee8a97dfc5c24ed03dbed78c2e3ed2e
|
|
BLAKE2b-256 checksum How to use checksums |
36e10236090c4565175c49f4acb96b7060f151972f587dd7443be004d4df5045
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 27, 2026.
Transparency logRelease files / caravan_rpc-0.1.1-py3-none-any.whl
| Download URL | caravan_rpc-0.1.1-py3-none-any.whl |
|---|---|
| Size | 31.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1801867f8d1c9f8737b7ea601dabe2c9356aafe92b94bf1a36ffa55c4b3744ad
|
|
BLAKE2b-256 checksum How to use checksums |
b80d8472f97843a144cd30f57aa365e4b4fe794ac4f2d416337d5babba5eb090
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 27, 2026.
Transparency log