Durable AI Agents with Temporal
A short agent run can live inside one application process. A production agent that calls several services, waits for approval, or runs for hours has a different problem: it is now a distributed workflow that can fail between any two steps.
Temporal supplies durable execution for that workflow. It does not make the model smarter. It preserves orchestration progress so work can continue after worker crashes, network failures, rate limits, and long waits.
This page builds on AI Agents: Concepts, Patterns, and Frameworks.
Why An Agent Loop Needs Durability
Section titled “Why An Agent Loop Needs Durability”Consider an agent that performs these steps:
- Understand a request.
- Search several data sources.
- Ask specialist agents to analyze the results.
- Wait for a human to approve an action.
- Call an external API.
- Produce and store the final result.
If this runs only in process memory, a restart can lose the current step, model responses, tool results, and approval state. Restarting the entire task may repeat expensive model calls or external side effects.
Common failure cases include:
- a model provider returns a transient error or rate limit
- a tool call times out
- a worker stops after an external action succeeds but before recording success
- a deployment restarts workers while jobs are active
- the user approves an action the next day
- one specialist fails after several other specialists completed
Durability means the orchestration can recover from recorded progress. It does not mean every tool is automatically correct, idempotent, or secure.
The Three Layers
Section titled “The Three Layers”The video combines two complementary systems:
| Layer | Responsibility |
|---|---|
| OpenAI Agents SDK | Defines agents, tools, guardrails, handoffs, and the model-tool loop |
| Temporal | Persists workflow progress, schedules work, applies retries and timeouts, and resumes after failure |
| External systems | Perform the real model calls, API operations, database writes, and MCP requests |
The agent framework decides what should happen next. Temporal makes sure the chosen process can continue reliably.
Temporal’s Core Concepts
Section titled “Temporal’s Core Concepts”| Concept | Meaning for an agent system |
|---|---|
| Workflow | Deterministic code that coordinates the agent run |
| Activity | A model call, API call, database operation, file operation, or other nondeterministic unit of work |
| Worker | A process that executes workflow and activity code |
| Task Queue | The routing boundary between the Temporal Service and workers |
| Temporal Service | Stores history, schedules tasks, tracks timeouts, and coordinates recovery |
| Event History | The ordered record used to reconstruct workflow state |
| Signal or Update | A message that can change a running workflow, such as an approval decision |
| Query | A read-only request for current workflow state |
flowchart TB
C["Client<br/>starts or updates an agent run"] --> TS["Temporal Service"]
TS <--> EH[("Event History")]
TS --> Q["Task Queue"]
Q --> WF
subgraph WP["Worker process"]
WF["Workflow<br/>agent orchestration"]
MA["Activity<br/>model invocation"]
TA["Activity<br/>tool or API call"]
WF --> MA
MA --> WF
WF --> TA
TA --> WF
end
MA --> MP["Model provider"]
TA --> EX["External APIs, databases,<br/>files, or MCP servers"]
Workflow code is the durable coordinator. Activities contain operations that interact with the outside world.
Replay Is How Workflow State Returns
Section titled “Replay Is How Workflow State Returns”Temporal does not normally restore a workflow from a memory snapshot. It records an ordered Event History and re-executes the workflow code to reconstruct the same state.
For replay to work, workflow code must make the same decisions when given the same history. That is why normal nondeterministic operations do not belong directly in a workflow:
- network requests
- database queries
- direct file I/O
- model invocations
- system time or unrecorded randomness
Those operations run as activities. When an activity completes, its result is recorded. During workflow replay, the recorded result is supplied to the workflow instead of executing that successful activity again.
For an agent, this distinction is valuable. A completed model response can be reused during replay rather than requesting the same inference again. The workflow can then rebuild the route the agent took from the recorded observations.
Replay and retry are different:
- Replay reconstructs workflow state from history and does not recompute recorded activity results.
- Retry starts another attempt of an activity that did not record a successful completion.
Mapping The Agent Loop Onto Temporal
Section titled “Mapping The Agent Loop Onto Temporal”The official Temporal integration for the OpenAI Agents SDK uses this general mapping:
| Agent operation | Temporal placement |
|---|---|
| Agent loop and orchestration | Workflow |
| Model invocation | Activity |
| Tool that calls an API or performs I/O | Activity |
| Pure deterministic calculation | May run in workflow code if it follows workflow restrictions |
| Human approval | Workflow waits; a Signal or Update delivers the decision |
| Multi-agent sequence or parallel fan-out | Workflow orchestration, child workflows, or activities depending on the required recovery boundary |
The integration’s OpenAIAgentsPlugin configures model invocations as Temporal activities. Its activity_as_tool helper exposes an activity to the agent as a normal tool.
The current code shape is:
from datetime import timedelta
from agents import Agent, Runnerfrom temporalio import activity, workflowfrom temporalio.contrib import openai_agents
@activity.defnasync def lookup_customer(customer_id: str) -> dict[str, str]: # Network and database I/O belong in an activity. return {"customer_id": customer_id, "status": "active"}
@workflow.defnclass DurableSupportAgent: @workflow.run async def run(self, question: str) -> str: agent = Agent( name="Support agent", instructions="Use the available tools to answer the request.", tools=[ openai_agents.workflow.activity_as_tool( lookup_customer, start_to_close_timeout=timedelta(seconds=30), ) ], )
result = await Runner.run(agent, input=question) return result.final_outputThis example shows the boundary, not complete worker setup. The worker and client must also configure the OpenAIAgentsPlugin; use the official integration documentation for the current API and serialization requirements.
Choose The Durability Granularity
Section titled “Choose The Durability Granularity”There are two useful ways to compose agents with a durable workflow.
| Design | Recovery boundary | Tradeoff |
|---|---|---|
| Agent loop in a workflow; model and tools are activities | Each model or tool step can be recorded independently | Fine-grained recovery, but workflow determinism rules shape the implementation |
| A bounded agent run is one activity in a larger workflow | The complete agent run is one retry unit | Easier high-level composition, but a retry may repeat internal model and tool calls unless that agent runtime persists its own progress |
The official OpenAI integration supports the first design. The second can still be useful for short, isolated specialist runs when coarse retry behavior is acceptable.
Activity Retries Require Idempotency
Section titled “Activity Retries Require Idempotency”Temporal recommends that activities be idempotent because an activity attempt can run more than once.
The difficult case is:
- A tool performs an external side effect.
- The external system reports success.
- The worker fails before Temporal records activity completion.
- Temporal cannot know whether the external operation completed.
- The activity is attempted again.
sequenceDiagram
participant W as Workflow
participant S as Temporal Service
participant A as Tool activity
participant X as External API
W->>S: Schedule activity
S->>A: Execute attempt
A->>X: Perform operation with idempotency key
X-->>A: Operation succeeds
Note over A,S: Worker fails before completion is recorded
S->>A: Retry activity
A->>X: Repeat the same idempotent request
X-->>A: Return the original result
A-->>S: Activity completed
S-->>W: Recorded result
Useful protections include:
- send a stable idempotency key to APIs that support one
- enforce uniqueness for business operations in the database
- check whether an operation already completed before repeating it
- make repeated writes converge on the same final state
- separate reads from irreversible writes
- mark validation and policy failures as non-retryable
Temporal provides retry machinery. The activity implementation must provide safe business semantics.
Timeouts, Retries, And Heartbeats
Section titled “Timeouts, Retries, And Heartbeats”A durable activity still needs explicit limits.
| Control | Purpose |
|---|---|
| Start-to-Close timeout | Limits one activity attempt |
| Schedule-to-Close timeout | Limits the activity including queue time and retries |
| Retry policy | Controls delay, backoff, maximum attempts, and non-retryable failures |
| Heartbeat | Reports progress for a long-running activity and can preserve checkpoint details between attempts |
| Cancellation | Lets the workflow request that activity work stop |
Classify failures before choosing a retry policy:
- Retry temporary network failures, rate limits, and unavailable dependencies.
- Do not blindly retry invalid tool arguments, denied authorization, failed safety checks, or an impossible business condition.
- Bound retries so a broken agent does not consume unlimited time, tokens, or money.
Compensation Is Not Rollback
Section titled “Compensation Is Not Rollback”An external side effect cannot be erased by replaying workflow code. If a later step fails permanently, the workflow may need a compensating action.
flowchart TB
W["Withdraw funds"] --> D["Deposit to destination"]
D -->|Success| C["Transfer complete"]
D -->|Permanent failure| R["Compensating activity<br/>refund source account"]
R --> F["Transfer closed as failed"]
Compensation is a new business operation, not a database rollback across unrelated services. It must have its own idempotency, retries, authorization, and audit trail.
The same pattern applies to agents that create tickets, send messages, reserve inventory, modify files, or trigger deployments.
Human-In-The-Loop Without Holding A Process Open
Section titled “Human-In-The-Loop Without Holding A Process Open”A workflow can wait durably for human input. It does not need to keep a thread, HTTP connection, or worker process alive for the entire wait.
Temporal provides three message types:
| Message | Use |
|---|---|
| Signal | Asynchronous write, such as submitting an approval without waiting for a response |
| Update | Tracked write whose sender can wait for validation, completion, or an error |
| Query | Read the current workflow state without changing it |
A sensitive agent action can therefore follow this pattern:
- The workflow records the proposed action and enters a waiting state.
- The application shows the exact action to an authorized user.
- A Signal or Update delivers approve, reject, or edited parameters.
- The workflow validates expiry and policy.
- An activity performs the approved action.
- The result and actor are recorded for audit.
Durable waiting does not replace authorization. Follow the controls in Agent Identity and Delegated Access: verify the approver, bind approval to exact parameters, enforce an expiry, and recheck policy before execution.
Durable Multi-Agent Orchestration
Section titled “Durable Multi-Agent Orchestration”Temporal can make code-directed multi-agent patterns recoverable:
- run a triage agent, then call the selected specialist
- fan out independent research agents and join their results
- loop between planning and evaluation with a maximum iteration count
- wait for clarification before continuing
- run compensation when a later action fails
Model-directed handoffs can also run inside the durable agent loop. Once a model activity result is recorded, replay sees the same handoff decision. Temporal preserves the route; it does not decide whether that route was a good choice.
For large systems, use separate activities or child workflows when a specialist needs independent retries, cancellation, ownership, or observability. Do not turn every prompt into a separate agent merely because the framework supports it.
MCP Has Its Own Durability Boundary
Section titled “MCP Has Its Own Durability Boundary”Temporal can durably retry the activity that talks to an MCP server, but it cannot recreate state that existed only inside that external MCP server.
The official integration distinguishes stateless and stateful MCP servers:
- A stateless operation contains everything needed for one call and can normally be retried against a restarted server.
- A stateful server may depend on an in-memory session established by earlier calls. If that session disappears, Temporal cannot reconstruct it unless the application has persisted enough state to establish it again.
Durable orchestration stops at the boundary of systems that do not participate in the same history and recovery model.
What Temporal Does Not Solve
Section titled “What Temporal Does Not Solve”Temporal does not automatically provide:
- correct prompts or reliable model judgment
- tool authorization and least-privilege credentials
- protection from prompt injection
- semantic validation of model output
- idempotency for external side effects
- durability inside external APIs or stateful MCP servers
- evaluations for agent quality
- unlimited workflow history
Long-lived workflow definitions also need versioning discipline. A code change that makes replay choose a different path can cause nondeterminism errors for existing executions. Use the SDK’s supported versioning or patching mechanisms when changing workflow logic.
For indefinitely running agents, event histories can grow large. Continue-As-New, child workflows, or bounded runs may be needed to control history size.
When Temporal Is Worth The Complexity
Section titled “When Temporal Is Worth The Complexity”| Use Temporal or another durable runtime when | A simpler process may be enough when |
|---|---|
| A task runs for minutes, hours, or days | One request normally finishes in seconds |
| Completed steps are expensive to repeat | Restarting the request is cheap and safe |
| The agent waits for people or external events | There are no long waits |
| External actions need retries and compensation | The agent only generates text |
| Work must survive deployments and worker failure | Occasional restart from the beginning is acceptable |
| Several agents or services must coordinate reliably | One bounded model call and tool call solve the task |
Temporal is one option. The OpenAI Agents SDK also documents integrations with Dapr, Restate, and DBOS. Evaluate operational model, language support, hosting, state requirements, and failure semantics rather than assuming every agent needs the same runtime.
Key Takeaways
Section titled “Key Takeaways”- The agent framework supplies intelligence and the model-tool loop; Temporal supplies durable execution.
- Workflow code coordinates deterministically. Model calls and I/O tools belong in activities.
- Replay reconstructs state from Event History and reuses recorded activity results.
- Activity retries may repeat external operations, so idempotency remains an application responsibility.
- Signals and Updates let a workflow wait for human decisions without keeping a process alive.
- Compensation handles previously committed side effects when a later step fails.
- Durability does not replace authorization, security, evaluation, or external-system recovery.
Resources
Section titled “Resources”- Building Durable, Production Ready Agents - Cornelia Davis, Temporal
- Temporal documentation
- Temporal Workflows and replay
- Temporal Activities
- Temporal Workflow message passing
- Temporal server repository
- Temporal Python SDK repository
- OpenAI Agents SDK integration for Temporal
- Temporal OpenAI Agents SDK samples
- OpenAI Agents SDK documentation
- OpenAI Agents SDK repository
- OpenAI durable execution integrations