Skip to main content

Dex SDK for Python

Python SDK for Dex workflow engine

New user contracts

The rewrite targets Python 3.11+ and exposes strongly typed workflow contracts from dex. This phase includes definitions, attributes, channels, waits, decisions, codecs, registry validation, synchronous client calls, and synchronous worker handlers. Python owns its gRPC Client and Worker transport; the shared Rust Core is used only for BlobCache.

from datetime import timedelta

import dex

counter = dex.Attribute("counter", int)
counters_by_region = dex.AttributeMap("counters-by-region", int)

class Run(dex.Step[str]):
    def wait_for(
        self, context: dex.Context, input: str
    ) -> dex.Wait:
        return dex.Wait.until(
            dex.Timer.by_duration(timedelta(seconds=1))
        )

    def execute(
        self, context: dex.Context, input: str
    ) -> dex.StepDecision:
        return dex.graceful_complete(input)

class CounterFlow(dex.Flow[str]):
    run = Run()

    def get_flow_type(self) -> str:
        return "Counter"

    def get_steps(self) -> dex.StepList[str]:
        return dex.StepList.start_step(self.run)

    def get_persistence_schema(self) -> dex.PersistenceSchema:
        return dex.PersistenceSchema.of(counter, counters_by_region)

    @dex.rpc(name="Increment")
    def increment(
        self, context: dex.Context, input: int
    ) -> dex.RPCResult[int]:
        return dex.RPCResult(input + 1)

flow = CounterFlow()
registry = dex.Registry((flow,))

Registry derives codecs from declared Python types and handler annotations. Built-in scalar types and dataclasses need no codec arguments. Register an explicit codec only for a custom encoding or a type Registry cannot derive. PersistenceSchema.of(...) accepts attributes and channels together and partitions them by definition type.

Worker and AsyncWorker synchronize all registered Indexed Attributes with Dex Server before opening their listener. Existing indexes return immediately; failure or the default two-minute deadline aborts startup. An indexed AttributeMap must provide one fixed index_key.

Initial attributes retain their value types without a public wrapper class:

options = (
    dex.StartFlowOptions()
    .with_attribute(counter, 1)
    .with_attribute(counters_by_region, "us-west", 1)
)

Opt in when declaring an Attribute or AttributeMap, and select the Store in Flow configuration:

email = dex.Attribute("customer-email", str, sync_to_attribute_store=True)
config = dex.FlowConfig(attribute_store_name="profiles")

The Store is an asynchronous latest-state projection. Deletion writes SQL NULL, and projection failures do not roll back Flow Attributes. None preserves the current target; an explicit empty string disables future synchronization while retaining protocol presence.

pip install dex-python-sdk==0.1.0

See samples for use case examples.

Requirements

Concepts

Applications implement two generic interfaces from dex:

  • Flow[START_INPUT] returns StepList.start_step(...), followed by optional .other_steps(...), from one get_steps() method. The StepList generic binds the Flow input to the starting Step input. Use StepList.empty() when a Flow has no Steps.
  • Step[INPUT] implements execute and optionally wait_for. The default Worker path requires synchronous handlers. With AsyncWorker and Registry(..., allow_async_handlers=True), handlers may be async def and await an AsyncClient.

StepOptions.wait_for_method_timeout and execute_method_timeout bound the two handler calls. Timer and channel conditions determine how long a Step waits.

Registry validates every Flow, Step, RPC signature, durable name, lock, and codec before Client or Worker startup. Client methods use these typed objects instead of raw Flow, Step, or RPC strings.

Errors

Client calls raise concrete DexServiceError subclasses. Existing-Flow reads (get_attribute, describe_flow, wait_for_flow, and reset_flow) raise FlowNotFoundError when the Flow does not exist. Mutations, RPCs, timer/Step waits, config updates, and continue-as-new triggers raise FlowNotActiveError when no running Flow can accept the operation.

try:
    client.publish(flow_id, orders.approved, order_id)
except dex.FlowNotActiveError:
    # The Flow is missing or already closed.
    pass

Duplicate starts, worker failures, RPC lock contention, and long-poll timeouts raise FlowAlreadyStartedError, WorkerInvocationError, RpcLockConflictError, and LongPollTimeoutError. All service errors retain code, sub_status, detail, operation, flow_id, and the original gRPC exception through Python exception chaining. Worker failures also expose worker_code, worker_error_type, and worker_error_detail. Registration, serialization, and invalid handler returns use FlowDefinitionError, ValueMappingError, and InvalidStepResultError.

