State machine orchestration for agent workflows.
Project description
FlatMachines (Python SDK)
State-machine orchestration for LLM agents. FlatMachines is agent-framework agnostic and uses adapters to execute agents from FlatAgents, smolagents, pi-mono, or other runtimes.
For LLM/machine readers: see MACHINES.md.
Install
pip install flatmachines[flatagents]
Optional extras:
flatmachines[cel]– CEL expression engineflatmachines[validation]– JSON schema validationflatmachines[metrics]– OpenTelemetry metricsflatmachines[smolagents]– smolagents adapter
Quick Start
from flatmachines import FlatMachine
machine = FlatMachine(config_file="workflow.yml")
result = await machine.execute(input={"query": "..."})
print(result)
workflow.yml
spec: flatmachine
spec_version: "0.10.0"
data:
name: reviewer
agents:
reviewer: ./reviewer.yml
states:
start:
type: initial
agent: reviewer
input:
code: "{{ input.code }}"
output_to_context:
review: "{{ output }}"
transitions:
- to: done
done:
type: final
output:
review: "{{ context.review }}"
Agent Adapters
FlatMachines delegates agent execution to adapters. Built-ins are registered automatically if their dependencies are installed:
- flatagent – uses FlatAgents configs (
flatmachines[flatagents]) - smolagents – executes
MultiStepAgentviaagent_ref.reffactories - pi-agent – Node bridge to pi-mono using
pi_agent_runner.mjs
Agent refs in data.agents can be:
- string path to a flatagent config
- inline flatagent config (
spec: flatagent) - typed adapter ref:
{ type: "smolagents" | "pi-agent" | "flatagent", ref?: "...", config?: {...} }
Custom adapters can be registered via AgentAdapterRegistry.
State Execution Order
For each state, the Python runtime executes in this order:
action→hooks.on_actionlaunch→ fire-and-forget machine(s)machine/foreach→ peer machines (blocking)agent→ adapter + execution strategyoutput→ render final output fortype: final
Jinja2 templates render input, context, and output. A plain string like context.foo resolves to the actual value (not a string).
Execution Types
execution:
type: retry
backoffs: [2, 8, 16]
jitter: 0.1
Supported: default, retry, parallel, mdap_voting.
Parallelism & Launching
machine: child→ invoke peer machine (blocking)machine: [a, b]→ parallelforeach: "{{ context.items }}"→ dynamic parallelismlaunch: child→ fire-and-forget; result is written to backend
Persistence & Resume
persistence:
enabled: true
backend: local # local | memory | sqlite
checkpoint_on: [machine_start, state_enter, execute, state_exit, machine_end]
SQLite backend (recommended for durable single-file persistence)
persistence:
enabled: true
backend: sqlite
db_path: ./flatmachines.sqlite # optional, defaults to flatmachines.sqlite
When backend: sqlite is declared, the SDK automatically selects:
SQLiteCheckpointBackendfor checkpoint storageSQLiteLeaseLockfor concurrency controlSQLiteConfigStorefor content-addressed config storage (auto-wired when no explicitconfig_storeis passed)
No imperative runner injection required — everything is driven from config.
db_path resolution order: config field → FLATMACHINES_DB_PATH env var → flatmachines.sqlite.
Resume with machine.execute(resume_from=execution_id). Checkpoints store MachineSnapshot including pending launches.
Hooks
Configure hooks via data.hooks:
hooks:
file: ./hooks.py
class: MyHooks
args: { ... }
Built-ins: LoggingHooks, MetricsHooks, WebhookHooks, CompositeHooks.
Invokers & Result Backends
Invokers define how peer machines are launched:
InlineInvoker(default)QueueInvoker(base class for external queues)SubprocessInvoker(python -m flatmachines.run)
Results are written/read via ResultBackend URIs: flatagents://{execution_id}/result.
Logging & Metrics
from flatmachines import setup_logging, get_logger
setup_logging(level="INFO")
logger = get_logger(__name__)
Env vars match FlatAgents: FLATAGENTS_LOG_LEVEL, FLATAGENTS_LOG_FORMAT, FLATAGENTS_LOG_DIR.
Metrics require flatmachines[metrics] and FLATAGENTS_METRICS_ENABLED=true.
CLI Runner
python -m flatmachines.run --config machine.yml --input '{"key": "value"}'
Examples (Repo)
- character_card
- coding_agent_cli
- custom_coding_workflow
- dfss_deepsleep
- distributed_worker
- dynamic_agent
- error_handling
- gepa_self_optimizer
- helloworld
- human-in-the-loop
- mdap
- multi_paper_synthesizer
- parallelism
- peering
- research_paper_analysis
- rlm
- story_writer
- support_triage_json
- writer_critic
Specs
Source of truth:
Project details
Release history Release notifications | RSS feed
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 flatmachines-2.3.0.tar.gz.
File metadata
- Download URL: flatmachines-2.3.0.tar.gz
- Upload date:
- Size: 105.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19c917b6227e62fde0a0cf496ac410dc4d74daf1efc9bc2118da8c4a7f04f0c9
|
|
| MD5 |
1ad71ce2063a1218ffb82966e76cbbb8
|
|
| BLAKE2b-256 |
262e75b07d219b1a3024a66263540264cd59e4cc2737859143ae461c855dc63b
|
File details
Details for the file flatmachines-2.3.0-py3-none-any.whl.
File metadata
- Download URL: flatmachines-2.3.0-py3-none-any.whl
- Upload date:
- Size: 128.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e86fca4c3745ef8261f23a4fd8521da1aa8b3ff25b330dcc4a1fddcd24885e2
|
|
| MD5 |
487195b6b20478bc723f7d08fa211e55
|
|
| BLAKE2b-256 |
673f0d15d067ce8c94adb318a058a6bda1ac996dd2bc8bf921681537fc342882
|