This sample workflow processes an expense request. It demonstrates human-in-the loop processing and asynchronous activity completion.
This sample demonstrates the following workflow:
-
Create Expense: The workflow executes the
create_expense_activityto initialize a new expense report in the external system. -
Wait for Decision: The workflow calls
wait_for_decision_activity, which demonstrates asynchronous activity completion. The activity registers itself for external completion using its task token, then callsactivity.raise_complete_async()to signal that it will complete later without blocking the worker. -
Async Completion: When a human approves or rejects the expense, an external process uses the stored task token to call
workflow_client.get_async_activity_handle(task_token).complete(), notifying Temporal that the waiting activity has finished and providing the decision result. -
Process Payment: Once the workflow receives the approval decision, it executes the
payment_activityto complete the simulated expense processing.
This pattern enables human-in-the-loop workflows where activities can wait as long as necessary for external decisions without consuming worker resources or timing out.
- You need a Temporal service running. See the main README.md for more details.
- Start the sample expense system UI:
uv run -m expense.ui
- Start workflow and activity workers:
uv run -m expense.worker
- Start expense workflow execution:
uv run -m expense.starter
- When you see the console print out that the expense is created, go to localhost:8099/list to approve the expense.
- You should see the workflow complete after you approve the expense. You can also reject the expense.
# Run all tests
uv run pytest expense/test_workflow.py -v
# Run a specific test
uv run pytest expense/test_workflow.py::TestSampleExpenseWorkflow::test_workflow_with_mock_activities -v- Human-in-the-Loop Workflows: Long-running workflows that wait for human interaction
- Async Activity Completion: Using
activity.raise_complete_async()to indicate an activity will complete asynchronously, then callingcomplete()on a handle to the async activity. - External System Integration: Communication between workflows and external systems via web services.
If you see the workflow failed, the cause may be a port conflict. You can try to change to a different port number in __init__.py. Then rerun everything.
workflow.py- The main expense processing workflowactivities.py- Three activities: create expense, wait for decision, process paymentui.py- A demonstration expense approval system web UIworker.py- Worker to run workflowsstarter.py- Client to start workflow executions by submitting an expense report