Install & Compatibility
Where this runs
tested against v0.18.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.940 runs
installs and imports cleanly · install 0.0s · import 0.633s · 37.2MB
glibcpy 3.10–3.940 runs
installs and imports cleanly · install 2.5s · import 0.598s · 37MB
33MB installed
● package 33MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
restate
✓ import restate
The primary import for accessing SDK components like Service, Context, and app.
Service
✓ from restate import Service
✗ import Service
Service is typically accessed via the top-level 'restate' import.
Context
✓ from restate import Context
✗ import Context
Context is typically accessed via the top-level 'restate' import and passed to handlers.
app
✓ from restate import app
✗ import app
The 'app' factory function is typically accessed via the top-level 'restate' import for serving services.
TerminalError
✓ from restate.exceptions import TerminalError
✗ from restate import TerminalError
TerminalError is in the `restate.exceptions` submodule, not directly under `restate`.
This quickstart defines a basic Restate service named 'MyService' with a single asynchronous handler 'greet'. Handlers receive a `restate.Context` object for durable operations and can process input to produce an output. To execute this service, it needs to be run within a Restate runtime environment, typically by using the `restate serve` CLI command after defining the service.
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'.")
Debug
Known issues
breakingSDK 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.fixUpgrade your `restate-sdk` to version 0.6 or higher. After upgrading, re-register your deployment with the Restate server.
affects: <0.6
breakingThe 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.fixReview and explicitly configure the retry policy for your LLM calls if the new defaults are not suitable for your application. This can often be done via service or handler-level configurations.
affects: 0.16.0+
gotchaUsing 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.fixAlways catch specific exceptions. For permanent, non-retryable errors, explicitly raise `restate.exceptions.TerminalError`. For transient errors, let them propagate to trigger Restate's built-in retry mechanism.
affects: All versions
gotchaIncompatible 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).fixEnsure your Restate SDK version is compatible with your Restate server version. Refer to the official Restate documentation for compatibility matrices. Upgrade either the SDK or the server as necessary.
affects: All versions
gotchaNew 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.fixIf you are using these advanced configuration options, ensure your Restate server is at least version 1.4 or 1.5, depending on the specific feature. Consult the in-code documentation or Restate release notes for exact version requirements.
affects: All versions if using older Restate Server
Errors
Common errors & fixes
Protocol violation error (RT0012) OR The service endpoint does not support any of the supported service protocol versions of the server (RT0013)
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.
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).
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())`. Upgrade
Version history
0.18.1latest on PyPI · released May 22, 2026
Audit
Dependencies
msgspecoptionalUsed for advanced serialization with the 'serde' extra.
openai-agentsoptionalUsed for native integration with OpenAI Agents SDK.
pytestoptionalTesting utility part of the 'harness' extra.
TestcontainersoptionalUsed by the testing harness to run a Restate Server in Docker.