AbstractRuntime
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.15.1 • Python: 3.10+
Status: pre-1.0 (API may evolve). For production use, pin versions and follow CHANGELOG.md.
What's new in 0.15.1
- Is Empty accepts lists: nothing, an empty text, or a list or object with no elements is empty (visual-flow
node
is_empty_string; backlog 0857).
What's new in 0.15.0
- Memory facade (
abstractruntime.integrations.abstractmemory.memory_facade.MemoryFacade): the one host surface for AbstractMemory 0.4.0's memory graph (open a mind, stamp provenance, reconstruct a source, history, revisions); hosts no longer importabstractmemory. ADR 0011. See docs/integrations/abstractmemory.md. MEMORY_REVISEeffect andmemory_reviseVisualFlow node: one atomic revision of a mind (assert / close / narrow) as a workflow step, stamped with the step that applied it.- Ledger provenance:
LedgerStore.get_record(run_id, seq)point reads, a step context for effect handlers, and a digestedstep/artifact/diary_entrysource ref on every memory write the runtime performs (reconstruct_sourceanswersok,partial,mismatch,source_goneorunsupported). - Upgrade note: requires AbstractMemory 0.4.0, whose vector re-encoding is one-way; move every process sharing a memory home together.
What's new in 0.14.0
- Replay view (
abstractruntime.replay): one deterministic reducer turns a run tree's ledger into the view every client renders (status, the interaction to answer, messages, activities, artifacts), with incremental deltas. Every ledger store now numbers records with a durable per-runseqcursor (list_after). See docs/replay.md. - Session tool policy: a conversation's standing approve/deny is applied before any approval
wait, with an
abstract.tool_policy_decisionaudit record. See docs/tool-approval.md. - Upgrade note: hash-chained JSONL ledgers written by 0.14.0 fail an older
verify_ledger_chain; upgrade writers and verifiers together.
AbstractFramework ecosystem
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
Install
Remote-light runtime:
pip install abstractruntime
The base install includes AbstractCore 2.30.0 or newer (its light install:
remote providers, tools, 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.
Quick start (pause + resume)
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"
What’s included (v0.8.2)
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@1fixed UTC intervals;schedule@2adds daily, weekly and monthly rules at a wall time in an IANA time zone), when mail arrives in one of the user's mailboxes (email.received@1,docs/email.md), on new feed items (feed.item@1), on a signed webhook call (webhook.received@1) or on request (manual@1) as a durable controller run; per-user trigger connections (feed URLs, webhook endpoints with sealed signing secrets) reused by any automation; every occurrence receives its trigger as a CloudEvents 1.0 event (input_data.event) and records who or what started it (_meta.origin); runs can schedule work for later withSCHEDULE_RUN(a one-shot wake in the same session, at most the caller's tools, reminders that reach the person), 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) - flows that act and tell: mail verbs on the run's mailbox (
mail_search,mail_get,mail_mark,mail_label,mail_move,mail_delete,mail_send,mail_reply,mail_forward,mail_attachment; changes and sends only on a mailbox the person keeps Read and write,docs/email.md) and Publish to channel (PUBLISH_EVENT: an event on the user's stream, optionally an alert with itsrecipientandchannels, handed to the host throughRuntime.set_publish_event_handler,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)
- large JSON run folders without scans: an in-memory active index and trusted run index (
trust_index,run_index_stats(), background reconciliation), change tokens on the run store and the ledger (change_token(),changed_run_ids()), event-wait indexes that see another process's parked runs, and the active-consumers index for "who listens?" (docs/architecture.md,docs/api.md) - 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)
Built-in scheduler (zero-config)
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"),
)
Documentation
| 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, event-driven and on-request workflows: controller, triggers (schedules, mail, feeds in RSS 2.0/RSS 1.0/Atom, webhooks), trigger connections, the CloudEvents envelope, run origin, wakes (SCHEDULE_RUN), Publish to channel (alerts with recipient and channels), commands, context, discussions, storage guarantees |
Email for each user: run-scoped account binding, sending without asking, the event inbox and mail feeder, the email.received@1 trigger on any of the user's mailboxes, mail verbs for flows (Read only / Read and write), the send-email action |
|
| 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 |
Development
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e ".[test,docs]"
python -m pytest -q
See CONTRIBUTING.md for contribution guidelines and doc conventions.
Metadata
Release files for AbstractRuntime 0.15.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| abstractruntime-0.15.1.tar.gz | 2.9 MB | With provenance | Details for abstractruntime-0.15.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| abstractruntime-0.15.1-py3-none-any.whl | Python 3 | none | any | Details for abstractruntime-0.15.1-py3-none-any.whl |
Total release size: 4.5 MB
Release files / abstractruntime-0.15.1.tar.gz
| Download URL | abstractruntime-0.15.1.tar.gz |
|---|---|
| Size | 2.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cc616cef441f9277d08eaa3c64191071488ef369a29d68872df0ed3994c35d86
|
|
BLAKE2b-256 checksum How to use checksums |
aa90efbb4f21bb6c4761c5b577c0767531524f6c10eda272ea3852827aa26e7b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.
Transparency logRelease files / abstractruntime-0.15.1-py3-none-any.whl
| Download URL | abstractruntime-0.15.1-py3-none-any.whl |
|---|---|
| Size | 1.6 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2e6294b8a0b3326824607e9f6546496609787bc269e3aff1d8d6c6d45abf568f
|
|
BLAKE2b-256 checksum How to use checksums |
c3558a4454bf207ed8b2e4a8cdffdb0024fd9079aac689217e148249245e0ed7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.
Transparency logSecurity for AbstractRuntime 0.15.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for abstractruntime-0.15.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.