Skip to content

Repository files navigation

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.7.1 • Python: 3.10+

Status: pre-1.0 (API may evolve). For production use, pin versions and follow CHANGELOG.md.

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
Loading

Install

Remote-light runtime:

pip install abstractruntime

The 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.

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.7.1)

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 a cancelled ledger 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_tools list 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), and run_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 thinking and speculation through Runtime effects; _runtime.speculation sets a run-wide MTP preference that nested workflows and Agent loops inherit. Provider Models nodes can apply Core capability_route filters 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, ordered lora_adapters, and video flow_shift, while keeping provider/model/task truth in AbstractCore and AbstractVision.
  • history_bundle exports replay-safe resolved_actions summaries 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 response as text and expose the schema-conformant object on data, 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_RESIDENCY with 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_facade passes 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 through resume_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: true delivers llm.delta / llm.delta_end events 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 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

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.

About

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages