Skip to main content

temporalio-graphs

Static analysis for Temporal Python workflows that outputs Mermaid diagrams covering every possible execution path.

What it does

  • Parses workflow source with Python's AST; no Temporal server or activity execution required.
  • Detects activities, decision points (to_decision), signal/wait points (wait_condition), and child workflow calls.
  • Generates every path permutation (2^n across decisions + signals) with configurable limits to prevent explosion.
  • Emits validation warnings for unreachable activities and branch-limit overruns.
  • Optional multi-workflow view for execute_child_workflow() using reference, inline, or subgraph rendering modes.

Install

# Recommended for development
uv pip install temporalio-graphs

# Standard
pip install temporalio-graphs

Requires Python 3.10+ and temporalio>=1.7.1.

Quick start

from datetime import timedelta
from temporalio import workflow
from temporalio_graphs import analyze_workflow, to_decision, wait_condition

@workflow.defn
class PaymentWorkflow:
    def __init__(self) -> None:
        self.approved = False

    @workflow.run
    async def run(self, amount: int) -> str:
        await workflow.execute_activity(validate_payment, amount)

        if await to_decision(amount > 1_000, "HighValue"):
            await workflow.execute_activity(require_approval, amount)

        if await wait_condition(lambda: self.approved, timedelta(hours=24), "WaitForApproval"):
            await workflow.execute_activity(process_payment, amount)
            return "approved"

        await workflow.execute_activity(handle_timeout, amount)
        return "timeout"

print(analyze_workflow("payment_workflow.py"))  # Mermaid diagram string

String literal names are required for to_decision(..., "Name") and wait_condition(..., "Name") so they can be detected statically.

Configuration (GraphBuildingContext)

Create a context and pass it to analyze_workflow() or analyze_workflow_graph().

from temporalio_graphs import GraphBuildingContext

context = GraphBuildingContext(
    max_decision_points=10,   # decisions + signals allowed before warning
    max_paths=1024,           # hard cap on generated paths
    split_names_by_words=True,
    include_path_list=True,   # included when output_format="full"
    output_format="full",    # "mermaid", "paths", or "full"
    child_workflow_expansion="reference",  # also "inline" or "subgraph"
    graph_output_file=None,   # write to file when set
)

Key defaults: start/end labels "Start"/"End", decision edge labels "yes"/"no", signal edges "Signaled"/"Timeout".

Signal Visualization Options (Epic 8)

For analyze_signal_graph(), additional context options control signal discovery:

context = GraphBuildingContext(
    # Maximum recursion depth for signal-based workflow discovery (default: 10)
    signal_max_discovery_depth=10,
    # Emit warnings for signals that cannot be resolved to handlers (default: True)
    warn_unresolved_signals=True,
    # Strategy: "by_name" (default), "explicit", or "hybrid"
    signal_resolution_strategy="by_name",
    # Visualization mode: "subgraph" (default) or "unified"
    signal_visualization_mode="subgraph",
)
Option Type Default Description
resolve_signal_targets bool False Enable signal resolution for cross-workflow visualization
signal_target_search_paths tuple[Path, ...] () Additional directories to search for target workflows
signal_resolution_strategy Literal "by_name" Strategy: "by_name", "explicit", "hybrid"
signal_visualization_mode Literal "subgraph" Mode: "subgraph" or "unified"
signal_max_discovery_depth int 10 Maximum recursion depth for signal chain discovery
warn_unresolved_signals bool True Emit warnings for unresolved signals

Multi-workflow graphs

Use analyze_workflow_graph() when a parent workflow spawns children via execute_child_workflow().

from temporalio_graphs import analyze_workflow_graph, GraphBuildingContext

context = GraphBuildingContext(child_workflow_expansion="inline")
diagram = analyze_workflow_graph(
    "parent_workflow.py",
    workflow_search_paths=["./workflows"],
    context=context,
)

child_workflow_expansion modes:

  • reference (default): render children as [[ChildWorkflow]] nodes without multiplying paths.
  • inline: full end-to-end paths across parent and children.
  • subgraph: separate Mermaid subgraphs for each workflow.

Cross-Workflow Signal Visualization

Use analyze_signal_graph() when workflows communicate via peer-to-peer signals (external workflow handles).

from temporalio_graphs import analyze_signal_graph

# Analyze workflows connected by signals (Order -> Shipping -> Notification)
diagram = analyze_signal_graph(
    "workflows/order_workflow.py",
    search_paths=["workflows/"],
)
print(diagram)  # Mermaid diagram with connected subgraphs

Example output showing three workflows connected by signals:

