Restate Python SDK
The `restate-sdk` is a Python SDK for Restate, a platform designed for building resilient applications using distributed durable async/await. It enables developers to implement durable backend services, virtual objects, and AI agents that can withstand failures and manage state reliably. The library is actively maintained with frequent minor version releases, integrating new features and improvements often.
Common errors
-
Protocol violation error (RT0012) OR The service endpoint does not support any of the supported service protocol versions of the server (RT0013)
cause The Restate Python SDK version is incompatible with the Restate server version it's trying to communicate with.fixCheck the Restate documentation for SDK-server compatibility. Upgrade your `restate-sdk` package or the Restate server to compatible versions. -
My Restate service keeps retrying indefinitely for an application-specific error, instead of failing permanently.
cause Restate, by default, retries all errors unless explicitly marked as terminal. Your application-specific error is being treated as a transient failure.fixFor errors that should not be retried (e.g., invalid input, business logic violations), raise `restate.exceptions.TerminalError('My error message')` in your handler. -
Non-deterministic behavior or unexpected state during replays when interacting with external systems (e.g., HTTP calls, random numbers).
cause External, non-deterministic operations or side effects are not being wrapped correctly within `ctx.run` blocks, which ensure their results are journaled and replayed consistently.fixWrap all external calls, non-deterministic computations, or any operation that should only execute once and whose result needs to be durable, inside `await ctx.run("unique-name", lambda: my_nondeterministic_op())`.
Warnings
- breaking SDK versions prior to 0.6 are deprecated and will be rejected by Restate server versions 1.5 and above. This can lead to registration failures for services deployed with older SDKs.
- breaking The default retry strategy for LLM calls within Restate AI integrations (e.g., `pydantic-ai`) changed in v0.16.0. It now defaults to 10 attempts with a 1-second minimum interval, potentially altering the behavior of existing AI agent workflows.
- gotcha Using broad exception handling like `except Exception:` or bare `except:` in Restate handlers is highly discouraged. This can inadvertently catch internal SDK exceptions, leading to non-deterministic behavior and breaking Restate's durable execution guarantees.
- gotcha Incompatible versions between the Restate SDK and the Restate server can lead to runtime errors like 'Protocol violation error' (RT0012) or 'The service endpoint does not support any of the supported service protocol versions of the server' (RT0013).
- gotcha New service/object/workflow constructor fields and handler decorator fields (e.g., `inactivity_timeout`, `abort_timeout`, `invocation_retry_policy`) only function correctly with Restate server versions 1.4 or 1.5 and newer.
Install
-
pip install restate-sdk -
pip install restate-sdk[serde] -
pip install restate-sdk[openai-agents] -
pip install restate-sdk[harness]
Imports
- restate
import restate
- Service
import Service
from restate import Service
- Context
import Context
from restate import Context
- app
import app
from restate import app
- TerminalError
from restate import TerminalError
from restate.exceptions import TerminalError
Quickstart
import restate
my_service = restate.Service("MyService")
@my_service.handler("greet")
async def greet(ctx: restate.Context, name: str) -> str:
# Use ctx.run to wrap any non-deterministic operations or external calls
# For this simple example, we'll just return a greeting.
return f"Hello {name}!"
# To run the service, typically you'd run this file with 'restate serve'
# or deploy it to a Restate runtime. For local testing, you can use:
# (This part is not runnable without a Restate runtime running)
# app = restate.app([my_service])
# app.run() # This would start an HTTP server
# Example of how to call this service (requires a running Restate server)
async def call_service_example():
# This client creation is for an ingress client (v0.12.0+)
async with restate.create_client("http://localhost:8080") as client:
# Assuming 'MyService' is registered and 'greet' handler is available
result = await client.object_call(my_service, key="unique-key", handler_name="greet", arg="World")
print(f"Service call result: {result}")
if __name__ == "__main__":
# For a full local setup and run, refer to Restate's Python Quickstart documentation.
# The provided code snippet defines a service, but doesn't run it as a standalone app
# without a Restate server or the 'restate serve' command.
import asyncio
# asyncio.run(call_service_example()) # Uncomment to try calling (requires Restate server)
print("Service 'MyService' with handler 'greet' defined. To run, use 'restate serve'.")