execution_engine: temporal and your existing workflows, tools, and agents keep working.
Outside of configuration (and starting a Temporal worker), you rarely need to touch your code. The same
@app.workflow, @app.workflow_run, @app.async_tool, Agent, and AugmentedLLM APIs behave identically with Temporal behind the scenes.When to choose Temporal
| Reach for Temporal when… | Asyncio alone is enough when… |
|---|---|
| Workflows must survive restarts, deploys, or worker crashes. | Runs are short-lived and you can re-trigger them on failure. |
| Human approvals, scheduled delays, or days-long research loops are in scope. | The agent answers a single request synchronously. |
| You need history, querying, and signal support from the Temporal UI or CLI. | You only need to fan out a few tasks inside one process. |
Enable the Temporal engine
Switch the execution engine and point at a Temporal cluster (the examples assumetemporal server start-dev):
@app.workflow_run) are re-executed after a crash, while non-deterministic work—LLM calls, MCP tool calls, HTTP requests—is automatically offloaded to Temporal activities by the executor. mcp-agent handles that split for you; you keep writing straightforward async Python.
Run a worker
Workers poll Temporal for workflow/activity tasks. The helpercreate_temporal_worker_for_app wires your MCPApp into a worker loop:
Launch workflows (or tools) durably
The executor API is unchanged—Temporal persists the state machine behind the scenes:@app.async_tool so clients invoke a single tool call while Temporal handles retries and state:
Human approvals, pause, and resume
Temporal signals map directly toexecutor.wait_for_signal and executor.signal_workflow. The pause/resume workflow shipped in examples/mcp_agent_server/temporal demonstrates the flow:
mcp-agent workflows resume):
app.context.executor.signal_bus, so you can prototype locally and switch to Temporal when you need durability.
Nested tools and elicitation
The Temporal server example also shows how durable workflows call nested MCP servers and trigger MCP elicitation when a human response is required. Activities such ascall_nested_elicitation log progress via app.app.logger so the request trace and Temporal history stay aligned.
Configure workflow-task modules and retry policies
Add optional top-level overrides to preload custom workflow tasks and refine retry behaviour:workflow_task_modulesentries are standard Python import paths; they are imported before the worker begins polling so@workflow_taskfunctions register globally.workflow_task_retry_policiesaccepts exact activity names, module or class suffixes (prefix.suffix), trailing wildcards likecustom_tasks.*, or the global*. The most specific match wins.- Retry intervals accept seconds (
1.5), strings ("2"), ortimedeltaobjects. - Marking error
types innon_retryable_error_typesprevents Temporal from re-running an activity when the failure is not recoverable (see the Temporal failure reference). For provider SDKs, useful values include:- OpenAI/Azure OpenAI:
AuthenticationError,PermissionDeniedError,BadRequestError,NotFoundError,UnprocessableEntityError. - Anthropic:
AuthenticationError,PermissionDeniedError,BadRequestError,NotFoundError,UnprocessableEntityError. - Azure AI Inference:
HttpResponseError(raised with non-retryable status codes such as 400/401/403/404/422). - Google GenAI:
InvalidArgument,FailedPrecondition,PermissionDenied,NotFound,Unauthenticated.
- OpenAI/Azure OpenAI:
- mcp-agent raises
WorkflowApplicationError(wrapping Temporal’sApplicationErrorwhen available) for known non-retryable provider failures, so these policies work even if you run without the Temporal extra installed. - Inspect an activity’s fully-qualified name via
func.execution_metadata["activity_name"]or through the Temporal UI history when adding a mapping. - Temporal matches
non_retryable_error_typesusing the exception class name string you supply (see the RetryPolicy reference). Use the narrowest names possible—overly generic entries such asNotFoundErrorcan suppress legitimate retries if a workflow expects to handle that condition and try again.
Operating durable agents
- Temporal Web UI (http://localhost:8233) lets you inspect history, replay workflow code, and emit signals.
- Workflow handles expose
describe(),query(), andlist()helpers for custom dashboards or integrations. - Observability: enable OpenTelemetry (
otel.enabled: true) to stream spans + logs while Temporal provides event history. - Deployment: mcp-agent Cloud uses the same configuration. Once deployed, Cloud exposes CLI commands (
mcp-agent workflows list,resume,cancel) that call the same signal/query APIs shown above.
Deeper dives
- Temporal example suite – side-by-side asyncio vs. Temporal workflows (basic, router, parallel, evaluator-optimizer) plus a detailed README walking through setup.
- Temporal MCP server – exposes durable workflows as MCP tools, demonstrates
workflows-resume, and includes a client script for pause/resume flows. - Temporal tracing example – shows the same code running with Jaeger exports once you flip the
execution_engine.
Example projects
- examples/temporal – basic workflow, evaluator-optimizer, router, and orchestrator patterns on Temporal.
- examples/mcp_agent_server/temporal – MCP server with durable human approvals, nested servers, and elicitation.
- examples/oauth/pre_authorize – demonstrates pre-authorised credentials for background Temporal workflows.
