Contributing examples
Conventions for adding runnable examples to the flux-src/examples/ folder so they ship as docs pages.
The examples/ folder in flux-src is two things at once. It is a runnable demo collection — every file is exercised end-to-end by tests/examples/ on every PR. And it is the source for the Examples section of this site, generated by site/scripts/python/generate_examples.py on every docs build.
Add an example when a workflow pattern is worth showing — not every internal test belongs as a public example, but anything that demonstrates a primitive, a control-flow pattern, or an integration is fair game.
File layout conventions
Top-level examples are single .py files in flux-src/examples/:
flux-src/examples/
├── hello_world.py
├── parallel_tasks.py
├── nested_tasks.py
├── output_storage.py
├── cancellation.py
├── github_stars.py
├── complex_pipeline.py
├── dataframe_with_pause.py
└── ...
Multi-file examples — ones that need fixtures, helpers, or a folder of supporting code — go in a subdirectory with a __main__.py or README.md:
flux-src/examples/
├── github_stars_parallel/
│ ├── __init__.py
│ ├── __main__.py
│ └── README.md
├── graph/
└── namespaces/
The generator treats a .py file or a directory containing __main__.py or README.md as one example. The slug for the docs page is derived from the filename: parallel_tasks.py becomes /examples/parallel-tasks/. The slugifier produces kebab-case-descriptive from snake_case_descriptive filenames; do not include spaces, dashes, or capitals in the source filename.
File structure
The opening docstring is the page subtitle. Keep it to one short paragraph that names the pattern and the point:
"""Parallel task execution.
Runs three greeting tasks concurrently and collects their results. Demonstrates
the parallel() built-in and the implicit fan-out / fan-in pattern.
"""
from flux import task, workflow, ExecutionContext
from flux.tasks import parallel
@task
async def say_hi(name: str) -> str:
return f"Hi, {name}"
@task
async def say_hello(name: str) -> str:
return f"Hello, {name}"
@workflow
async def parallel_greetings(ctx: ExecutionContext[str]):
return await parallel(
say_hi(ctx.input),
say_hello(ctx.input),
)
if __name__ == "__main__":
ctx = parallel_greetings.run("World")
print(ctx.output)
Every example ends in an if __name__ == "__main__": block so it runs as python examples/<name>.py. The tests/examples/ suite imports each example and runs the workflow inline, then asserts ctx.has_finished and ctx.has_succeeded. Examples that need an external service have to handle the missing-credential case.
Prerequisites and secrets
Examples that need API keys read them from environment variables — never hardcode keys, and never commit a .env:
"""Anthropic conversational agent.
Requires ANTHROPIC_API_KEY in the environment. Talks to claude-3-7-sonnet by
default; set FLUX_EXAMPLE_MODEL to override.
"""
import os
if not os.getenv("ANTHROPIC_API_KEY"):
raise SystemExit("Set ANTHROPIC_API_KEY before running this example.")
State the prereqs in the opening docstring so the generated page surfaces them above the code block. The generator looks for the second line of the docstring onward and renders it as the page’s lead paragraph.
The # docs: skip directive
Add # docs: skip to any source line you want excluded from the generated page. The generator strips marked lines before rendering the code block; the line still runs when the example is executed.
import os
from flux import workflow, task, ExecutionContext
os.environ.setdefault("FLUX_LOG_LEVEL", "WARNING") # docs: skip
Use this for noise the reader does not need to see — log-level shims, test-only os.environ defaults, debug prints. Do not use it to hide behavior that materially changes how the example works.
The # docs: skip pattern was identified during Phase 8 of the docs build as a way to keep example files runnable without cluttering the rendered page. See the existing examples for usage.
Ordering
The sidebar order of generated example pages is editorial, not alphabetic. site/scripts/python/examples-order.yml lists the preferred order:
order:
- hello-world
- simple-pipeline
- parallel-tasks
- subflows
- complex-pipeline
- pause-and-resume
- scheduled-workflow
- using-secrets
- github-stars
Slugs listed in order: appear first in that sequence. Slugs not listed appear after, sorted alphabetically. Edit examples-order.yml in the docs repo when you add an example that should sit in the pedagogical lead.
AI agent examples
The flux-src/examples/ai/ directory — conversational agents, blog-post writers, data-analysis agents, CrewAI integrations — has a README.md, so the generator discovers it and ships it as a single page (slug ai). What it does not do is recurse into the directory: the ~38 individual .py files inside examples/ai/ are not generated as separate pages. The generator treats a directory as one example and does not walk its contents.
So an AI example added under examples/ai/<name>.py is exercised by the test suite (tests/examples/ covers it) but does not get its own rendered docs page — it is folded into the single ai page.
If you add an AI agent example, put it under examples/ai/<name>.py next to the existing ones, write the docstring as usual, and note in the PR description that it will not surface as a standalone docs page. Giving individual AI examples their own pages would need a generator change (recurse into subdirectories, namespace the slug) plus editorial framing for provider-specific prereqs.
Running an example
# From the flux repo root
poetry install
poetry run python examples/parallel_tasks.py
# Or with poe
poetry run python -m examples.github_stars_parallel
Inline runs auto-register the workflow on first call, so examples work without flux start server. To exercise the distributed path:
# In one terminal
poetry run flux start server
# In another
poetry run flux start worker
# In a third
poetry run flux workflow register examples/parallel_tasks.py
poetry run flux workflow run parallel_greetings '"World"'
Pull request checklist
- One example per PR; do not bundle unrelated additions.
- The example file runs cleanly via
poetry run python examples/<name>.py. - The opening docstring is one paragraph and explains the pattern.
- Prereqs (API keys, optional extras) are listed in the docstring.
- A test exists in
tests/examples/test_<name>.pythat assertsctx.has_finished and ctx.has_succeeded. examples-order.ymlin the docs repo is updated if the example should appear above the alphabetic tail.- The framework version is bumped in
pyproject.toml(patch for example additions).
Reviewers run the example locally and read the rendered docs page in a preview build before merging.