Azure / Azure/azure-functions-agents-runtime
Proposal: make Dynamic Workflow dependencies optional
- Dominant language
- Python
- Stars
- 9
- Forks
- 7
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 20
Description
## Summary
Make Dynamic Workflow dependencies optional so applications that do not enable workflows avoid installing and importing the Durable Functions stack.
Proposed installation experience:
```text
# Standard agents
pip install azurefunctions-agents-runtime
# Dynamic Workflows
pip install azurefunctions-agents-runtime[workflows]
# Dynamic Workflows with Azure Monitor
pip install azurefunctions-agents-runtime[workflows,monitor]
```
## Motivation
Dynamic Workflows depend on `azure-functions-durable`. With Durable Functions Python 2.x, this also brings in packages such as `durabletask`, `grpcio`, and `protobuf`.
A local measurement of the relevant installed distributions was approximately:
| Distribution | Installed size |
| --- | ---: |
| `azure-functions-durable` | 0.4 MiB |
| `durabletask` | 1.9 MiB |
| `grpcio` | 12.6 MiB |
| `protobuf` | 2.6 MiB |
| **Total** | **17.5 MiB** |
Today, `app.py` imports `azure.durable_functions` at module load time and imports `workflows.integration`, which imports the Durable engine. As a result, importing `azure_functions_agents` loads the Durable stack even when no agent enables Dynamic Workflows. In one local check, this loaded 85 Durable/grpc-related modules.
This increases deployment size and cold-start work for the default, non-workflow experience.
## Proposed design
### 1. Establish a lazy import boundary
Keep workflow configuration, schema, policy, decorators, discovery, and validation independent of the Durable SDK.
Move or isolate Durable-specific behavior behind a runtime boundary:
- `DFApp` creation;
- orchestrator and Activity registration;
- Durable client bindings and management operations;
- Durable engine implementation.
`create_function_app()` should first resolve agent configuration and build the workflow policy catalog. It should import the Durable runtime only when at least one agent has `workflows.enabled: true`.
```text
create_function_app()
-> load and validate agents
-> no workflow-enabled agents
-> create FunctionApp
-> do not import Durable
-> workflow-enabled agent exists
-> verify workflow dependencies
-> lazily import Durable runtime
-> create DFApp and register workflows
```
### 2. Add a `workflows` optional extra
Move `azure-functions-durable` from the default dependency set to:
```toml
[project.optional-dependencies]
workflows = [
"azure-functions-durable==...",
]
```
Workflow samples and documentation should install `[workflows]`; standard samples should remain on the lightweight default package.
### 3. Provide an actionable startup error
If an agent enables workflows without the extra installed, fail during app composition with a concise error such as:
```text
Dynamic Workflows are enabled, but workflow dependencies are not installed.
Install them with: pip install azurefunctions-agents-runtime[workflows]
```
Applications without workflow-enabled agents should not warn or fail when Durable is absent.
## User experience considerations
- Keep one runtime package and one version number; avoid a separate workflow package unless the extra proves insufficient.
- Use installation as the capability opt-in, following the existing `[monitor]` pattern.
- Do not add another frontmatter switch: `workflows.enabled` remains the feature declaration, while `[workflows]` supplies its runtime dependency.
- Detect a missing extra at startup rather than at the first workflow invocation.
- Update every workflow sample so copying its `requirements.txt` continues to work without additional discovery.
- Clearly document combinations such as `[workflows,monitor]`.
## Compatibility and rollout
This changes installation requirements for existing Dynamic Workflow users. Because the feature is currently experimental, making the split before a stable release minimizes long-term migration cost.
A safe implementation can use two PRs:
1. Refactor import boundaries and prove that non-workflow applications do not import Durable, while retaining the current hard dependency.
2. Move Durable to `[workflows]`, add missing-extra diagnostics, and update workflow samples and documentation.
## Acceptance criteria
- A default installation does not install `azure-functions-durable`, `durabletask`, or their workflow-only transitive dependencies.
- Importing `azure_functions_agents` does not import `azure.durable_functions`, `durabletask`, or `grpc`.
- Creating a non-workflow `FunctionApp` succeeds without Durable installed and does not load Durable modules.
- Enabling workflows without `[workflows]` fails at startup with an actionable installation command.
- Installing `[workflows]` preserves current Dynamic Workflow behavior and passes existing unit and real Functions-host E2E tests.
- Workflow samples install `[workflows]`; non-workflow samples do not.
- Package-size impact is measured and recorded before and after the change.
- Documentation covers default, workflow, monitor, and combined installation commands.
## Alternatives considered
### Lazy imports without changing dependencies
This can reduce import and cold-start work, but it does not reduce deployment size. It is useful as the first implementation step, not the complete solution.
### Separate workflow distribution
A package such as `azurefunctions-agents-runtime-workflows` could isolate dependencies more strongly, but it would add version synchronization, release, API, and support complexity. An optional extra should be preferred unless a technical constraint requires a separate distribution.
Contributor guide
Research direction
Start with app.py and create_function_app(), then trace workflows.integration and the current Durable imports. Inspect pyproject.toml, workflow and standard sample requirements, and related documentation. Done means non-workflow apps run without Durable imports or dependencies, workflow setup gives the specified missing-extra error, and existing workflow tests and samples remain valid.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, python
- Domain
- backend, cloud
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100