Python-Native BPMN: Workflows as Code

Python-native BPMN means you write a business process as plain Python code. No graphical editor, no hand-edited XML. The workflow lives in your codebase, next to the models it drives — versioned, reviewed, and tested like any other code.

Viewflow is an open-source BPMN workflow engine built on this idea. You write a Flow class in Python; Viewflow runs it in production and renders the BPMN diagram from the same source.

Why Define BPMN as Code?

Traditional BPMN tools store the process as an XML file that a graphical designer generates. That XML is the source of truth, and everything else — your code, your tests, your review process — works around it. Python-native BPMN inverts that: the code is the process. Four things follow from that choice.

Git History and Atomic Changes

Because the workflow is code, every change to it is a normal commit. You see who changed a gateway, when, and why — the same git blame and git log you already use.

The bigger win is atomicity. A real change usually touches the model and the process together: you add a field, add the task that fills it, and add the migration in one commit. With XML-based tools, the model lives in code but the process lives in a separate designer. The two drift apart, and you re-sync them by hand. Code-first keeps them in lockstep.

from viewflow import this
from viewflow.workflow import flow
from . import models, views

class ApprovalFlow(flow.Flow):
    process_class = models.ApprovalProcess

    start = (
        flow.Start(views.StartView.as_view())
        .Next(this.approve)
    )
    approve = (
        flow.View(views.ApproveView.as_view())
        .Next(this.check)
    )
    check = (
        flow.If(cond=lambda activation: activation.process.approved)
        .Then(this.end)
        .Else(this.start)
    )
    end = flow.End()

The diagram and the executable process come from this one class — no second file to keep in sync.

Real, Fast Tests

You test a Python workflow with the tools you already run in CI. Run a node in isolation, set the process state, and assert on which task comes next. No BPMN simulator, no clicking through a designer.

from django.test import TestCase
from viewflow.workflow import activation

class ApprovalFlowTests(TestCase):
    def test_approved_moves_to_check(self):
        process = ApprovalFlow.process_class.objects.create()
        task = process.task_set.create(flow_task=ApprovalFlow.approve)

        act = activation.Context(task)
        act.prepare()
        act.process.approved = True
        act.done()

        self.assertTrue(
            process.task_set.filter(flow_task=ApprovalFlow.check).exists()
        )

Because these are plain unittest (or pytest) tests, they run in milliseconds and gate every pull request. Process logic stops being the untested part of the system.

AI-Friendly by Construction

Large language models read and write Python well. They are far weaker at hand-writing valid BPMN 2.0 XML. When your process is a Python class, an AI assistant can propose a new gateway, refactor a branch, or explain what a flow does — working in the same language as the rest of your project.

This compounds with the points above. The model can read the git history to see how a process evolved, run the tests to check its own change, and submit the result as a reviewable diff. A workflow locked inside a proprietary designer offers the AI none of that context.

Refactor and Reuse

Code-first workflows are Python, so ordinary refactoring applies. Shared logic goes in a function or a mixin. Common patterns become base Flow classes. You reuse a view from one process in another. Copy-paste between XML diagrams gives you none of this.

Code-First vs. Graphical BPMN

Capability Python-native BPMN (Viewflow) XML / graphical BPMN
Source of truth Python code Generated XML file
Version control Native git diffs and blame Opaque XML diffs
Code review Standard pull requests Separate tooling, if any
Testing pytest / unittest Dedicated simulator
Model + process changes One atomic commit Two sources, synced by hand
AI support First-class (plain Python) Limited (BPMN XML)
Diagram Rendered from the code Drawn by hand

When a Graphical Designer Still Helps

Code-first is not a rejection of diagrams. Non-developers often need to read a process, and a rendered picture communicates better than a class. Viewflow keeps both: the code stays authoritative, and Viewflow renders the BPMN diagram from it. The picture never falls out of date with what runs. The PRO edition adds a visual frontend on top of the same code-defined flows.

Common Questions

What is Python-native BPMN?

Python-native BPMN is the practice of defining a business process in Python code — a class with tasks and gateways — instead of XML or a drag-and-drop designer. That code runs as the workflow and renders the diagram.

Is code-first BPMN better than a graphical designer?

For engineering teams, yes on the axes that matter to them: version control, code review, automated testing, and atomic changes alongside the data model. Graphical designers remain useful for letting non-developers read a process, which is why Viewflow renders the diagram from the code rather than replacing it.

Can I run BPMN workflows as Python code in production with Django?

Yes. Viewflow is an open-source BPMN engine for Django. You define the process as a Flow class and run it in production with support for parallel tasks, persistence, and Celery. See the workflow documentation.

Why is code-first BPMN a good fit for AI coding assistants?

AI assistants generate and refactor Python well, but struggle with valid BPMN 2.0 XML. A process written as a Python class lets the assistant use the project’s real context — its git history, its tests, and its diffs — to make and verify changes.

Next Steps