{"id":7196,"library":"durabletask","title":"Durable Task SDK for Python","description":"The `durabletask` library is a Python Client SDK for the Azure Durable Task Scheduler, enabling developers to define, schedule, and manage resilient and stateful workflows (orchestrations) using ordinary Python code. It is designed for building fault-tolerant, long-running processes. The current version is 1.4.0, and the project maintains an active release cadence.","status":"active","version":"1.4.0","language":"en","source_language":"en","source_url":"https://github.com/microsoft/durabletask-python","tags":["workflow","orchestration","distributed","azure","task"],"install":[{"cmd":"pip install durabletask","lang":"bash","label":"Install core SDK"}],"dependencies":[],"imports":[{"symbol":"DurableTaskClient","correct":"from durabletask import DurableTaskClient"},{"symbol":"DurableTaskWorker","correct":"from durabletask import DurableTaskWorker"},{"symbol":"OrchestrationContext","correct":"from durabletask import OrchestrationContext"},{"symbol":"Task","correct":"from durabletask import Task"},{"symbol":"TaskActivity","correct":"from durabletask import TaskActivity"}],"quickstart":{"code":"import os\nfrom durabletask import DurableTaskClient, DurableTaskWorker, OrchestrationContext, Task, TaskActivity\n\n# NOTE: For local development, ensure the Durable Task Scheduler emulator is running.\n# For example, using Docker: docker run --name dtsemulator -d -p 8080:8080 -p 8082:8082 mcr.microsoft.com/dts/dts-emulator:latest\nCONNECTION_STRING = os.environ.get(\"DURABLETASK_CONNECTION_STRING\", \"Endpoint=http://localhost:8080;Authentication=None\")\nTASK_HUB_NAME = os.environ.get(\"DURABLETASK_TASK_HUB_NAME\", \"default\")\n\nclass HelloActivity(TaskActivity):\n    async def run(self, context: OrchestrationContext, input: str) -> str:\n        print(f\"Executing HelloActivity with input: {input}\")\n        return f\"Hello, {input}!\"\n\nclass HelloOrchestrator(TaskActivity):\n    async def run(self, context: OrchestrationContext, input: str) -> str:\n        print(f\"Starting HelloOrchestrator with input: {input}\")\n        # Call an activity function\n        result = await context.call_activity(\"HelloActivity\", input)\n        print(f\"Orchestrator received result: {result}\")\n        return result\n\nasync def main():\n    client = DurableTaskClient(CONNECTION_STRING, TASK_HUB_NAME)\n    \n    # Register orchestrators and activities with the worker\n    worker = DurableTaskWorker(\n        CONNECTION_STRING,\n        TASK_HUB_NAME,\n        orchestrators={\n            \"HelloOrchestrator\": HelloOrchestrator()\n        },\n        activities={\n            \"HelloActivity\": HelloActivity()\n        }\n    )\n    \n    async with worker:\n        print(\"Worker started. Starting orchestration...\")\n        # Start a new orchestration\n        instance_id = await client.schedule_new_orchestration(\"HelloOrchestrator\", \"World\")\n        print(f\"Orchestration instance started: {instance_id}\")\n\n        # Wait for the orchestration to complete\n        status = await client.wait_for_orchestration_completion(instance_id, timeout_in_seconds=60)\n        if status:\n            print(f\"Orchestration '{instance_id}' completed. Status: {status.runtime_status}, Output: {status.output}\")\n        else:\n            print(f\"Orchestration '{instance_id}' did not complete within the timeout.\")\n\nif __name__ == \"__main__\":\n    import asyncio\n    asyncio.run(main())\n","lang":"python","description":"This quickstart demonstrates a simple 'Hello World' orchestration. It defines an activity (`HelloActivity`) and an orchestrator (`HelloOrchestrator`), registers them with a worker, and then schedules a new orchestration instance using the client. It assumes a Durable Task Scheduler emulator is running locally on `http://localhost:8080` (e.g., via Docker) and uses environment variables for configuration."},"warnings":[{"fix":"Upgrade your Python environment to 3.10 or a later supported version.","message":"Python 3.9 support was removed in version 1.3.0. The library now requires Python 3.10 or newer.","severity":"breaking","affected_versions":">=1.3.0"},{"fix":"For current time, use `context.current_utc_datetime` or similar deterministic APIs provided by the SDK. Ensure all operations within orchestrators are replayable.","message":"Orchestrator functions must be deterministic. Avoid direct use of non-deterministic operations like `datetime.datetime.now()` or `random.random()` within orchestrator code, as this can lead to replay mismatches and unexpected behavior. Instead, use context-provided deterministic alternatives.","severity":"gotcha","affected_versions":"all"},{"fix":"Wrap calls to activities in `try/except` blocks within your orchestrator to handle individual activity failures gracefully. Inspect `TaskFailedException.FailureDetails` for root cause information. Python does not support custom retry handlers directly in orchestrators; implement retry logic with loops, exception handling, and timers.","message":"When using `context.task_all` (or `Task.all`) to run multiple activities in parallel, the orchestration will fail immediately upon the *first* activity's failure, even if other activities might succeed. Error details are encapsulated in `TaskFailedException`.","severity":"gotcha","affected_versions":"all"},{"fix":"For Azure Durable Functions, refer to the Azure Functions documentation and use the appropriate SDK for your language (e.g., `azure-functions-durable` for Python).","message":"This SDK is *not* directly compatible with Azure Durable Functions. If you are building Durable Functions, use the `azure-functions-durable` package and its associated tools. This SDK targets the standalone Durable Task Scheduler.","severity":"gotcha","affected_versions":"all"},{"fix":"Ensure the connection string matches the expected format: `Endpoint=http://localhost:8080;Authentication=None` for the local emulator (note `http` and port 8080) or `Endpoint=https://<scheduler-name>.durabletask.io;...` for Azure (note `https`). Verify `Authentication` parameter and port usage.","message":"Incorrect connection string formats are a common cause of startup failures, especially when switching between local development (emulator) and Azure deployments.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Run `pip install durabletask` to install the package. Ensure your virtual environment is activated if you are using one.","cause":"The `durabletask` package is not installed in the current Python environment or the environment is not activated.","error":"ModuleNotFoundError: No module named 'durabletask'"},{"fix":"Check the Durable Task Scheduler dashboard (usually on port 8082 for the emulator) for errors. Verify that all activities called by the orchestrator are correctly registered with the `DurableTaskWorker`. Ensure external events are being raised, and activities are not silently failing.","cause":"This typically means the orchestration is waiting for a task (activity or sub-orchestration) that has not completed. Common reasons include an activity not being registered with the worker, waiting for an unraised external event, or an activity throwing an unhandled exception.","error":"Orchestration is stuck in the 'Running' state"},{"fix":"Ensure all calls to `async` functions within orchestrators, activities, and the main execution block are preceded by `await`. Confirm that your main application entry point uses `asyncio.run()` to initiate the asynchronous flow.","cause":"Python Durable Task SDK heavily relies on `asyncio` and `await`. This error often occurs when an `async` function is called without `await` or when `asyncio.run()` is not used correctly to start the event loop.","error":"TypeError: 'coroutine' object is not callable (or similar async/await issues)"},{"fix":"This specific error usually indicates a conflict or misconfiguration with Azure Durable Functions rather than the standalone Durable Task SDK. If you are building a Durable Function, ensure you are using the correct Durable Functions SDK (`azure-functions-durable`) and that your `host.json` has the correct extension bundle version. If using the Durable Task SDK, ensure it's not being deployed into a Durable Functions runtime environment unless explicitly supported via custom host.","cause":"This error points to an issue with Durable Functions extensions, often related to how extension bundles are cached or loaded, typically in Azure Functions environments when the Durable Task SDK is mistakenly used or conflicting dependencies exist.","error":"DurableTask.Netherite.AzureFunctions: Could not load file or assembly 'Microsoft.Azure.WebJobs.Extensions.DurableTask, Version=...' (or similar assembly loading error)"}]}