Sync vs asyncio

  • Sync (default): Client and Worker use blocking gRPC and a thread-pool Worker. Blocking Client calls inside Step.execute are safe (one pool thread is occupied; other RPCs still run).
  • Asyncio: AsyncClient and AsyncWorker use grpc.aio. Use Registry(..., allow_async_handlers=True) when Steps/RPCs are coroutines. Inside async execute, inject AsyncClient — do not call sync Client on the Worker event loop. Sync Worker still rejects coroutine handlers at registry construction unless allow_async_handlers=True (and even then the sync Worker dispatcher rejects awaitable return values).

Integration scenarios live under tests/integ. They exercise the same workflows, client operations, and assertions as the Java suite against an isolated dexcli dev environment.

Implementation status

The strongly typed contracts, registry, synchronous Client/Worker, optional AsyncClient/AsyncWorker (grpc.aio), and Rust-backed BlobCache are implemented. Python owns its gRPC transport; the native bridge is limited to the shared BlobCache. Design notes: docs/design/plan/python-sdk-async-apis.md.

Running dex-server locally

Option 1: use docker compose

See dex README

Option 2: VSCode Dev Container

Dev Container is an easy way to get dex-server running locally. Follow these steps to launch a dev container:

  • Install Docker, VSCode, and VSCode Dev Container plugin.
  • Open the project in VSCode.
    cd dex-python-sdk
    code .
    
  • Launch the Remote-Containers: Reopen in Container command from Command Palette (Ctrl + Shift + P). You can also click in the bottom left corner to access the remote container menu.
  • Once the dev container starts, dex-server will be listening on port 8801.

How To Contribute

This project uses uv for Python versions, dependencies, virtual environments, locking, building, and publishing.

To install requirements:

uv sync --locked

Run the complete Python SDK integration suite with an isolated Dex development environment:

./run-integration-tests.sh

Measure integration coverage

Run the same integration suite with Python source coverage:

./run-integration-tests.sh --coverage

Only the integration scenarios contribute execution data, and only production Python modules under dex are measured. Generated protobuf modules under dex/dexpb are excluded. The terminal report lists uncovered line ranges. The browser report starts at coverage/html/index.html; coverage/coverage.xml and coverage/lcov.info are also generated.

CI uploads LCOV to Codecov with GitHub OIDC under the sdk-python-integration flag and retains the full report as the sdk-python-integration-coverage Actions artifact.

Update IDL

Edit protos/dex.proto. Rename catalog: docs/design/idl-renames.md.

Generate stubs from IDL

make -C ../protos proto-python

Checked-in Python stubs land in dex/dexpb/.

Linting

Validate that every dex.__all__ class, function, constant, public method, argument, return value, dataclass field, enum value, and public instance attribute has a Google-style docstring:

uv run --frozen python scripts/check_public_docs.py

The checker resolves definitions from the public package export table, so private helpers and generated protobuf modules are excluded. Use help(dex.Client) or IDE hover information to read the same documentation. To run all other linting for this project:

uv run --frozen pre-commit run --show-diff-on-failure --color=always --all-files

Code of Conduct

This project is governed by the Contributor Covenant v 1.4.1. (Review the Code of Conduct and remove this sentence before publishing your project.)

Publishing to PyPI

  1. Optionally run Publish Python SDK to PyPI via workflow_dispatch with a version and publish=false to validate all distributions without uploading.
  2. Create a GitHub Release with tag sdk-python/vX.Y.Z (for example sdk-python/v0.1.0). CI stamps that version into pyproject.toml for the build (same idea as the TypeScript SDK release), then builds and smoke-tests Linux x86_64/ARM64, macOS x86_64/ARM64, and Windows x86_64 wheels, verifies the source distribution, and publishes with PYPI_TOKEN.
  3. After publishing, bump the committed pyproject.toml / docs install line when you want the repo tip to reflect the released version.

A manual run publishes only from main, and only when publish is explicitly selected. The dispatch version input is stamped the same way as a release tag.

See CONTRIBUTING.md for monorepo tag conventions.

License

