Skip to main content

Overview

The Restate Python SDK is open source and can be found on GitHub: (sdk-python repo).

🚀Set up your project in seconds

Have a look at the Python Quickstart!

Add the restate_sdk requirement to your Python project to start developing Restate services.

The Restate SDK lets you implement handlers. Handlers can either be part of a Service, a Virtual Object, or a Workflow. Let's have a look at how to define them.

Services

Services and their handlers are defined as follows:

import restate
from restate import Context, Service
my_service = Service("MyService")
@my_service.handler("myHandler")
async def my_service_handler(ctx: Context, greeting: str) -> str:
return f"${greeting}!"
app = restate.app([my_service])
  • Initialize a Service and specify the service name (here MyService).
  • The service definition contains a list of handlers. Each handler is annotated by @service_name.handler(), optionally you can override the name of the handler (here myHandler). This is the name that will be used to call the handler, here you would use <RESTATE_INGRESS_URL>/MyService/myHandler.
  • The function has the Restate Context as its first argument. Within the handler, you use the Context to interact with Restate. The SDK stores the actions you do on the context in the Restate journal to make them durable.
  • The handler input argument (at most one) and return type are optional and can be of any primitive type or a TypedDict. They need to be serializable with json.dumps and deserializable with json.loads. If not, you need to specify a custom serializer.
  • Finally, initialize the app and bind the service(s) to it. The SDK follows the ASGI standard to serve the app. The templates and examples use Hypercorn as the server. Have a look at the serving docs to learn more.

Virtual Objects

Virtual Objects and their handlers are defined similarly to services, with the following differences:

import restate
from restate import VirtualObject, ObjectContext, ObjectSharedContext
my_virtual_object = VirtualObject("MyVirtualObject")
@my_virtual_object.handler("myHandler")
async def my_object_handler(ctx: ObjectContext, greeting: str) -> str:
return f"${greeting} ${ctx.key()}!"
@my_virtual_object.handler(kind="shared")
async def my_concurrent_handler(ctx: ObjectSharedContext, greeting: str) -> str:
return f"${greeting} ${ctx.key()}!"
app = restate.app([my_virtual_object])
  • Initialize a VirtualObject and specify the object's name (here MyVirtualObject).
  • The first argument of each handler must be the ObjectContext parameter. Handlers with the ObjectContext parameter can write to the K/V state store. Only one handler can be active at a time, to ensure consistency.
  • You can retrieve the key of the object you are in via ctx.key().
  • If you want to have a handler that executes concurrently to the others and doesn't have write access to the K/V state, add kind="shared" as annotation argument and use the ObjectSharedContext. You can use these handlers, for example, to read K/V state and expose it to the outside world, or to interact with the blocking handler (e.g. resolve awakeables).

Workflows

Workflows are a special type of Virtual Objects, their definition is similar but with the following differences:

import restate
from restate import Workflow, WorkflowSharedContext, WorkflowContext
from restate.serde import Serde
my_workflow = Workflow("MyWorkflow")
@my_workflow.main()
async def run(ctx: WorkflowContext, req: str) -> str:
# ... implement workflow logic here ---
return "success"
@my_workflow.handler()
async def interact_with_workflow(ctx: WorkflowSharedContext, req: str):
# ... implement interaction logic here ...
return
app = restate.app([my_workflow])
  • Initialize a Workflow and specify its name (here MyWorkflow).
  • Every workflow implementation needs to have a handler annotated with @workflow_name.main() called run that implements the workflow logic. This handler uses the WorkflowContext to interact with the SDK. The run handler executes exactly one time per workflow execution/object.
  • The other handlers of the workflow are used to interact with the workflow: either query it, or signal it. They use the WorkflowSharedContext to interact with the SDK. These handlers can run concurrently with the run handler and can still be called after the run handler has finished.
  • Have a look at the workflow docs to learn more.

Now that you have a high-level idea of what a Restate service might look like, let's have a look at what the Restate Context allows you to do.