Axon is a small, extensible framework for defining, discovering, and running ordered flows. Each flow combines a
strict Pydantic configuration, Python callables executed in order, a shared runtime context, and declared outputs.
Applications install their flows as providers and expose them through the same axon command.
The distribution is named axonx; the Python package and command are both named axon.
Framework at a glance
| Layer | Contract | Responsibility |
|---|---|---|
| Configuration | BaseConfig |
Validates typed inputs with unknown fields forbidden. |
| Flow | BaseFlow |
Owns configuration, logger, shared context, steps, and outputs. |
| Step | Callable[[], None] |
Performs one unit of work and reads or updates the flow context. |
| Registry | @register("name") |
Maps a normalized action name to one flow class. |
| Discovery | axon.flows entry points |
Imports installed provider modules so registration runs. |
| Runtime | axon --action --field value |
Parses inputs, validates configuration, executes steps, and emits JSON. |
Axon deliberately keeps orchestration close to Python. A concrete list builds a fixed sequence; a generator can use
normal if, for, and yield from control flow to decide later steps after earlier steps update the context. There is
no separate workflow DSL or scheduler.
Installation
Axon requires Python 3.11 or newer.
python -m pip install axonx
For framework development:
git clone https://github.com/FlowLLM-AI/Axon.git
cd Axon/packages
python -m pip install -e ".[dev]"
Quick start
The framework includes a small demo flow:
axon --list
axon --demo --x 1 --y 2
The successful result is written to stdout as JSON:
{"result": 3}
Every configuration argument is a --field value pair, including booleans. Hyphens in action and field names are
normalized to underscores. Unknown fields, duplicate fields, missing values, malformed values, and unknown actions
fail before flow execution.
Define a flow
Subclass BaseConfig for inputs and BaseFlow for orchestration. Annotating config lets Axon infer the configuration
class. build_steps() returns or yields zero-argument callables, while output_keys declares which context values
must exist after execution.
from collections.abc import Iterable
from axon.cli import BaseConfig, BaseFlow, Step, register
class GreetConfig(BaseConfig):
name: str
times: int = 1
@register("greet")
class GreetFlow(BaseFlow):
config: GreetConfig
output_keys = ("message",)
def build_steps(self) -> Iterable[Step]:
yield self.build_message
def build_message(self) -> None:
self.context["message"] = " ".join([f"hello {self.config.name}"] * self.config.times)
Import the module containing the class, then run:
axon --greet --name Axon --times 2
{"message": "hello Axon hello Axon"}
The execution contract is intentionally small:
| Element | Rule |
|---|---|
config annotation |
Must resolve to a BaseConfig subclass. |
build_steps() |
Returns an iterable of zero-argument callables in execution order. |
self.context |
Starts with constructor keyword arguments and carries state between steps. |
output_keys |
Names required context keys and preserves their declared order in the result. |
execute() |
Runs every yielded step, then raises if any declared output is missing. |
Dynamic orchestration uses ordinary Python:
| Pattern | Expression |
|---|---|
| Task | yield self.step |
| Sequence | yield from self.build_subsequence() |
| Conditional | Use if while lazily yielding steps. |
| For each | Loop and yield a zero-argument callable; use functools.partial to bind arguments. |
Because a generator resumes between steps, conditions placed after a yield can observe context written by the
previous step.
Publish a flow provider
An external package exposes its flows through the axon.flows entry-point group. For example, this repository's
pyproject.toml connects axon-core to the framework with:
[project.entry-points."axon.flows"]
default = "core.default"
Axon imports core.default, whose package initialization imports the modules containing @register(...). After the
provider is installed, its flows appear automatically:
axon --list
Built-in flows
This table describes flows shipped by axonx. Provider packages should document their own flows in the same format,
making the catalog easy to extend as new flows are added.
| Flow | Config | Inputs | Output | Purpose |
|---|---|---|---|---|
demo |
DemoConfig |
x: int, y: int |
result |
Demonstrates task, sequence, conditional, and loop-based step generation by adding two integers. |
Utilities
The supported helpers are exported from axon.utils. Add one row when a new public utility is introduced so this
table remains the compact public catalog.
| Utility | Signature | Configuration | Behavior |
|---|---|---|---|
load_env |
load_env(path=None, *, override=True) -> dict[str, str] |
Optional file path | Loads an explicit file or the nearest .env in the working directory or first five parents. Returns only values written to the environment. |
get_logger |
get_logger() |
AXON_LOG_DIR |
Lazily creates the shared Loguru INFO logger with stderr and daily rotating file sinks; file retention is seven days. |
send_dingtalk_message |
send_dingtalk_message(title, text, msgtype="markdown", timeout=10.0) -> str |
DINGTALK_CLIENT_ID, DINGTALK_CLIENT_SECRET, DINGTALK_CONVERSATIONS |
Sends Markdown or text through a DingTalk application robot to every configured, deduplicated conversation. |
DINGTALK_CONVERSATIONS must be a JSON object whose non-empty names map to non-empty conversation IDs, for example
{"research":"cidxxx","operations":"cidyyy"}. Credentials and group IDs are omitted from transport errors. Network
calls occur only when send_dingtalk_message() is invoked.
Environment variables
Axon calls load_env() before CLI provider discovery, allowing provider imports to resolve environment-based defaults.
| Variable | Used by | Default | Purpose |
|---|---|---|---|
AXON_LOG_DIR |
Shared logger | logs |
Directory for timestamped process log files. |
DINGTALK_CLIENT_ID |
DingTalk helper | Required on use | Application key and robot code. |
DINGTALK_CLIENT_SECRET |
DingTalk helper | Required on use | Application secret used to obtain an access token. |
DINGTALK_CONVERSATIONS |
DingTalk helper | Required on use | JSON object mapping names to group conversation IDs. |
Provider-specific variables belong in the provider's documentation rather than the framework package.
Package layout
| Path | Contents |
|---|---|
axon/cli.py |
Configuration and flow bases, registry, provider discovery, argument parsing, execution, and CLI. |
axon/flows/ |
Built-in flows; importing the package registers them. |
axon/utils/ |
Environment, logging, and notification helpers. |
tests/ |
Fast tests using temporary files and mocked network boundaries. |
Development
python -m pytest -v --tb=long
pre-commit run --all-files
python -m build
Keep provider-specific business logic outside the framework. A provider may depend on axonx; axonx must not
depend on that provider.
License
Licensed under the Apache License, Version 2.0. See LICENSE for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file axonx-0.0.1.tar.gz.
File metadata
- Download URL: axonx-0.0.1.tar.gz
- Upload date:
- Size: 21.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64bc73e85d4355d2045d8b608ba4466d3a52b704c1f22f810df3a6aeb042e422
|
|
| MD5 |
330fa1f44b311da9507612c1afe2f941
|
|
| BLAKE2b-256 |
0454b2e7ed3288573523e6d6bda095721d2afe698590899ce20d186cbef7c712
|
File details
Details for the file axonx-0.0.1-py3-none-any.whl.
File metadata
- Download URL: axonx-0.0.1-py3-none-any.whl
- Upload date:
- Size: 17.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c265ef1410d62b380e94a8b58990459e624dddaed05b40294995d6882bb5f08d
|
|
| MD5 |
7fc83ed7870a970454ab9b49749c4c36
|
|
| BLAKE2b-256 |
f055383ae980cadc7789e7502356541870794c52725a6114a1a6ccaf86860943
|