Python: Durable Support for Workflows#3630
Merged
dmytrostruk merged 30 commits intomainfrom Feb 17, 2026
Merged
Conversation
3663ba2 to
c54d3bb
Compare
Member
d8db985 to
b0e7c16
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds comprehensive workflow orchestration support to Azure Functions, enabling multi-agent workflows with conditional routing, parallel execution, and human-in-the-loop (HITL) patterns using Azure Durable Functions.
Changes:
- New workflow orchestration engine in
_workflow.pythat executes MAF Workflows using Durable Functions' generator-based model - Serialization utilities in
_serialization.pyfor cross-activity message passing - Capturing runner context in
_context.pyfor activity execution - Extended
AgentFunctionAppwith workflow parameter and auto-registration of agents - Four new samples (09-12) demonstrating shared state, stateless, parallel, and HITL workflow patterns
- Comprehensive unit and integration tests (152 unit tests, 14 integration tests)
- Bug fix: Updated
chat_client.as_agent()usage withdefault_optionsparameter
Reviewed changes
Copilot reviewed 47 out of 47 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
_workflow.py |
Main orchestration engine with HITL support, parallel execution, and edge group routing |
_serialization.py |
Serialization/deserialization for dataclasses, Pydantic models, and MAF types |
_context.py |
CapturingRunnerContext for activity execution without durable storage |
_app.py |
Extended AgentFunctionApp with workflow support and HTTP endpoints |
_agent_executor.py |
Added agent property to expose underlying agent |
| Samples 09-12 | Four new workflow samples with requirements, configs, and README files |
| Test files | Unit tests for workflow utilities and integration tests for all samples |
pyproject.toml |
Increased test timeout from 120s to 300s for workflow tests |
| Sample 07 | Fixed type annotations for Azure Functions worker compatibility |
Comments suppressed due to low confidence (1)
python/packages/azurefunctions/agent_framework_azurefunctions/_app.py:1056
- This import of module asyncio is redundant, as it was previously imported on line 9.
import asyncio
python/samples/getting_started/azure_functions/10_workflow_no_shared_state/function_app.py
Outdated
Show resolved
Hide resolved
python/samples/getting_started/azure_functions/10_workflow_no_shared_state/function_app.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/tests/integration_tests/testutils.py
Outdated
Show resolved
Hide resolved
python/samples/getting_started/azure_functions/07_single_agent_orchestration_hitl/demo.http
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_workflow.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_serialization.py
Outdated
Show resolved
Hide resolved
python/samples/getting_started/azure_functions/10_workflow_no_shared_state/function_app.py
Outdated
Show resolved
Hide resolved
5edfd45 to
3c3c325
Compare
larohra
reviewed
Feb 4, 2026
python/packages/azurefunctions/agent_framework_azurefunctions/_app.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_app.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_app.py
Outdated
Show resolved
Hide resolved
larohra
reviewed
Feb 4, 2026
python/packages/azurefunctions/agent_framework_azurefunctions/_context.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_context.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_serialization.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_serialization.py
Outdated
Show resolved
Hide resolved
alliscode
reviewed
Feb 4, 2026
python/packages/azurefunctions/agent_framework_azurefunctions/_workflow.py
Show resolved
Hide resolved
larohra
reviewed
Feb 4, 2026
python/packages/azurefunctions/agent_framework_azurefunctions/_workflow.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_workflow.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_workflow.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_workflow.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_workflow.py
Outdated
Show resolved
Hide resolved
python/packages/azurefunctions/agent_framework_azurefunctions/_workflow.py
Outdated
Show resolved
Hide resolved
2530661 to
3d7d917
Compare
larohra
approved these changes
Feb 10, 2026
c3843db to
42b6f97
Compare
larohra
approved these changes
Feb 12, 2026
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…_message_content_from_dict since it is not needed
- State.import_state/export_state are now sync (removed await) - Add State.commit() before export_state() in activity execution - Rename executor parameter shared_state -> state - Rename ctx.set_shared_state/get_shared_state -> set_state/get_state (sync) - WorkflowBuilder now takes start_executor as constructor kwarg - Update WorkflowOutputEvent -> WorkflowEvent with type='output' - Update RequestInfoEvent -> WorkflowEvent[Any] - Update SharedState -> State in test imports - Update duplicate agent name tests to match new warning behavior - Update sample README API references
- Add workflow samples 09-12 to 04-hosting/azure_functions/ - Adapt to ChatMessage -> Message rename from main - Adapt to pickle-based checkpoint encoding from main - Simplify _serialization.py to delegate to core encode/decode - Fix Message -> WorkflowMessage disambiguation in _context.py - Remove non-existent _checkpoint_summary import
4bfc4bd to
ea704ce
Compare
dmytrostruk
approved these changes
Feb 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
The
agent-framework-azurefunctionspackage currently supports single-agent and multi-agent orchestration via durable entities. However, it does not support MAF'sWorkflowabstraction — the graph-based orchestration model with conditional routing, parallel fan-out/fan-in, and human-in-the-loop (HITL) patterns. This PR bridges that gap by adding full workflow orchestration support to Azure Durable Functions, enabling developers to define workflows usingWorkflowBuilderand run them durably with automatic HTTP endpoints.Description
This PR adds workflow orchestration support to the
agent-framework-azurefunctionspackage, enabling MAFWorkflowgraphs to execute on Azure Durable Functions. The implementation adapts MAF's async edge-routing model to Durable Functions' generator-based orchestration model (yieldinstead ofawait).Architecture
The workflow engine distinguishes between two executor types and routes them differently:
DurableAIAgent)dafx-{executor_id})This design reuses MAF's edge group routing logic (
SingleEdgeGroup,FanOutEdgeGroup,FanInEdgeGroup,SwitchCaseEdgeGroup) while adapting execution to the DF generator model.New Modules
_workflow.py(978 lines)_context.py(168 lines)CapturingRunnerContext— captures messages/events during activity execution without durable storage_serialization.py(217 lines)encode_checkpoint_value/decode_checkpoint_value)Changes to Existing Modules
_app.py— ExtendedAgentFunctionAppto accept an optionalworkflowparameter. When provided, automatically:ValueErrorto logging a warning and skipping (needed because workflow extraction may produce overlapping agent lists)_build_error_response()static helper for consistent error JSON responsespyproject.toml— Increased test timeout from 120s to 300s (workflow integration tests with Azurite + Durable Task Scheduler need more time)Core Package Changes (Minimal)
_workflows/__init__.py— Exportedencode_checkpoint_value,decode_checkpoint_value, andStateso the azurefunctions package can reuse the core checkpoint encoding system_agent_executor.py— Added public.agentproperty toAgentExecutorso the azurefunctions package can extract the underlyingSupportsAgentRuninstance when extracting agents from workflow executorsHTTP Endpoints (Auto-registered)
/api/workflow/run/api/workflow/status/{instanceId}/api/workflow/respond/{instanceId}/{requestId}HITL (Human-in-the-Loop) Support
The workflow engine detects
RequestInfoEventinstances from executor activities, exposes them via the status endpoint aspendingHumanInputRequests, and useswait_for_external_eventto pause the orchestration. When a human response arrives via the respond endpoint, the orchestrator resumes and routes the response back through the executor's@response_handlermethod. Configurable timeout with automatic rejection on expiry.Samples (4 new)
09_workflow_shared_stateStatefor cross-executor data sharing10_workflow_no_shared_state11_workflow_parallel12_workflow_hitlrequest_info/@response_handlerEach sample includes
function_app.py, README.md,demo.http,host.json,local.settings.json.sample, andrequirements.txt. All samples support dual-mode execution: Azure Functions (default) or pure MAF with DevUI (--mafflag).Tests
test_workflow.pytest_utils.pyCapturingRunnerContext,reconstruct_to_typetest_app.pyAgentFunctionAppworkflow initialization, agent extraction, executor activity registrationtest_09_workflow_shared_state.pytest_10_workflow_no_shared_state.pytest_11_workflow_parallel.pytest_12_workflow_hitl.pyAll 152 unit tests and 14 integration tests pass.
Contribution Checklist