Temporal
In this section we explain Temporal, show practical use cases, and walk through Bluetext configuration
1. Temporal
Temporal is an open-source workflow orchestration tool which can be used to build long-running, fault-tolerant apps. Developers write workflow steps in normal programming languages, and Temporal guarantees that these steps will eventually complete, even if servers crash, deploy, fail, or lose connectivity. Temporal records workflow execution history as events and can replay code to exactly restore state.
Temporal workflows describe when things happen and in what order. Workflows are generally composed of one or more activities, which are the functions that perform the actual side effects such as calling external services, writing to databases, or sending emails.
In the context of an online clothing store, the ordering workflow is the process that coordinates the steps of ordering clothes, while the activities are the individual steps that make up the workflow, for example charging the payment, and sending the confirmation email.
The example below shows an example workflow for a clothes ordering workflow in the Temporal UI, from placing the order, to paying and entering your email for confirmation.

2. Temporal in Bluetext
Bluetext integrates Temporal through a three-phase tool discovery system. First, add-temporal scaffolds and starts the Temporal server, Postgres backend (which stores Temporal data), and UI as Polytope-managed containers. Second, add-temporal-client adds the temporal-client library, creates configuration and initialization hooks, and registers the add-temporal-workflow tool in polytope.yml, making it discoverable to AI agents. Third, when agents call the workflow tool, it automatically scaffolds complete workflow files with Pydantic models and activities, then registers them for immediate execution. This progressive enhancement enables AI agents to autonomously build Temporal functionality by first establishing server infrastructure, then client connectivity, and finally discovering workflow creation capabilities.
3. Setting up a Workflow
Use the following prompt to set up a minimal Temporal workflow and endpoints that demonstrate the basics of starting and signaling a workflow. The POST /flows endpoint starts a workflow that simply waits for a confirmation signal, and the POST /flows/:id/confirm endpoint sends that signal, causing the workflow to complete immediately.
I'm building a dummy API for testing temporal. Create an API with two endpoints:
1. POST /flows: creates a temporal workflow that waits for confirmation
2. POST /flows/:id/confirm: sends a confirmation for a running workflow (when the workflow receives this signal, it just completes without taking further action)Send a POST request to /flows to start the workflow; it will appear as Running in the Temporal UI. Then send a POST request to /flows/<workflowId>/confirm to complete it. After the signal, the workflow will show as Completed in the UI.
4. Common Patterns and Best Practices
This section covers the most common distributed workflow patterns and how to implement them in Temporal, along with best practices to ensure your system is scalable and maintainable.
The Sequencer (chain)
This is the simplest pattern where tasks must be executed one after another. If one fails, the process stops (or retries). An example of such a workflow could be charging a payment, where it makes no sense to proceed to the next steps if the payment fails or is cancelled. To implement this in Temporal, we would call activities sequentially using the await (or blocking) syntax.
await workflow.execute_activity(activityA)
await workflow.execute_activity(activityB)
await workflow.execute_activity(activityC)Temporal automatically persists the state after every step. If activityB fails, the worker crashes, or the DB goes down, Temporal resumes exactly at activityB without re-running activityA.
Parallel Execution
If you want to process multiple tasks simoultaneously, and agreggate results when all of them are finished, we implement it in Temporal by starting multiple activity futures in a loop and then awaiting workflow.wait_all() to continue only after all tasks have completed. An example of such a workflow could include sending a large number of text messages at once, or uploading multiple mp3 files somewhere simoultaneously
from temporalio import workflow
@workflow.defn
class FanOutFanInWorkflow:
@workflow.run
async def run(self, items: list[str]):
futures = []
# fan out – start all activities without waiting
for item in items:
fut = workflow.execute_activity(
process_item_activity,
item,
start_to_close_timeout=timedelta(seconds=10),
)
futures.append(fut)
# fan in – wait for all to complete
results = await workflow.wait_all(futures)
# continue after all are done
return resultsThe Saga (distributed transaction)
When you need data consistency across microservices that cannot share a database transaction, If step 3 fails, you must "undo" steps 1 and 2. If a failure occurs that cannot be fixed by retries, execute Compensations in reverse order. For example, booking a trip where you reserve a flight, hotel, and rental car, and must cancel the previous reservations if a later step fails (for example if there are no cars available).
Last updated