flowchart TB
    subgraph OrderWorkflow
        s_Order((Start)) --> ProcessOrder[Process Order]
        ProcessOrder --> ext_sig_ship[/Signal 'ship_order'\]
        ext_sig_ship --> e_Order((End))
    end

    subgraph ShippingWorkflow
        sig_handler_ship{{ship_order}}
        s_Ship((Start)) --> ShipPackage[Ship Package]
        ShipPackage --> ext_sig_notify[/Signal 'notify_shipped'\]
    end

    subgraph NotificationWorkflow
        sig_handler_notify{{notify_shipped}}
    end

    %% Cross-workflow signal connections
    ext_sig_ship -.ship_order.-> sig_handler_ship
    ext_sig_notify -.notify_shipped.-> sig_handler_notify

    %% Signal handler styling
    style sig_handler_ship fill:#e6f3ff,stroke:#0066cc
    style sig_handler_notify fill:#e6f3ff,stroke:#0066cc

Signal Visualization Syntax

Element Mermaid Syntax Purpose
Subgraph wrapper subgraph Name ... end Groups workflow nodes
Signal handler {{signal_name}} Hexagon for signal reception
External signal [/Signal 'name'\] Trapezoid for signal send
Cross-workflow edge -.signal_name.-> Dashed edge between workflows
Handler styling fill:#e6f3ff,stroke:#0066cc Blue color for hexagons
Unresolved signal [/?/] Warning node when handler not found

Signal Types Comparison

Signal Type Function Shape
Internal (Epic 4) wait_condition() Hexagon {{name}}
Parent-Child (Epic 6) execute_child_workflow() Subroutine [[name]]
Peer-to-Peer (Epic 7-8) get_external_workflow_handle().signal() Trapezoid + Hexagon

Examples

Run the curated examples (linear, branching, signals, multi-decision, cross-workflow signals):

make run-examples
# or individually
python examples/simple_linear/run.py        # Linear workflow (Epic 2)
python examples/money_transfer/run.py       # Decision branches (Epic 3)
python examples/signal_workflow/run.py      # Wait conditions (Epic 4)
python examples/multi_decision/run.py       # Multiple decisions
python examples/signal_flow/run.py          # Cross-workflow signals (Epic 8)

The examples/signal_flow/ directory demonstrates peer-to-peer workflow signaling with three connected workflows (Order -> Shipping -> Notification). See expected_output.md for the expected Mermaid diagram.

Troubleshooting

  • Too many branches: Raise max_decision_points / max_paths in GraphBuildingContext or simplify the workflow; errors include the calculated path count.
  • Names missing: Decision/signal names must be string literals; variables and f-strings are ignored by static analysis.
  • Unsupported flow: Loops or dynamic activity names are not graphed; refactor to explicit steps or decisions.
  • Signals not resolved: Ensure search_paths includes directories containing target workflow files with @workflow.signal handlers.
  • Unresolved signal [/?/] node: Target workflow not found in search paths or no matching @workflow.signal handler exists. Check that signal name matches handler method name.
  • Multiple handlers warning: Multiple workflows handle the same signal name. This may be intentional (e.g., broadcast signals) or indicate naming conflicts. Review handler implementations.

Development

uv venv && source .venv/bin/activate
uv sync
pytest -v --cov=src/temporalio_graphs
mypy src/
ruff check src/ tests/ examples/
ruff format src/ tests/ examples/

Reference

  • API: docs/api-reference.md
  • Architecture rationale: docs/architecture.md, spike/EXECUTIVE_SUMMARY.md
  • Examples: examples/
  • License: MIT (LICENSE)

Metadata

Release files for temporalio-graphs 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for temporalio-graphs 0.4.0
File Size Uploaded
temporalio_graphs-0.4.0.tar.gz 19.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for temporalio-graphs 0.4.0
File Interpreter ABI Platform
temporalio_graphs-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 19.3 MB

Release files / temporalio_graphs-0.4.0.tar.gz

Download URL temporalio_graphs-0.4.0.tar.gz
Size 19.2 MB
Tags Source
SHA-256 checksum
How to use checksums
ec0a25e2328e483a05ea740d2a8092b6d1ddbcc58366f12c6232bb7ca334fd8c
BLAKE2b-256 checksum
How to use checksums
6df36224a42dbf50055423d577863e41106c7109e91eddc2cede53410fdce87c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.13

Release files / temporalio_graphs-0.4.0-py3-none-any.whl

Download URL temporalio_graphs-0.4.0-py3-none-any.whl
Size 78.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
af2ab72ebb9dee5434c16fde4c46876f773ce53f58c710f9f4d72c34b3623d79
BLAKE2b-256 checksum
How to use checksums
c7cf1e7a3edd13746eaa2f40f8e7f5545aad4144c08163770ee651ee5fd05ce4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.13

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page