Public API spine for reverse ETL authoring.
Project description
condor-retl
condor-retl is a Python reverse ETL library for declaring syncs from
warehouse-shaped rows into destination-facing mutations.
Users write Python declarations for five primitives:
- Source: a SQL-backed set of source rows
- State: desired current facts such as profile attributes or audience membership
- Event: occurred facts such as purchases, signups, or lifecycle events
- Sync: one State or Event declaration bound to one destination surface
- Destination Surface: a connector-owned API contract such as Meta Custom Audiences or Klaviyo profiles
The runtime executes those declarations through durable collect -> stage -> reconcile -> sync phases with retry-aware ledger state, dry-run planning, and
bounded operator evidence.
This project is in the initial 0.1.x alpha line. APIs are intended to be
usable, but the package is still early and may change before a stable release.
User Documentation
The Docusaurus user-docs source lives in
docs-site/. From that directory, run:
npm install
npm run dev
npm run build
The root docs/ tree remains the repository control-plane,
contributor, and implementation-contract documentation surface.
Installation
Install the core package:
pip install condor-retl
Install the source backend extras you need:
pip install "condor-retl[duckdb]"
pip install "condor-retl[snowflake]"
pip install "condor-retl[bigquery]"
pip install "condor-retl[databricks]"
pip install "condor-retl[postgresql]"
Install destination connectors as separate packages:
pip install condor-retl-meta
pip install condor-retl-klaviyo
pip install condor-retl-google-ads-data-manager
pip install condor-retl-bing-ads
pip install condor-retl-tiktok-ads
The distribution package is named condor-retl; the Python import package is
retl:
import retl
AI Skills
Install RETL's user-facing AI skills into a project:
retl install-skills .
By default this installs the same packaged skills into .agents/skills/ and
.claude/skills/ in the target project.
The installed retl-start-project skill guides an AI agent to create the
right local project shape for the user's actual source backend, destination,
and operating model.
Quickstart
This is the smallest useful shape for sending one email audience to Meta. The
SQL only needs an email column; retl.target(...) names the logical Meta
Custom Audience for every row.
dry_run=True plans the Meta request without writing to Meta; change it to
False when you are ready to send.
import retl
from retl.backends.duckdb import DuckDBSqlBackend
db = DuckDBSqlBackend(
database="warehouse.duckdb",
source_schema="main",
runtime_schema="retl",
)
audience = retl.state(
name="newsletter_audience",
source=retl.source(
name="newsletter_customers",
mode="snapshot",
backend=db.source_backend(),
query="""
select email
from customers
where email is not null
""",
),
key={"customer_id": "email"},
target=retl.target("newsletter_customers"),
identifiers=[{"type": "email", "value": "email"}],
)
meta = retl.destinations.load(
"retl/meta",
binding_name="meta_primary",
credential_namespace="destinations.meta",
config_namespace="destinations.meta",
)
result = retl.runner(
name="send_newsletter_audience",
runtime_store=db.runtime_store(),
).run(
retl.sync(
name="newsletter_audience_to_meta",
declaration=audience,
destination=meta,
surface="custom_audiences",
),
dry_run=True,
)
print(result.to_text())
For local development, the default config and secret resolvers read environment variables. The example above expects values such as:
export DESTINATIONS__META__ACCESS_TOKEN="..."
export DESTINATIONS__META__AD_ACCOUNT_ID="act_..."
Core Model
RETL separates source shaping from destination delivery.
Source SQL owns joins, aggregation, dedupe, filtering, and other grain changes. RETL declarations map already-shaped rows into State or Event intent.
State is for desired current facts:
customer_state = retl.state(
name="customer_state",
source=customers,
key={"customer_id": "customer_id"},
identifiers=[{"type": "email", "value": "email"}],
payload={"plan": "plan"},
)
Event is for occurred facts from checkpointed sources:
purchase_events = retl.event(
name="purchase",
source=purchases,
key={"purchase_id": "purchase_id"},
occurred_at="purchased_at",
identifiers=[{"type": "email", "value": "email"}],
payload={"order_total": "order_total", "currency": "currency"},
)
Identifier mappings support one value or a list of values:
identifiers=[
{"type": "email", "value": "primary_email"},
{"type": "email", "values": "all_emails"},
]
Both forms produce flat canonical Identifier objects shaped like
{"type": "...", "value": "..."}.
Execution
The normal execution entrypoints are:
runner.run(sync)for one Syncrunner.run(sync, dry_run=True)for planning without irreversible destination writes or progress advancementrunner.run_many([sync_a, sync_b])for an explicit Sync set that can share collect and stage workrunner.dismiss_unresolved(sync)for intentionally dismissing unresolved destination batches in one Sync destination scope
Runtime recovery is ledger-first. Later runs retry old pending batches and
retryable failed batches before scanning new work. Terminal outcomes such as
succeeded, accepted, and skipped are not retried automatically.
Destination Connectors
First-party partner destination connectors are published separately from the
core runtime. They expose connector refs through the retl.destinations entry
point group, then user code loads them by ref:
retl.destinations.load("retl/meta", binding_name="meta_primary")
Core RETL also ships two built-in local connectors, retl/mock and
retl/reference. These are proof and authoring surfaces for tests, examples,
and new connector development. They are not partner integrations and are not
the way operators install a production destination. retl/mock is the core
runtime test double for synthetic destination outcomes.
Current first-party connector packages:
| Package | Connector ref | Surfaces |
|---|---|---|
condor-retl-meta |
retl/meta |
Meta Custom Audiences and Conversions API events |
condor-retl-klaviyo |
retl/klaviyo |
Klaviyo profiles and list memberships |
condor-retl-google-ads-data-manager |
retl/google-ads-data-manager |
Google Ads Customer Match and Data Manager events |
condor-retl-bing-ads |
retl/bing-ads |
Microsoft Advertising Customer Match Customer Lists |
condor-retl-tiktok-ads |
retl/tiktok-ads |
TikTok Ads Custom Audience membership |
The retl/reference-http connector remains a repo-local reference package for |
||
| tests and connector authors. It is the package-shaped proof path for HTTP | ||
| request planning, dry runs, injected transport, receipts, and destination batch | ||
| ledger behavior, and is not published to PyPI. |
Connector READMEs contain partner-specific auth, config, target, sandbox, and surface details.
Configuration And Secrets
Public config and secret material use stable dotted logical names. By default, the environment resolver maps names to uppercase environment variables with double underscores:
retl.config["destinations.meta.ad_account_id"]
retl.secrets["destinations.meta.access_token"]
becomes:
DESTINATIONS__META__AD_ACCOUNT_ID=act_123
DESTINATIONS__META__ACCESS_TOKEN=...
Local scripts can configure TOML-backed resolvers without changing destination declarations:
retl.configure(
config_resolver=retl.ChainedConfigResolver(
retl.TomlConfigResolver("retl.local.toml"),
retl.EnvironmentConfigResolver(),
),
secret_resolver=retl.TomlSecretResolver("retl.local.toml"),
)
Development
This repository uses uv for the local
environment, dependency lock, builds, and publishing.
Set up the development environment:
make dev
Run the default verification baseline:
make check
make check runs formatting, linting, typechecking, tests, repository skeleton
validation, and architecture validation.
If package names or workspace members changed, resync before checking:
uv sync --all-extras --group dev
make check
Build the core package:
make build-library
Build one destination connector package:
make build-destination-connector PACKAGE=meta
Documentation
Start with the durable docs index:
Repository policy, architecture, and agent workflow details live in Control Plane.
License
Unless a package-level license file or package metadata says otherwise, this repository is licensed under Elastic-2.0.
The core condor-retl package is licensed under the
Elastic License 2.0. First-party destination
connector packages distributed by Condor are licensed under the
Apache License 2.0; the authoritative license for any connector is the
LICENSE and pyproject.toml metadata shipped with that package.
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 condor_retl-0.1.0.tar.gz.
File metadata
- Download URL: condor_retl-0.1.0.tar.gz
- Upload date:
- Size: 223.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be7d9f7c69d94f45c03607bf767bcd3e766997972fd8f58adbd1472005fcdf8d
|
|
| MD5 |
ff4a0b54b51102042df901981ea373ab
|
|
| BLAKE2b-256 |
9667b1d58d7814beceb0b8f43659f84c331f19094ee85ddedf27aa690577571e
|
Provenance
The following attestation bundles were made for condor_retl-0.1.0.tar.gz:
Publisher:
publish.yml on condorgraph/condor-retl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
condor_retl-0.1.0.tar.gz -
Subject digest:
be7d9f7c69d94f45c03607bf767bcd3e766997972fd8f58adbd1472005fcdf8d - Sigstore transparency entry: 1565121250
- Sigstore integration time:
-
Permalink:
condorgraph/condor-retl@18e0a038f797cb3529b6a1d8662794d89958eddb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/condorgraph
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@18e0a038f797cb3529b6a1d8662794d89958eddb -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file condor_retl-0.1.0-py3-none-any.whl.
File metadata
- Download URL: condor_retl-0.1.0-py3-none-any.whl
- Upload date:
- Size: 299.8 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 |
27ee305ed92a51d74e52ec1a0cb4524b139c28bb0256b316e3c254f809fd60ee
|
|
| MD5 |
f342844295967f23a90aedce142a44fe
|
|
| BLAKE2b-256 |
2b820dfc285c818b0d526ef38ab48ed221d76e1a31d2561d1b009cbf1dd93448
|
Provenance
The following attestation bundles were made for condor_retl-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on condorgraph/condor-retl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
condor_retl-0.1.0-py3-none-any.whl -
Subject digest:
27ee305ed92a51d74e52ec1a0cb4524b139c28bb0256b316e3c254f809fd60ee - Sigstore transparency entry: 1565121294
- Sigstore integration time:
-
Permalink:
condorgraph/condor-retl@18e0a038f797cb3529b6a1d8662794d89958eddb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/condorgraph
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@18e0a038f797cb3529b6a1d8662794d89958eddb -
Trigger Event:
workflow_dispatch
-
Statement type: