Approval¶
A flow that pauses for a human decision and resumes with the answer.
Source: examples/approval.py. Run it with python examples/approval.py while cereyan serve examples/ is running.
wait_for_input parks the run in Paused with a question. The engine is released
while the run waits; answering through the UI, the API, the client, or the MCP
resume_run tool schedules a new attempt that replays the flow from the top, where
tasks marked cache=INPUTS return their stored results and wait_for_input
returns the answer. This example runs against a server: start
cereyan serve examples/ first.
import time
from datetime import date
from cereyan import INPUTS, flow, get_run_logger, task, wait_for_input
from cereyan import client
@task(cache=INPUTS, persist_result=True)
def prepare(day: date) -> int:
get_run_logger().info("preparing %s", day)
return 1200
@task
def release(rows: int) -> str:
return f"released {rows} rows"
The flow¶
The question carries a JSON schema, which the run page turns into a form.
@flow
def publish(day: date) -> str:
rows = prepare(day)
decision = wait_for_input(
f"Release {rows} rows for {day}?",
schema={"type": "object", "properties": {"approve": {"type": "boolean"}}, "required": ["approve"]},
)
if not decision["approve"]:
return "held"
return release(rows)
Driving it from a script¶
Start the run, wait until it pauses, read the question, answer it, and wait for the result.
def wait_for(run_id: int, predicate, timeout: float = 30.0) -> dict:
deadline = time.time() + timeout
while time.time() < deadline:
run = client.get_run(run_id)
if predicate(run):
return run
time.sleep(0.1)
raise TimeoutError(f"run {run_id} did not reach the expected state")
if __name__ == "__main__":
run = client.run("publish", day="2026-03-01")
paused = wait_for(run["id"], lambda r: r["state"]["type"] == "Paused")
print("question:", paused["state"]["details"]["prompt"])
client.default_client().resume(run["id"], {"approve": True})
done = wait_for(run["id"], lambda r: r["state"]["type"] in ("Completed", "Failed", "Crashed", "Cancelled"))
assert done["state"]["type"] == "Completed", done["state"]
print("state:", done["state"]["type"])