Palm Engine — lightweight orchestration for multi-step transactional workflows
Project description
Palm Engine 🌴
Palm is a lightweight, Python-first orchestration engine built on a clean Behavior Tree foundation. It coordinates interactive wizards, data pipelines, and—over time—compute-heavy workloads with explicit contracts, durable state, and human-first tooling.
Current release line: 0.8.15 · See CHANGELOG.md · MIGRATION-0.6.md · SCOPE.md for roadmap
Installation
Palm is published on PyPI as palmengine. After install, you import palm and run the palm CLI — same names as in source development.
| What | Name |
|---|---|
| PyPI package | palmengine |
pip install |
pip install palmengine[cli] |
| Python import | import palm |
| CLI command | palm |
# End users — CLI + REPL
pip install palmengine[cli]
palm version --full
palm doctor
# Library only (no Rich / REPL)
pip install palmengine
# From source (contributors)
git clone https://github.com/JGabrielGruber/palmengine.git && cd palmengine
uv sync --group dev --extra cli
uv pip install -e ".[cli]"
Optional extras: [cli], [test], [dev], [all], [postgres], [mongodb].
Vision
Palm aims to be simple at the core and powerful at the edges:
- Human-first — interactive wizards, Rich CLI feedback, backtracking, resume after interruption
- Truth-seeking — pluggable state, persistent process instances, transactional commits
- Extensible — patterns, providers, and storages register at the edge; core stays pure
- Ambitious but honest — from onboarding wizards to multi-flow data pipelines and planned GPU kernel nodes
Behavior Trees are the control-flow foundation. Steps are nodes. Cross-cutting concerns (auth, guards, observability) belong in runtimes and optional BT guard nodes—not buried in step definitions.
What works today (0.8.15)
| Area | Capabilities |
|---|---|
| Core | Behavior tree, orchestration (apply_result authority), context, storage, resource, event, auth |
| State | DictStateSchema, scoped state, schema-aware snapshots (__palm:meta), observability events |
| Patterns | Wizard (layered validation, collection steps, summary/commit); parallel branches; DAG and ETL stubs |
| Executions | ExecutionPlan / ProcessPlan, DefinitionExecutor, prepare/submit batch API |
| Persistence | Production filesystem backend, StorageFactory, InstanceManager, durable resume across restarts |
| State snapshots | Optional StateSnapshotHook — bounded blackboard history for audit/debug (off by default) |
| Runtimes | EmbeddedRuntime, DaemonRuntime, ServerRuntime (HTTP), CLI + REPL |
| Middleware | JobHook, AuthMiddleware, drive observability, instance persistence, state snapshots |
| DX | Examples (schema-onboard, todo-builder, parallel-demo), numbered choice UX, just quality recipes |
flowchart LR
User[Developer / operator] --> CLI[CLI / REPL]
CLI --> ER[EmbeddedRuntime]
ER --> CM[common]
CM --> PAT[patterns]
CM --> INST[instances]
PAT --> BT[Behavior Tree]
INST --> STO[storage]
Quick start
pip install palmengine[cli]
palm version --full # version + registered plugins
palm doctor # health, definitions, instances
palm repl # interactive shell (default: `palm`)
palm flow start onboard # recommended — works for all patterns
# shortcut: palm start onboard
From source: uv sync --group dev --extra cli && uv pip install -e ".[cli]" then the same palm commands. Demo script: uv run python examples/full_demo.py.
Try the new examples:
palm flow start schema-onboard # layered state schemas + scopes
palm flow start todo-builder # dynamic todo list (collection step)
palm flow start parallel-demo # parallel wizard branches
CLI persistence: the CLI is a thin client of PalmApp. By default it uses in-memory storage (fast, non-durable). Set durable storage via flags or environment:
# Recommended for local work — persists instances under ./data/
export PALM_STORAGE_BACKEND=filesystem
export PALM_DATA_DIR=./data
# Or per invocation:
palm --storage-backend filesystem --data-dir ./data wizard start onboard
palm doctor and REPL startup show whether state will survive restarts. Instance
commands (list, status, snapshots, resume, prune) all resolve through the same
PalmApp.instance_manager — short ids from instance list work with prefix matching.
Global CLI flags (override env only when explicitly passed):
| Flag | Env | Purpose |
|---|---|---|
-b / --storage-backend |
PALM_STORAGE_BACKEND |
Storage backend (memory, filesystem, …) |
-d / --data-dir |
PALM_DATA_DIR |
Data directory for durable backends |
--config |
— | Optional .env-style config file |
-S / --enable-state-snapshot |
PALM_ENABLE_STATE_SNAPSHOT |
Capture state snapshot history |
--max-loaded-instances |
PALM_MAX_LOADED_INSTANCES |
InstanceManager LRU size |
--max-concurrent-active |
PALM_MAX_CONCURRENT_ACTIVE |
Active instance cap |
--scheduler |
PALM_DEFAULT_SCHEDULER |
inline or queued |
--format |
— | table (default) or json for scripting |
Settings precedence: PALM_* environment → --config file → CLI flags.
palm instance list # active (non-terminal) instances
palm instance list --all --format json # all instances, JSON for scripts
palm instance list --status WAITING_FOR_INPUT --flow quick
palm instance prune --dry-run # preview terminal instance cleanup
palm --format json instance status <id> # machine-readable status
The REPL uses smart tab-completion for commands, flow/process names, and instance ids
(active by default; --all includes terminal instances).
Persistent wizard resume
Process instances snapshot orchestrated work—wizard answers, step, status—and persist through storage so sessions survive restarts.
palm wizard start onboard
palm input Ada
palm instance list # note instance id
# Later, or in a new terminal:
palm process resume <instance_id>
palm input ada@example.com
# … continue through summary and commit
Shared StorageEngine across runtime lifetimes is required for cross-process resume (see DEVELOPMENT.md).
Durable filesystem storage (recommended for local dev and single-node deploys):
export PALM_STORAGE_BACKEND=filesystem
export PALM_DATA_DIR=./data # optional; defaults to ./data
palm wizard start onboard
palm input Ada
# Restart the CLI — instances and definitions persist under ./data/
palm process resume <instance_id>
State snapshots (optional)
Palm can record point-in-time blackboard captures at selected job status transitions—useful for audit trails, debugging wizard flows, and future time-travel replay. Snapshots are stored on each ProcessInstance as a bounded ring buffer (state_snapshots[]). The feature is off by default.
Enable via environment:
export PALM_ENABLE_STATE_SNAPSHOT=true
export PALM_SNAPSHOT_ON_STATUS='["WAITING_FOR_INPUT","SUCCEEDED","FAILED"]'
export PALM_MAX_SNAPSHOTS_PER_INSTANCE=10
palm wizard start onboard
palm input Ada
palm instance snapshots <instance_id> # inspect captured history
Enable in code:
from palm.app import PalmApp, PalmSettings
settings = PalmSettings(
enable_state_snapshot=True,
snapshot_on_status=["WAITING_FOR_INPUT", "SUCCEEDED"],
max_snapshots_per_instance=5,
)
with PalmApp(settings) as app:
app.create_runtime("embedded", autostart=True)
job = app.submit_flow("onboard")
snapshots = app.list_instance_snapshots(job.metadata["instance_id"])
Resume still uses the latest state_snapshot field (maintained by InstancePersistenceHook). Historical entries are for inspection—not replay yet. See ARCHITECTURE.md for middleware design and trade-offs.
Example flows
Definitions under examples/definitions/ auto-register at CLI startup.
| Example | Command | Highlights |
|---|---|---|
| Onboarding | flow start onboard |
Validation, summary + commit |
| Schema wizard | flow start schema-onboard |
Flow + per-step schemas, scoped resume |
| Todo builder | flow start todo-builder |
Collection step, dynamic lists, schemas |
| Parallel demo | flow start parallel-demo |
Concurrent branches, merge, branch scopes |
| Data ingestion | flow start ingest-wizard |
Resource action step, ETL companion flow |
| Approval | flow start approval |
Multi-field validation, commit handler |
| Quick demo | flow start quick |
Minimal wizard for resume experiments |
palm process list
palm process submit data-ingestion
palm doctor # shows flows with state schemas
Details: examples/README.md
CLI overview
| Command | Description |
|---|---|
palm / palm repl |
Interactive REPL |
palm doctor |
Diagnostics: health, plugins, definitions, instances |
palm version --full |
Version, Python, registered patterns/providers/storages |
palm process list | submit | resume |
Definition catalog and lifecycle |
palm instance list |
Persisted instances |
palm instance snapshots <id> |
State snapshot history for an instance (when enabled) |
palm flow start <flow> |
Start any flow (wizard, parallel, …) — recommended |
palm start <flow> |
Shortcut for flow start |
palm wizard start <flow> |
Wizard-only shortcut (legacy alias) |
palm input / palm back |
Drive or rewind an active flow |
Run palm --help for the full list.
Project structure
src/palm/
├── app/ # PalmApp orchestrator, settings, multi-runtime bootstrap
├── core/ # Pure engines (BT, orchestration, context, storage, …)
├── common/ # Shared coordination (plans, hooks, persistence, managers, StorageFactory)
├── instances/ # ProcessInstance + StateSnapshot models
├── definitions/ # FlowDefinition, ProcessDefinition
├── patterns/ # wizard, dag, etl (extensible)
├── providers/ # rest, graphql, postgres (extensible)
├── storages/ # memory, filesystem, postgres, mongodb (extensible)
└── runtimes/ # BaseRuntime, Embedded/Daemon/Server, CLI
examples/ # definitions/ + full_demo.py
SCOPE.md # vision, scope, roadmap
ARCHITECTURE.md # layers, middleware, BT model
archive/ # legacy + experimental (not imported)
Where Palm is headed
High-level direction (not all shipped yet). Full detail in SCOPE.md.
| Theme | Direction |
|---|---|
| Runtimes | WebSocket surface, persistent plan registry, richer server auth |
| Middleware | Runtime-level auth/observability; optional BT guard nodes for step policy |
| Resources | Deeper ResourceEngine integration in patterns and commit handlers |
| Compute | KernelLeaf GPU nodes, resident kernels, dataset staging (Parquet → context → kernel → artifact) |
| Observability | Structured events, long-running job management |
GPU batch prototypes live in archive/experimental/gpubatches/ as early R&D—not part of the supported API until promoted.
---
title: CPU vs GPU Execution Time
---
xychart
title "CPU vs GPU Batch Processing Time"
x-axis "Batch Size" ["32K", "65K", "131K", "262K"]
y-axis "Time (seconds)" 0 --> 60
line "CPU" [8.28, 14.37, 28.64, 57.14]
line "GPU" [0.026, 0.051, 0.100, 0.200]
Architecture & contribution
| Document | Contents |
|---|---|
| SCOPE.md | Vision, in/out of scope, roadmap, experimental areas |
| ARCHITECTURE.md | Layers, BT control flow, middleware model, engines |
| DEVELOPMENT.md | Setup, tests, adding patterns/backends |
| AGENTS.md | Rules for contributors and AI agents |
just dev # setup
just check # lint + types + tests
just palm-doctor # CLI health
just demo-full # end-to-end script
Philosophy
🌴 Palm grows where the sun meets the sea.
Orchestration should balance structure with flexibility—automation with mindful human participation. Palm keeps the core small and truthful, puts people first in interactive flows, and grows capability through registries and nodes rather than monolithic middleware.
Migration
- 0.5.x → 0.6.0 — see MIGRATION-0.6.md for removed aliases (
ExecutionBackend,EmbeddedMode, etc.) - 0.3.x legacy — code under
archive/is reference-only; never import fromarchive/in new work
License
MIT
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 palmengine-0.8.15.tar.gz.
File metadata
- Download URL: palmengine-0.8.15.tar.gz
- Upload date:
- Size: 179.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2d6c664baadc56832fc021f9a0bc02b8f7d19c2db06d4d9cc3f0d79d18af329
|
|
| MD5 |
6a52cc9d11bfd63715a374eba88e8b9e
|
|
| BLAKE2b-256 |
ba26a2f7ad82a13ba5d9391a13ac1f584c64c15209ed78446c5cd8751b459bd2
|
File details
Details for the file palmengine-0.8.15-py3-none-any.whl.
File metadata
- Download URL: palmengine-0.8.15-py3-none-any.whl
- Upload date:
- Size: 217.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8408d1308f40eb443fb76af30474b867e72457f250aced451c594052da4647fa
|
|
| MD5 |
9ada1e4ea7052016d8677f27a97f6c65
|
|
| BLAKE2b-256 |
2921f960372d23c0bebde9d81a3770d9f685b4539910774acbcd1ebc9b11e680
|