⚠️ Experimental — pattern exploration. APIs and behavior may change. Not recommended as a production dependency yet.
Part of the Azure Functions Python DX Toolkit — dogfood-tested by azure-functions-cookbook-python.
Read this in: 한국어 | 日本語 | 简体中文
Alpha Notice — This package is in early development (
0.1.0a0). APIs may change without notice between releases. Do not use in production without thorough testing.
Manifest-first graph runtime for Azure Functions with Durable Functions orchestration.
Part of the Azure Functions Python DX Toolkit → Bring FastAPI-like developer experience to Azure Functions
Running graph-shaped workflows on Azure Functions is harder than it should be:
- Orchestrator determinism — Durable Functions orchestrators must be deterministic; calling LLMs or tools directly inside them breaks replay safety
- Graph-to-runtime gap — Translating a node/edge graph design into Durable Functions activities requires repetitive plumbing
- No standard runtime — Each team builds its own wiring between graph definitions and Durable Functions primitives
- Manifest-first runtime — compile graph definitions into a stable, versioned manifest that the orchestrator reads without violating determinism
- Automatic HTTP API —
POST /api/graphs/{graph_name}/runs,GET /api/runs/{instance_id}, event injection, cancellation, and health endpoints are registered automatically - Deterministic orchestrator loop — all user logic (node execution, routing, event handling) runs in Durable Functions activities, never inside the orchestrator
- Conditional routing & external events — support for branching workflows and human-in-the-loop patterns via
RouteDecision
- Azure Functions Python v2 programming model
- Durable Functions orchestration via
azure-functions-durable - Pydantic v2-based state models
- Graph topologies: sequential, conditional, and event-driven
This package is independent of LangGraph and has no dependency on it. The name was inspired by LangGraph's node/edge model.
ManifestBuilderAPI for declaring graph nodes, routes, and event handlers- Deterministic Durable Functions orchestrator with configurable execution loop
- Typed state management via Pydantic v2 models
- Built-in HTTP endpoints: start run, get status, send event, cancel, health, OpenAPI
- Graph versioning with manifest-derived hash for safe deployments
pip install azure-functions-durable-graphYour Azure Functions app should also include:
azure-functions
azure-functions-durable
azure-functions-durable-graph
For local development:
git clone https://github.com/yeongseon/azure-functions-durable-graph-python.git
cd azure-functions-durable-graph
pip install -e .[dev]from pydantic import BaseModel
from azure_functions_durable_graph import DurableGraphApp, ManifestBuilder, RouteDecision
class MyState(BaseModel):
message: str
processed: bool = False
def process_message(state: MyState) -> dict:
return {"processed": True}
def finalize(state: MyState) -> dict:
return {"message": f"Done: {state.message}"}
builder = ManifestBuilder(graph_name="my_graph", state_model=MyState)
builder.set_entrypoint("process")
builder.add_node("process", process_message, next_node="finalize")
builder.add_node("finalize", finalize, terminal=True)
registration = builder.build()
runtime = DurableGraphApp()
runtime.register_registration(registration)
app = runtime.function_appPOST /api/graphs/my_graph/runs— starts a new graph executionGET /api/runs/{instance_id}— polls run statusGET /api/health— lists registered graphsGET /api/openapi.json— OpenAPI document
A few durable-specific concepts matter before you go to production. Each links to the full write-up in Durable Concepts.
- Orchestrator lifecycle — the orchestrator is deterministic and replay-safe:
it only reads the manifest, calls activities, and waits for events. It pins the
graph version via
graph_hashinOrchestrationInputand never runs LLM/tool code directly. - Manifest → registration → runtime —
ManifestBuilder.build()compiles a validated, hash-versionedGraphRegistration;register_registration()stores it; a run pins the currentgraph_hashand executes activities against it. - State-merge semantics — a handler returning a
dictis shallow-merged (top-level keys only), aBaseModelreplaces the state, andNoneleaves it unchanged. Nested dicts are not deep-merged — return the full nested object or a full model to update them. - Events & resume — a route handler can return
RouteDecision.wait_for_event(event_name, resume_node)to pause the run; deliver the event withPOST /api/runs/{instance_id}/events/{event_name}and execution resumes atresume_nodeafter the event handler's return value is merged into the state. host.jsonis required — Durable Functions needs the Durable Task extension and an extension bundle. See the Deployment guide.- Top gotchas — shallow-merge surprises, forgetting
host.json, and reusing a task hub across environments. See Troubleshooting.
sequenceDiagram
participant Client
participant HTTP as HTTP Endpoint
participant Orch as afdg_orchestrator
participant Act as Activities
Client->>HTTP: POST /api/graphs/{name}/runs
HTTP->>Orch: start_new("afdg_orchestrator", input)
loop until COMPLETE
Orch->>Act: afdg_execute_node(node, state)
Act-->>Orch: updated state
Orch->>Act: afdg_resolve_route(node, state)
Act-->>Orch: RouteDecision
alt wait_for_event
Orch->>Orch: wait_for_external_event
Orch->>Act: afdg_apply_event(event, state, payload)
Act-->>Orch: updated state
end
end
Orch-->>Client: final state
- You need graph-shaped LLM workflows on Azure Functions
- You want deterministic Durable Functions orchestration without manual activity wiring
- You need human-in-the-loop approval patterns (external events)
- You want versioned graph deployments with manifest-derived hashing
| Example | Pattern | Key Concepts |
|---|---|---|
| Data Pipeline | Sequential | next_node chaining, state accumulation — deterministic multi-step orchestration |
| Content Classifier | Conditional routing | RouteDecision.next(), fan-in topology — route handlers |
| Support Agent | Human-in-the-loop | wait_for_event / external events — pause-and-resume approval flow |
- Project docs live under
docs/ - New to durable graphs? Read Durable Concepts
- Deploying to Azure? See the Deployment guide and Choose a Plan
- Smoke-tested examples live under
examples/ - Product requirements:
PRD.md - Design principles:
DESIGN.md
Part of the Azure Functions Python DX Toolkit:
| Package | Role |
|---|---|
| azure-functions-openapi-python | OpenAPI spec generation and Swagger UI |
| azure-functions-validation-python | Request/response validation and serialization |
| azure-functions-db-python | SQLAlchemy-powered DB integration helpers (poll-based pseudo trigger, input/output/client injection) |
| azure-functions-langgraph-python | LangGraph deployment adapter for Azure Functions |
| azure-functions-scaffold-python | Project scaffolding CLI |
| azure-functions-logging-python | Structured logging and observability |
| azure-functions-doctor-python | Pre-deploy diagnostic CLI |
| azure-functions-durable-graph-python | Manifest-first graph runtime with Durable Functions (experimental) |
| azure-functions-knowledge-python | Knowledge retrieval (RAG) decorators |
| azure-functions-cookbook-python | Dogfood examples — runnable recipes that exercise the full toolkit |
This repository includes llms.txt and llms-full.txt in the root directory.
These files provide comprehensive package and API information optimized for LLM context windows.
llms.txt— Quick reference with core API, installation, and quick-start examplellms-full.txt— Complete reference with full signatures, patterns, design principles, and ecosystem context
Use these files to get better context when working with this package in AI-assisted coding environments.
This project is an independent community project and is not affiliated with, endorsed by, or maintained by Microsoft.
Azure and Azure Functions are trademarks of Microsoft Corporation.
MIT