Skip to main content

resonate banner

Resonate Python SDK

ci codecov License

About this component

The Resonate Python SDK enables developers to build reliable and scalable cloud applications across a wide variety of use cases.

Packages

Package Module What it is
resonate-sdk resonate The SDK: durable functions, context, the HTTP/SSE/local transports.
resonate-base resonate_base Connector seam: the Network/Source protocols and ConnectorError. Nothing else — a connector moves opaque strings and never parses ids or invents address formats. No third-party dependencies.
resonate-nats resonate_nats NATS connector. Install with pip install resonate-nats.
resonate-pg resonate_pg Postgres connector — the server is a resonate-pg schema, no server process. Install with pip install resonate-pg.
resonate-sdk-aws resonate_aws AWS Lambda worker shim.

Connectors depend on resonate-base alone, never on resonate-sdk — and they are not extras of resonate-sdk. Installing one is pip install resonate-nats or pip install resonate-pg, so the SDK's dependency metadata never names a connector and the arrow only ever points one way.

Requirements

  • Python ≥3.12
  • A Resonate server: either the Resonate server (v0.9.x and up), or resonate-pg — one SQL file on Postgres 16+ — via resonate-pg.

Quickstart

quickstart banner

  1. Install the Resonate Server & CLI
brew install resonatehq/tap/resonate
  1. Install the Resonate SDK
pip install resonate-sdk
  1. Write your first Resonate Function

A countdown as a loop. Simple, but the function can run for minutes, hours, or days, despite restarts.

import asyncio
from datetime import timedelta

from resonate.context import Context
from resonate.resonate import Resonate


async def countdown(ctx: Context, count: int, delay: int) -> None:
    for i in range(count, 0, -1):
        # Run a function durably, awaiting its persisted result
        await ctx.run(ntfy, i)
        # Sleep durably -- the worker holds no state while suspended
        await ctx.sleep(timedelta(seconds=delay))
    print("Done!")


async def ntfy(ctx: Context, i: int) -> None:
    print(f"Countdown: {i}")


async def main() -> None:
    # Connect to the Resonate server and register the functions
    resonate = Resonate(url="http://localhost:8001")
    resonate.register(countdown)
    resonate.register(ntfy)

    try:
        # Invoke with execution id "countdown.1"; run() returns a handle
        # immediately, result() awaits the durable outcome
        handle = resonate.run("countdown.1", countdown, 5, 1)
        await handle.result()
    finally:
        await resonate.stop()


if __name__ == "__main__":
    asyncio.run(main())
  1. Start the server
resonate dev
  1. Run the worker
python countdown.py

Result

You will see the countdown in the terminal

python countdown.py
Countdown: 5
Countdown: 4
Countdown: 3
Countdown: 2
Countdown: 1
Done!

What to try

While the function is running, inspect the current state of the execution using the resonate tree command. The tree command visualizes the call graph of the function execution as a graph of durable promises.

resonate tree countdown.1

Now try killing the worker mid-countdown and restarting python countdown.py. Because the invocation id is the same (countdown.1), the worker reattaches to the existing durable promise and the countdown picks up right where it left off without missing a beat.

Examples

The examples/ directory contains runnable programs covering the core patterns. Start a server (resonate dev) on localhost:8001, then run any of them, for example:

uv run python examples/hello-world
uv run python examples/fibonacci --mode rpc --n 10
Example What it shows
hello-world A minimal ctx.run / ctx.rpc chain
fibonacci Recursive durable invocations via run, rpc, or a mix
pipeline A multi-stage DAG with stages running in parallel
structured-concurrency The runtime never leaks an unawaited durable child
recovery Typed serialize/deserialize across the durability boundary
retries Resonate retrying a flaky leaf function until it succeeds
error-handling How a failure crosses the boundary and is re-raised
detached Fire-and-forget invocations decoupled from the parent
human-in-the-loop Suspending on a promise an external party resolves
polling Non-blocking progress tracking with handle.done()
rpc One worker dispatching to another by group
versioning Running several versions of one function side by side
saga Compensating completed steps when a later step fails
pydantic Pydantic BaseModel (de)serialization at the durability boundary
pydantic-ai Durable Pydantic AI agent runs

Integrations

Pydantic AI

resonate.ext.pydantic_ai makes Pydantic AI agent runs durable: wrap any agent in ResonateAgent and every run() executes as a durable workflow, with model requests and MCP server communication checkpointed as durable steps that are served from the journal on recovery instead of re-hitting the provider.

pip install "resonate-sdk[pydantic-ai]"
from pydantic_ai import Agent

from resonate.ext.pydantic_ai import ResonateAgent
from resonate.resonate import Resonate

resonate = Resonate(url="http://localhost:8001")

agent = Agent(
    "openai:gpt-5.2",
    instructions="You're an expert in geography.",
    name="geography",
)
durable_agent = ResonateAgent(agent, resonate)


async def main():
    result = await durable_agent.run("What is the capital of Mexico?", id="capital-1")
    print(result.output)

The optional id is the run's durable identity: retrying with the same id after a crash (or calling it twice) performs the work exactly once and returns the recovered result. Function tools run inline in the workflow body and are re-executed on replay; model and MCP steps are not. Because a crashed run recovers from its serialized parameters, run-time arguments that cannot be rebuilt from JSON (model, toolsets, output_type, callables) must be configured on the agent at construction time. Provider-level retries are best disabled in favor of Resonate's step retry policies (model_retry_policy / mcp_retry_policy).

Release files for resonate-sdk 0.8.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for resonate-sdk 0.8.1
File Size Uploaded
resonate_sdk-0.8.1.tar.gz 110.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for resonate-sdk 0.8.1
File Interpreter ABI Platform
resonate_sdk-0.8.1-py3-none-any.whl Python 3 none any Details

Total release size: 239.8 kB

Release files / resonate_sdk-0.8.1.tar.gz

Download URL resonate_sdk-0.8.1.tar.gz
Size 110.9 kB
Tags Source
SHA-256 checksum
How to use checksums
c8a24fc366a83729a2f48bf54edf51f82bee80cf3761f1973d47694d1208b665
BLAKE2b-256 checksum
How to use checksums
f7a22a70feb01682928bf0e4e00fdf5989066cd1e83322f4b122d67ed6e084db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","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}

Release files / resonate_sdk-0.8.1-py3-none-any.whl

Download URL resonate_sdk-0.8.1-py3-none-any.whl
Size 129.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d29f84f3f807325a0260e33e3aa23f1e73ca09410a57f92fb769dc661e37bb9f
BLAKE2b-256 checksum
How to use checksums
9c733268e46f774c39d733deca8d2c857b41c9a16ab2f87d1857db70e9290f61
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","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}

Release history Release notifications | RSS feed

This release

0.8.1 This release

2 release files

0.8.0

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.7

2 release files

0.6.6

2 release files

0.6.5

2 release files

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.6

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.12

2 release files

0.4.11

2 release files

0.4.9

2 release files

0.4.8

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.34

2 release files

0.1.33

2 release files

0.1.31

2 release files

0.1.30

2 release files

0.1.29

2 release files

0.1.23

2 release files

0.1.22

2 release files

0.1.21

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release 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