resonate-basic-ephemeral-world-usage-python — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited resonate-basic-ephemeral-world-usage-python (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
The ephemeral world is anywhere your Python process starts: a main(), a FastAPI route, an HTTP handler, a script, a worker entry point. You use the Resonate class to register durable functions and invoke them. Once an invocation starts, it crosses into the durable world and Resonate guarantees its completion — retries on failure, resumes after crashes, continues across restarts.
This skill covers the Client API surface. The Durable World (Context APIs) lives in resonate-basic-durable-world-usage-python.
resonate-sdk on PyPI.resonate dev starts one on localhost:8001). The Rust server v0.9.x runs on a single port — no separate store port.uv add 'resonate-sdk>=0.7.0'
# or: pip install 'resonate-sdk>=0.7.0'
# or: poetry add 'resonate-sdk>=0.7.0'from __future__ import annotations
import os
from resonate.resonate import Resonate
url = os.environ.get("RESONATE_URL", "http://localhost:8001")
# Connect to a Resonate server
r = Resonate(url=url)
# With a named group (required for rpc routing to a specific worker pool)
r = Resonate(url=url, group="order-workers")
# With a default retry policy
from resonate.retry import Never
r = Resonate(url=url, retry_policy=Never())One Resonate instance per process. The server is always required for durable execution across restarts and multi-process coordination.
Durable functions in the Python SDK v0.7.0 are async def coroutines. Register them explicitly after definition:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from resonate.context import Context
async def process_order(ctx: Context, order_id: str) -> dict:
# ctx is the Context; everything inside the function body runs in the durable world
return {"order_id": order_id, "status": "done"}
r.register(process_order)Registration name defaults to the function name. To override (useful for RPC when caller and callee are in different codebases):
r.register(process_order_v2, name="process_order", version=2)With a per-function retry policy:
from resonate.retry import Exponential
r.register(charge, retry_policy=Exponential())The ephemeral world is where you construct things that durable code shouldn't build itself — database connections, HTTP clients, config objects. Register them by type:
import psycopg
conn = psycopg.connect(DATABASE_URL)
r.with_dependency(conn)Inside a durable function, access them by type via ctx.get_dependency(MyType). Dependencies are references, not serialized state — keep them construction-heavy and usage-simple.
import asyncio
import time
async def main() -> None:
# r.run is SYNC — returns a handle immediately; await the handle's .result()
handle = r.run(f"order-{time.time_ns()}", process_order, "order-123")
result = await handle.result()
# One-liner form
result = await r.run(f"order-{time.time_ns()}", process_order, "order-123").result()
# Dispatch by name (rpc) — routes through the Resonate server to a worker group
result = await r.rpc(f"order-{time.time_ns()}", "process_order", "order-123").result()Invocation IDs are yours to choose and deterministic. Pick something stable that uniquely names this invocation across retries — f"order:{order_id}" is better than a random UUID, because the latter creates a new invocation every restart.
async def main() -> None:
handle = await r.get("my-invocation-id")
result = await handle.result()Returns a handle for the existing promise. Useful for a separate process (e.g., a status-check HTTP endpoint) to block on a workflow started elsewhere.
Sync/async asymmetry: r.run(...) is synchronous and returns a handle directly (no await). r.get(...) is asynchronous and must be awaited. This is intentional — run creates and enqueues immediately; get performs a network lookup to find the existing promise.
Options configure the invocation. For top-level calls, options come first on the Resonate instance:
from resonate.retry import Exponential, Constant, Linear, Never
handle = r.options(
target="backend", # RPC routing group
retry_policy=Exponential(), # or Constant(), Linear(), Never()
version=2, # function version for schema evolution
).rpc(f"order-{time.time_ns()}", "process_order", "order-123")
result = await handle.result()External promises let a process outside the durable function resolve or reject it. This is the primitive behind human-in-the-loop workflows, webhooks, and any "wait for external event" pattern.
from datetime import timedelta
from resonate.types import Value
# resolve a promise (e.g. from a webhook handler)
await r.promises.resolve("approval-ord-123", Value(data={"approved": True}))
# or reject it
await r.promises.reject("approval-ord-123", Value(data={"reason": "denied"}))
# query state
record = await r.promises.get("approval-ord-123")All r.promises.* methods are async — always await them.
from datetime import timedelta
sched = await r.schedule(
id="nightly-digest",
cron="0 9 * * *",
func_name="send_digest",
args=("user-123",),
promise_timeout=timedelta(minutes=30),
)Always stop the Resonate instance on exit:
try:
result = await r.run(id, fn, arg).result()
finally:
await r.stop()Ephemeral world (Client APIs, `Resonate` class):
r.with_dependency(obj))r.promises.resolve/reject/get)r.get)Durable world (Context APIs, used inside a registered function):
await ctx.run(...), await ctx.rpc(...))ctx.get_dependency(MyType))Top-level script:
from __future__ import annotations
import asyncio
import os
import time
from typing import TYPE_CHECKING
from resonate.resonate import Resonate
if TYPE_CHECKING:
from resonate.context import Context
async def greet(ctx: Context, name: str) -> str:
return f"Hello, {name}!"
async def main() -> None:
r = Resonate(url=os.environ.get("RESONATE_URL", "http://localhost:8001"))
r.register(greet)
try:
result = await r.run(f"greet-{time.time_ns()}", greet, "Alice").result()
print(result)
finally:
await r.stop()
if __name__ == "__main__":
asyncio.run(main())HTTP handler that starts a workflow:
@app.post("/orders")
async def create_order(body: OrderBody):
order_id = body.order_id
# Return immediately; workflow continues durably in the background
r.run(f"order:{order_id}", process_order, order_id)
return {"status": "started", "order_id": order_id}Pure-ephemeral coordinator that dispatches to workers over RPC:
handle = r.options(target="order-workers").rpc(
f"batch-{time.time_ns()}",
"nightly_reconciliation",
{"date": "2026-04-16"},
)
result = await handle.result()resonate-basic-durable-world-usage-python — the Context API companion; use after a function is registeredresonate-basic-debugging-python — what to do when workflows hang, replay unexpectedly, or raiseresonate-philosophy and durable-execution — foundational concepts; read these first if you're new to Resonate~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.