Agora — async-first ETL framework for Python.
Project description
Agora ETL Framework
Async-first ETL framework for Python.
agora-etl is the core Agora runtime: a builder-first ETL framework organized
around Source -> Middleware chain -> Sink(s).
It stays focused on runtime semantics and extension contracts:
- immutable pipeline composition
- per-record, batched, and Arrow-aware execution
- checkpointing and replay
- DLQ and sink failure policies
- backpressure, tracing, metrics, and health surfaces
- scheduled workers and config-driven runs
Official backend integrations such as Redis, Kafka, PostgreSQL, cron
scheduling, and distributed coordination live in
agora-etl-plugins. Optional acceleration belongs in
agora-etl-rs.
Install
pip install agora-etl
pip install "agora-etl[file]" # pyarrow + faster JSONL paths
pip install "agora-etl-plugins[all]" # official first-party integrations
Quick Start
import asyncio
from agora import DeliveryConfig, IterableSource, Pipeline
from agora.core.dlq import SQLiteDLQSink
from agora.sinks.file.jsonlines import JsonLinesSink
records = [
{"id": 1, "city": "Ho Chi Minh City", "confidence": 0.92},
{"id": 2, "city": "Da Nang", "confidence": 0.41},
{"id": 3, "city": "Hanoi", "confidence": 0.88},
]
async def main() -> None:
summary = await (
Pipeline(IterableSource(records))
.filter(lambda row: row["confidence"] >= 0.5, name="confidence_gate")
.build(
JsonLinesSink(path="cities.jsonl"),
config=DeliveryConfig(
dlq=SQLiteDLQSink(".agora_dlq.db"),
batch_size=100,
),
)
.run()
)
print(summary)
asyncio.run(main())
What this does:
- reads from an in-memory source
- filters low-confidence rows
- writes the survivors to
cities.jsonl - sends failed records to a local SQLite DLQ
- returns a
PipelineRunSummarywith counts, timing, and runtime signals
Why 0.3.0 Matters
Agora now exposes execution shape as a first-class contract.
Three shared data planes:
python_rowspython_batchesarrow_batches
That vocabulary now shows up consistently across sources, middleware, writer planning, sink boundaries, runtime summaries, and tracing.
You can inspect the plan before the run starts:
from agora import Pipeline
from agora.sinks.file.csv import CsvSink
bound = Pipeline(source).build(CsvSink(path="out.csv", row_mapper=lambda row: row))
plan = bound.explain(max_records=1_000)
print(plan)
print(plan.to_dict())
PipelineExplain surfaces:
- selected execution lane
- source and writer data planes
- middleware compatibility matrix
- per-sink selected plane and downgrade markers
Execution Shapes
Agora supports more than one runtime shape, but keeps them explicit:
- row pipelines: standard
Middleware/MapMiddleware/FilterMiddleware - Python batch pipelines:
stream_batches()plusBatchMiddleware - Arrow pipelines:
pyarrow.RecordBatchplus Arrow-native middleware and sinks
The important rule is that one middleware chain must stay internally compatible:
- Python-row chain is valid
- all-Arrow chain is valid
- mixed Arrow plus Python-row/list-batch chain is rejected during planning
For Arrow fan-out, Agora chooses the best path per sink:
- Arrow-capable sinks receive the original
RecordBatch - non-Arrow sinks downgrade only at the sink boundary
Builder Model
The pipeline builder is immutable.
base = (
Pipeline(source)
.pipe(NormalizeMiddleware())
.filter(lambda row: row["confidence"] >= 0.5)
)
csv_pipeline = base.build(CsvSink(path="clean.csv", row_mapper=lambda row: row))
jsonl_pipeline = base.build(JsonLinesSink(path="clean.jsonl"))
Common composition patterns:
.build(sink)for one destination.fan_out([...])for writing the same record to many sinks.route(router)for sending each record to one matching sink.run(max_records=N)for bounded runs, now enforced at the source boundary
Delivery options are passed via DeliveryConfig, including:
dlqcheckpointbatch_sizesink_failure_policysink_concurrencybackpressuretracer
Public Data-Plane API
The execution-shape contract is now public API:
from agora import DataPlane, SinkDataPlaneSpec, SourceDataPlaneSpec
source_spec = source.data_plane_spec()
sink_spec = sink.data_plane_spec()
Legacy data-plane booleans still work in 0.3.x, but they are now a
compatibility bridge and emit DeprecationWarning when Agora has to infer a
non-row plane from them.
Preferred direction:
- sources override
data_plane_spec() - sinks advertise
accepted_data_planesandnative_data_planes
Core vs Plugins
Keep this mental model:
agora-etl: runtime semantics, pipeline contracts, CLI, docsagora-etl-plugins: official integrationsagora-etl-rs: optional acceleration that preserves the same semantics
If a capability depends on Redis, Kafka, PostgreSQL, cron parsing, or distributed lease ownership, it likely belongs in the plugin bundle rather than the core package.
Documentation Map
- Quickstart
- Pipelines
- Failure Handling
- Checkpointing
- Observability
- Scheduling
- Plugins
- Architecture
- CLI
- Change Log
Reference sections:
License
Apache 2.0 - see LICENSE.
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 agora_etl-0.3.0.tar.gz.
File metadata
- Download URL: agora_etl-0.3.0.tar.gz
- Upload date:
- Size: 431.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42908df17705eea324bd7c170ceb1d363196b43eb9108d3b8e02cd9e8c2e53bb
|
|
| MD5 |
db0362d7bab2061f734467b7c8fa8645
|
|
| BLAKE2b-256 |
ed714a46a5882c35e896e88c8244e5f7b569418b845b41a53654bca91318e019
|
Provenance
The following attestation bundles were made for agora_etl-0.3.0.tar.gz:
Publisher:
release.yml on thanhtham010891/agora-etl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agora_etl-0.3.0.tar.gz -
Subject digest:
42908df17705eea324bd7c170ceb1d363196b43eb9108d3b8e02cd9e8c2e53bb - Sigstore transparency entry: 1734155096
- Sigstore integration time:
-
Permalink:
thanhtham010891/agora-etl@5e490ff7c33b9bdad1aeda55f5853e72b804b289 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/thanhtham010891
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5e490ff7c33b9bdad1aeda55f5853e72b804b289 -
Trigger Event:
release
-
Statement type:
File details
Details for the file agora_etl-0.3.0-py3-none-any.whl.
File metadata
- Download URL: agora_etl-0.3.0-py3-none-any.whl
- Upload date:
- Size: 277.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dae9e1008ad5f4442af7a1f2ad2c8dd3059d653a99214375554ceb94f23018a8
|
|
| MD5 |
e771173c70122ae00081cac6c3968dcd
|
|
| BLAKE2b-256 |
b29441de7dca26a76e42d4c81420ce637918173bcd161991f718ff7fcafe8452
|
Provenance
The following attestation bundles were made for agora_etl-0.3.0-py3-none-any.whl:
Publisher:
release.yml on thanhtham010891/agora-etl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agora_etl-0.3.0-py3-none-any.whl -
Subject digest:
dae9e1008ad5f4442af7a1f2ad2c8dd3059d653a99214375554ceb94f23018a8 - Sigstore transparency entry: 1734155178
- Sigstore integration time:
-
Permalink:
thanhtham010891/agora-etl@5e490ff7c33b9bdad1aeda55f5853e72b804b289 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/thanhtham010891
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5e490ff7c33b9bdad1aeda55f5853e72b804b289 -
Trigger Event:
release
-
Statement type: