AbstractRuntime is a durable workflow runtime (interrupt → checkpoint → resume) with an append-only execution ledger.
It is designed for long-running workflows that must survive restarts and explicitly model blocking (human input, timers, external events, subworkflows) without keeping Python stacks alive.
Version: 0.7.1 • Python: 3.10+
Status: pre-1.0 (API may evolve). For production use, pin versions and follow CHANGELOG.md.
AbstractRuntime is one component of the wider AbstractFramework ecosystem:
- AbstractRuntime (this repo) — durable workflow kernel (
src/abstractruntime/core/*) - AbstractCore — LLM + tools integration (wired via
src/abstractruntime/integrations/abstractcore/*)
Repo: lpalbou/abstractcore
At a high level, hosts define workflow graphs (WorkflowSpec) and AbstractRuntime executes them durably. When nodes request LLM/tool work (EffectType.LLM_CALL, EffectType.TOOL_CALLS), those effects are typically handled via AbstractCore.
flowchart LR
Host["Host app / orchestrator"] -->|"WorkflowSpec"| RT["AbstractRuntime"]
RT -->|"LLM_CALL / TOOL_CALLS"| AC["AbstractCore"]
AC -->|"results / waits"| RT
Remote-light runtime:
pip install abstractruntimeThe base install includes AbstractCore 2.18.0 or newer with remote provider,
tool, vision, voice, audio, and music integration, plus the
abstractruntime-mcp-worker entry point. It keeps inference remote/light by
default: local engines such as MLX, vLLM, HuggingFace/Torch, Diffusers, and
sentence-transformer embeddings are not selected unless you choose a hardware
profile or another package-specific local extra.
VisualFlow document nodes use permissive dependencies in Runtime's base install:
Read PDF extracts text and metadata with pypdf, Write PDF renders text or
Markdown-style report content to real PDF bytes with reportlab, and
Write DOCX renders Markdown-style report content to Word-compatible .docx
bytes with the Python standard library.
Native Python hardware profiles add local inferencer stacks:
pip install "abstractruntime[apple]"
pip install "abstractruntime[gpu]"abstractruntime[apple] delegates to AbstractCore's native Apple aggregate;
abstractruntime[gpu] delegates to AbstractCore's GPU aggregate.
from abstractruntime import Effect, EffectType, Runtime, StepPlan, WorkflowSpec
from abstractruntime.storage import InMemoryLedgerStore, InMemoryRunStore
def ask(run, ctx):
return StepPlan(
node_id="ask",
effect=Effect(
type=EffectType.ASK_USER,
payload={"prompt": "Continue?"},
result_key="user_answer",
),
next_node="done",
)
def done(run, ctx):
answer = run.vars.get("user_answer") or {}
text = answer.get("text") if isinstance(answer, dict) else None
return StepPlan(node_id="done", complete_output={"answer": text})
wf = WorkflowSpec(workflow_id="demo", entry_node="ask", nodes={"ask": ask, "done": done})
rt = Runtime(run_store=InMemoryRunStore(), ledger_store=InMemoryLedgerStore())
run_id = rt.start(workflow=wf)
state = rt.tick(workflow=wf, run_id=run_id)
assert state.status.value == "waiting"
state = rt.resume(
workflow=wf,
run_id=run_id,
wait_key=state.waiting.wait_key,
payload={"text": "yes"},
)
assert state.status.value == "completed"Kernel (import-light):
- workflow graphs:
WorkflowSpec(src/abstractruntime/core/spec.py) - durable execution:
Runtime.start/tick/resume(src/abstractruntime/core/runtime.py) - durable waits/events:
WAIT_EVENT,WAIT_UNTIL,ASK_USER,EMIT_EVENT - append-only ledger (
StepRecord) + node traces (vars["_runtime"]["node_traces"]) - retries/idempotency hooks:
src/abstractruntime/core/policy.py - runtime-aware limits (
_limits) with a default iteration budget of 20 (docs/limits.md) - Stop that reaches the running effect:
Runtime.cancel_run(...)signals the in-flight model or tool call, which ends as acancelledledger record (never retried); a model unload stops the calls using that model first (docs/api.md) - host pause at step boundaries:
Runtime.tick(..., step_gate=...) - run-tree tool ceiling: an explicit
allowed_toolslist can only narrow across child runs, and approval policy never widens it - automations: run a workflow on a schedule (
schedule@1, fixed UTC intervals) or on request (manual@1) as a durable controller run whose occurrences are deterministic child runs and session turns, with commands, independent or growing context, discussions forked at any occurrence (own workspace, automation workspace mounted read-only), tool approval, typed waits and quiet-by-default notifications (docs/automations.md) - explicit run ids:
Runtime.start(..., run_id=...)creates a run only if the id is free (RunStore.create_if_absent), andrun_mutation_lock(run_id)serializes a run's writers in a process
Durability + storage:
- stores: in-memory, JSON/JSONL, SQLite (
src/abstractruntime/storage/*) - durable command inbox primitives (idempotent, append-only):
CommandStore,CommandCursorStore(src/abstractruntime/storage/commands.py,src/abstractruntime/storage/sqlite.py) - artifacts + offloading (store large payloads by reference)
- snapshots/bookmarks (
docs/snapshots.md) - tamper-evident hash-chained ledger (
docs/provenance.md)
Drivers + distribution:
- scheduler:
create_scheduled_runtime()(src/abstractruntime/scheduler/*) - VisualFlow compiler + WorkflowBundles (
src/abstractruntime/visualflow_compiler/*,src/abstractruntime/workflow_bundle/*) - VisualFlow multi-entry execution lowering for fan-in routes and per-entry input overrides (
docs/workflow-bundles.md) - VisualFlow LLM Call and Agent nodes propagate Core generation params such as
thinkingandspeculationthrough Runtime effects;_runtime.speculationsets a run-wide MTP preference that nested workflows and Agent loops inherit. Provider Models nodes can apply Corecapability_routefilters so run-time model discovery matches Gateway/Flow authoring. - VisualFlow image/video nodes and Runtime media helpers preserve task-specific
Core media controls, including
count/n,seeds, orderedlora_adapters, and videoflow_shift, while keeping provider/model/task truth in AbstractCore and AbstractVision. history_bundleexports replay-saferesolved_actionssummaries derived from Core request/output route resolution, so thin clients can reconstruct what capability ran without reverse-engineering prompt prose.- VisualFlow structured LLM/Agent results preserve
responseas text and expose the schema-conformant object ondata, so Break Object and Switch can consume fields without reparsing the response string. - run history export:
export_run_history_bundle(...)(src/abstractruntime/history_bundle.py)
Runtime-owned integrations:
- AbstractCore (LLM + tools,
MODEL_RESIDENCYwith residency locks and context estimates, public discovery/host/run facades, cached sessions with per-session prompt-cache listing/clearing, host memory snapshots, local-only prompt-cache export/import admin, durable bloc prompt-cache controls, bindings, lifecycle operations, generated image/video/voice/music outputs with progress events, host email helpers, Telegram host wrappers, and tool approval waits):docs/integrations/abstractcore.md - AbstractCore models and engines for hosts:
config_facadepasses through the host profile, local-engine status and installs, the model catalog with fit verdicts, installed models, deletes, host jobs (with who-cancelled attribution) and the embeddable console screens:docs/integrations/abstractcore.md#models-engines-and-host-jobs-config-facade - For outbound comms, use the durable run facade when the send belongs to a run:
get_abstractcore_run_facade(...).send_email(...)/send_telegram_message(...). If that child run pauses for approval or passthrough execution, resume it throughresume_tool_calls(...). Direct host-facade send helpers and the standalone email comms facade remain host-local and nondurable. - AbstractMemory TripleStore integration for
MEMORY_KG_*effects. Runtime depends on the light AbstractMemory contract; hosts choose storage backends such as LanceDB, SQLite, or in-memory stores. - comms toolset gating (email/WhatsApp/Telegram):
docs/tools-comms.md - live token streaming:
Runtime.set_live_delta_sink(sink)plus_runtime.stream: truedeliversllm.delta/llm.delta_endevents while an answer is generated, outside the ledger (docs/integrations/abstractcore.md#live-token-streaming) - model switching in a shared process: changing the default model unloads the previous in-process model unless another owner in the process still uses it (
docs/integrations/abstractcore.md#unloading-and-switching-models) - workspace-scoped file and shell tools driven by
workspace_*run vars, including host-only protected folders that are enforced without being shown to the model (docs/integrations/abstractcore.md#workspace-scoped-tools)
from abstractruntime import create_scheduled_runtime
sr = create_scheduled_runtime()
run_id, state = sr.run(my_workflow)
if state.status.value == "waiting":
state = sr.respond(run_id, {"text": "yes"})
sr.stop()For persistent storage:
from abstractruntime import create_scheduled_runtime, JsonFileRunStore, JsonlLedgerStore
sr = create_scheduled_runtime(
run_store=JsonFileRunStore("./data"),
ledger_store=JsonlLedgerStore("./data"),
)| Document | Description |
|---|---|
| Getting Started | Install + first durable workflow |
| API Reference | Public API surface (imports + pointers) |
| Docs Index | Full docs map (guides + reference) |
| FAQ | Common questions and gotchas |
| Troubleshooting | Symptom-oriented setup, runtime, and integration fixes |
| Architecture | Component map + diagrams |
| Overview | Design goals, core concepts, and scope |
| AbstractCore Integration | LLM_CALL / TOOL_CALLS, host facades, models/engines/host jobs |
| Automations | Scheduled and on-request workflows: controller, triggers, commands, context, discussions, storage guarantees |
| Artifacts | Artifact identity, descriptors, catalog search and access stats |
| Tool Approval | Tool risk tiers, run-policy ceiling, per-call refiners |
| Comms Toolset | Opt-in email/WhatsApp/Telegram tools |
| Entity Runtime | Per-entity runtimes, homes, leases, visit waits |
| Snapshots | Named checkpoints for run state |
| Provenance | Tamper-evident ledger documentation |
| Evidence | Artifact-backed evidence capture for web/command tools |
| Limits | _limits namespace and RuntimeConfig |
| WorkflowBundles | .flow bundle format (VisualFlow distribution) |
| MCP Worker | abstractruntime-mcp-worker CLI |
| Changelog | Release notes |
| Contributing | How to build/test and submit changes |
| Code of Conduct | Contributor conduct expectations |
| Security | Responsible vulnerability reporting |
| Acknowledgments | Credits |
| ROADMAP | Current status and longer-term direction |
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e ".[test,docs]"
python -m pytest -qSee CONTRIBUTING.md for contribution guidelines and doc conventions.