Build with confidence.simple APIs.

ResonateEcho — the quality-of-life improvement developers have been yearning for.

asynchronoushuman-in-the-loopagent-in-the-loop

Painless human-in-the-loop

Suspend work for minutes or months while you wait for a human (or agent) to weigh in, then resume exactly where you left off.

Load balancing diagram
#process x
@resonate.register()
def myWorkflow(ctx, workflow_id):
    blocking_promise = yield ctx.promise()
    yield ctx.lfc(send_email, blocking_promise.id)
    # block the workflow until the promise is resolved
    yield blocking_promise
    # ...
    return "complete"

# process y
@app.route("/unblock-workflow", methods=["GET"])
def unblock_workflow_route_handler():
    # unblock a workflow by resolving a promise
    promise_id = request.args.get("promise_id")
    # resolve the promise
    resonate.promises.resolve(id=promise_id, ikey=promise_id)

Complex problems. Simple code.

Async/await — across services, agents, and humans.
Durable execution (retries and recovery) baked in.
Currently available in Python and TypeScript.
Dead simple, formally verified, and deterministically tested.
Highly configurable and extensible (serverless, transports, etc.).

Open source, open standards

Implements the open Distributed Async Await spec and the Async RPC protocol so discovery, load balancing, and recovery are transparent.

Join the community.

Connect with the engineers building resilient systems today. Share feedback, see what's shipping next, and learn how teams are scaling with Resonate in production.

Latest from the Resonate HQ Journal

Deep dives, release notes, and field reports from the team.

Read all posts
  • Loading the latest posts…

Jump into the Discord

Share ideas, swap implementation patterns, and hang out with engineers shipping Resonate in production.

Active right now

Check in for live threads and real-time support

Add a star to follow along

Stars help us reach more developers and signal which SDKs matter most. Plus, you'll stay in the loop as we ship new features.

View GitHub org

AI developer support

Provided by Kapa.ai, the leading AI developer support system, helps helps you ship faster with Resonate.

Ask Echo anything about the SDKs or runtime…

Resonate's Async APIs

A delightful set of asynchronous APIs that empower developers, not constrain them.

Resonate Run

The Resonate Run API, used in the ephemeral world, starts a Durable Execution in the same process.

Synchronous: resonate.run()

LocalSynchronousEphemeral to Durable
# bar() is in process x
# bar() is a durable function
@resonate.register
def bar(ctx: Context, arg: str):
  # ...
  return result


# foo() is in process x
# foo() is an ephemeral function
def foo():
  try:
    # Invoke bar() and await on the result
    result = bar.run("write_once_id", arg="hello world")
    # ...
  except Exception as e:
    # ...



Asynchronous: resonate.begin_run()

LocalAsynchronousEphemeral to Durable
# bar() is in process x
# bar() is a durable function
@resonate.register
def bar(ctx: Context, arg: str):
  # ...
  return result


# foo() is in process x
# foo() is an ephemeral function
def foo():
  try:
    # Invoke bar() and get a promise / handle
    handle = bar.begin_run("write_once_id", arg="hello world")
    # Use on the promise / handle to get the result
    result = handle.result()
  except Exception as e:
    # ...


Resonate RPC

The Resonate RPC API, used in the ephemeral world, starts a Durable Execution in another process.

Synchronous: resonate.rpc()

RemoteSynchronousEphemeral to Durable
# bar() is in process y
# bar() is a durable function
@resonate.register
def bar(ctx: Context, arg: str):
  # ...
  return result


# foo() is in process x
# foo() is an ephemeral function
def foo():
  try:
    # invoke bar() in process y and await on the result
    result = resonate.options(target="process-y").rpc(
      "write_once_id", func="bar", arg="hello world"
    )
  except Exception as e:
      # ...









Asynchronous: resonate.begin_rpc()

RemoteAsynchronousEphemeral to Durable
# bar() is in process y
# bar() is a durable function
@resonate.register
def bar(ctx: Context, arg: str):
  # ...
  return result


# foo() is in process x
# foo() is an ephemeral function
def foo():
  try:
    # invoke bar() in process y and get a promise / handle
    handle = resonate.options(target="process-y").begin_rpc(
      "write_once_id", func="bar", arg="hello world"
    )
    # Use the promise / handle to get the result
    result = handle.result()
  except Exception as e:
    # ...







Context Run

The Context Run API, used in the durable world, starts a Durable Execution in the same process.

Synchronous: context.run()

LocalSynchronousDurable to Durable
# baz is in process y
# baz() is a durable function
def baz(ctx: Context, arg: str):
  # ...
  return result


# bar() is in process y
# bar() is a durable function
@resonate.register
def bar(ctx: Context, arg: str):
  # invoke baz() and await on the result
  result = yield ctx.run(func=baz, arg=arg)
  return result


Asynchronous: context.begin_run()

LocalAsynchronousDurable to Durable
# baz() is in process y
# baz() is a durable function
def baz(ctx: Context, arg: str):
  # ...
  return result


# bar() is in process y
# bar() is a durable function
@resonate.register
def bar(ctx: Context, arg: str):
  # invoke baz() and get a promise
  promise = yield ctx.begin_run(func=baz, arg=arg)
  # Await on the promise to get the result
  result = yield promise
  return result

Context RPC

The Context RPC API, used in the durable world, starts a Durable Execution in a different process.

Synchronous: context.rpc()

RemoteSynchronousDurable to Durable
# baz() is in process z
# baz() is a durable function
@resonate.register
def baz(ctx: Context, arg: str):
  # ...
  return result

# bar() is in process y
# bar() is a durable function
@resonate.register
def bar(ctx: Context, arg: str): 
  # invoke baz() and await on the result
  result = yield ctx.rpc(func="baz", arg=arg).options(
    target="process-z"
  )
  return result




Asynchronous: context.begin_rpc()

RemoteAsynchronousDurable to Durable
# baz() is in process z
# baz() is a durable function
@resonate.register
def baz(ctx: Context, arg: str):
  # ...
  return result

# bar() is in process y
# bar() is a durable function
@resonate.register
def bar(ctx: Context, arg: str):
  # invoke baz() and get a promise
  promise = yield ctx.begin_rpc(func="baz", arg=arg).options(
    target="process-z"
  )
  # Await on the promise to get the result
  result = yield promise
  return result


Examples in action.

Resonate solves a wide range of distributed systems challenges. Run an example to see how it applies to your use case.

Extended directory

A full list of links to all of our resources.

© 2025 Resonate HQ, Inc.