Super Durable Source License 1.0, with legacy portions under their original terms as described in LEGACY_NOTICES.md.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dex_python_sdk-0.1.2.tar.gz (134.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

dex_python_sdk-0.1.2-cp311-abi3-win_amd64.whl (514.0 kB view details)

Uploaded CPython 3.11+Windows x86-64

dex_python_sdk-0.1.2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (671.0 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ x86-64

dex_python_sdk-0.1.2-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (668.8 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ ARM64

dex_python_sdk-0.1.2-cp311-abi3-macosx_11_0_arm64.whl (612.0 kB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

dex_python_sdk-0.1.2-cp311-abi3-macosx_10_12_x86_64.whl (631.4 kB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

File details

Details for the file dex_python_sdk-0.1.2.tar.gz.

File metadata

  • Download URL: dex_python_sdk-0.1.2.tar.gz
  • Upload date:
  • Size: 134.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dex_python_sdk-0.1.2.tar.gz
Algorithm Hash digest
SHA256 dceda2dbbb2017df6f8ecaebfe1c6df3ecb5b3d29195204a57d511810a5b875c
MD5 7c0949d6f20047a0464b697d0f025548
BLAKE2b-256 b8f4f99764acd8ad90620401b368a6bee4e7413d780595bdb4e3aa74d0ae4c5f

See more details on using hashes here.

File details

Details for the file dex_python_sdk-0.1.2-cp311-abi3-win_amd64.whl.

File metadata

  • Download URL: dex_python_sdk-0.1.2-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 514.0 kB
  • Tags: CPython 3.11+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dex_python_sdk-0.1.2-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 0c2ee9e66a23681ed84a0ccf083618bdf7174d4901da6c3e22e7e743757e2705
MD5 e2e500609e2a9f794840b01070cae359
BLAKE2b-256 b8ae1dea73af6bcbe8542410b426501a28bec69d76b6a79a757f42b4082355c9

See more details on using hashes here.

File details

Details for the file dex_python_sdk-0.1.2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

  • Download URL: dex_python_sdk-0.1.2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  • Upload date:
  • Size: 671.0 kB
  • Tags: CPython 3.11+, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dex_python_sdk-0.1.2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 28795874630d6a8aa24ef5dfafc33262c8825b2b2342c7ccd37aed1ec55684b2
MD5 a4c16581ad86f220b5b71657e35eebf7
BLAKE2b-256 a56b092d554fc4f7021dfa38fe3701193bbc9480bde5a701a42c2169c4a8d575

See more details on using hashes here.

File details

Details for the file dex_python_sdk-0.1.2-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

  • Download URL: dex_python_sdk-0.1.2-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
  • Upload date:
  • Size: 668.8 kB
  • Tags: CPython 3.11+, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dex_python_sdk-0.1.2-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4b4df4485e4041c2ebb5c8da66cfc2e652d879fc8910e0cdafafa3f994c5a631
MD5 56f80b6c9f652376ff3b87645126959e
BLAKE2b-256 05d93d3eb8f6eef2b7ab87e5855f625c802e0b8681ebf06a1dcf79e4463e040c

See more details on using hashes here.

File details

Details for the file dex_python_sdk-0.1.2-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: dex_python_sdk-0.1.2-cp311-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 612.0 kB
  • Tags: CPython 3.11+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dex_python_sdk-0.1.2-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f530caa5adb580ef948fe43bf2b4dfd81ccceacb3988d90286dfaf9536c7ef74
MD5 a562ed8324c2ed7755cc58389de8dfc0
BLAKE2b-256 e551ae5797854fa989e17c090118de2a887ed244b04ce73d20b9dc1ba3cd2d7f

See more details on using hashes here.

File details

Details for the file dex_python_sdk-0.1.2-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: dex_python_sdk-0.1.2-cp311-abi3-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 631.4 kB
  • Tags: CPython 3.11+, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dex_python_sdk-0.1.2-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 17499d156b0845a40ab0bb1a058ad6a443a44ac8e3e1737e2e4ef8eabe056e4c
MD5 d14007f4d65e5a2b5143b9c1cb0e5279
BLAKE2b-256 8a2000e14636a71320c3111077ce823c551275aa8f48cae903da4850eb86456f

See more details on using hashes here.

Release history Release notifications | RSS feed

0.7.0

6 files

0.6.0

6 files

0.5.0

6 files

0.4.0

6 files

0.3.2

6 files

0.3.1

6 files

0.2.11

6 files

0.2.10

6 files

0.2.9

6 files

0.2.8

6 files

0.2.7

6 files

0.2.6

6 files

0.2.5

6 files

0.2.4

6 files

0.2.3

6 files

0.2.2

6 files

0.2.1

6 files

0.2.0

6 files

0.1.11

6 files

0.1.10

6 files

0.1.5

6 files

0.1.4

6 files

0.1.3

6 files

This release

0.1.2 This release

6 files

0.1.1

6 files

0.0.2

6 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page