AbstractRuntime 0.0.0__tar.gz → 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. abstractruntime-0.0.1/.gitignore +88 -0
  2. {abstractruntime-0.0.0 → abstractruntime-0.0.1}/LICENSE +3 -1
  3. abstractruntime-0.0.1/PKG-INFO +163 -0
  4. abstractruntime-0.0.1/README.md +141 -0
  5. abstractruntime-0.0.1/ROADMAP.md +234 -0
  6. abstractruntime-0.0.1/docs/adr/0001_layered_coupling_with_abstractcore.md +27 -0
  7. abstractruntime-0.0.1/docs/adr/0002_execution_modes_local_remote_hybrid.md +32 -0
  8. abstractruntime-0.0.1/docs/adr/0003_provenance_tamper_evident_hash_chain.md +30 -0
  9. abstractruntime-0.0.1/docs/adr/README.md +37 -0
  10. abstractruntime-0.0.1/docs/backlog/README.md +42 -0
  11. abstractruntime-0.0.1/docs/backlog/completed/001_runtime_kernel.md +23 -0
  12. abstractruntime-0.0.1/docs/backlog/completed/002_persistence_and_ledger.md +23 -0
  13. abstractruntime-0.0.1/docs/backlog/completed/003_wait_primitives.md +18 -0
  14. abstractruntime-0.0.1/docs/backlog/completed/004_scheduler_driver.md +116 -0
  15. abstractruntime-0.0.1/docs/backlog/completed/005_abstractcore_integration.md +23 -0
  16. abstractruntime-0.0.1/docs/backlog/completed/006_snapshots_bookmarks.md +17 -0
  17. abstractruntime-0.0.1/docs/backlog/completed/007_provenance_hash_chain.md +22 -0
  18. abstractruntime-0.0.1/docs/backlog/completed/009_artifact_store.md +136 -0
  19. abstractruntime-0.0.1/docs/backlog/completed/011_subworkflow_support.md +454 -0
  20. abstractruntime-0.0.1/docs/backlog/completed/012_run_store_query_and_scheduler_support.md +78 -0
  21. abstractruntime-0.0.1/docs/backlog/completed/013_effect_retries_and_idempotency.md +190 -0
  22. abstractruntime-0.0.1/docs/backlog/deprecated/001_integrations_abstractcore.md +257 -0
  23. abstractruntime-0.0.1/docs/backlog/deprecated/001_runtime_kernel.md +37 -0
  24. abstractruntime-0.0.1/docs/backlog/deprecated/002_persistence_and_ledger.md +30 -0
  25. abstractruntime-0.0.1/docs/backlog/deprecated/002_snapshots_bookmarks.md +186 -0
  26. abstractruntime-0.0.1/docs/backlog/deprecated/003_provenance_ledger_chain.md +209 -0
  27. abstractruntime-0.0.1/docs/backlog/deprecated/003_wait_resume_and_scheduler.md +28 -0
  28. abstractruntime-0.0.1/docs/backlog/deprecated/004_effect_handlers_and_integrations.md +32 -0
  29. abstractruntime-0.0.1/docs/backlog/deprecated/004_tests.md +134 -0
  30. abstractruntime-0.0.1/docs/backlog/deprecated/005_docs_updates.md +113 -0
  31. abstractruntime-0.0.1/docs/backlog/deprecated/005_examples_and_composition.md +20 -0
  32. abstractruntime-0.0.1/docs/backlog/deprecated/006_ai_fingerprint_and_provenance.md +68 -0
  33. abstractruntime-0.0.1/docs/backlog/deprecated/DEPRECATED_README.md +33 -0
  34. abstractruntime-0.0.1/docs/backlog/deprecated/README.md +112 -0
  35. abstractruntime-0.0.1/docs/backlog/deprecated/abstractruntime_docs_final_02a7373b.plan.md +124 -0
  36. abstractruntime-0.0.1/docs/backlog/planned/008_signatures_and_keys.md +21 -0
  37. abstractruntime-0.0.1/docs/backlog/planned/010_examples_and_composition.md +29 -0
  38. abstractruntime-0.0.1/docs/backlog/planned/014_remote_tool_worker_executor.md +69 -0
  39. abstractruntime-0.0.1/docs/integrations/abstractcore.md +97 -0
  40. abstractruntime-0.0.1/docs/manual_testing.md +309 -0
  41. abstractruntime-0.0.1/docs/proposal.md +166 -0
  42. abstractruntime-0.0.1/docs/provenance.md +36 -0
  43. abstractruntime-0.0.1/docs/snapshots.md +47 -0
  44. {abstractruntime-0.0.0 → abstractruntime-0.0.1}/pyproject.toml +6 -4
  45. abstractruntime-0.0.1/src/abstractruntime/__init__.py +110 -0
  46. abstractruntime-0.0.1/src/abstractruntime/core/__init__.py +19 -0
  47. abstractruntime-0.0.1/src/abstractruntime/core/models.py +239 -0
  48. abstractruntime-0.0.1/src/abstractruntime/core/policy.py +166 -0
  49. abstractruntime-0.0.1/src/abstractruntime/core/runtime.py +581 -0
  50. abstractruntime-0.0.1/src/abstractruntime/core/spec.py +53 -0
  51. abstractruntime-0.0.1/src/abstractruntime/identity/__init__.py +7 -0
  52. abstractruntime-0.0.1/src/abstractruntime/identity/fingerprint.py +57 -0
  53. abstractruntime-0.0.1/src/abstractruntime/integrations/__init__.py +11 -0
  54. abstractruntime-0.0.1/src/abstractruntime/integrations/abstractcore/__init__.py +43 -0
  55. abstractruntime-0.0.1/src/abstractruntime/integrations/abstractcore/effect_handlers.py +89 -0
  56. abstractruntime-0.0.1/src/abstractruntime/integrations/abstractcore/factory.py +150 -0
  57. abstractruntime-0.0.1/src/abstractruntime/integrations/abstractcore/llm_client.py +296 -0
  58. abstractruntime-0.0.1/src/abstractruntime/integrations/abstractcore/logging.py +27 -0
  59. abstractruntime-0.0.1/src/abstractruntime/integrations/abstractcore/tool_executor.py +89 -0
  60. abstractruntime-0.0.1/src/abstractruntime/scheduler/__init__.py +13 -0
  61. abstractruntime-0.0.1/src/abstractruntime/scheduler/convenience.py +324 -0
  62. abstractruntime-0.0.1/src/abstractruntime/scheduler/registry.py +101 -0
  63. abstractruntime-0.0.1/src/abstractruntime/scheduler/scheduler.py +431 -0
  64. abstractruntime-0.0.1/src/abstractruntime/storage/__init__.py +25 -0
  65. abstractruntime-0.0.1/src/abstractruntime/storage/artifacts.py +488 -0
  66. abstractruntime-0.0.1/src/abstractruntime/storage/base.py +107 -0
  67. abstractruntime-0.0.1/src/abstractruntime/storage/in_memory.py +119 -0
  68. abstractruntime-0.0.1/src/abstractruntime/storage/json_files.py +208 -0
  69. abstractruntime-0.0.1/src/abstractruntime/storage/ledger_chain.py +153 -0
  70. abstractruntime-0.0.1/src/abstractruntime/storage/snapshots.py +217 -0
  71. abstractruntime-0.0.1/tests/README.md +274 -0
  72. abstractruntime-0.0.1/tests/conftest.py +20 -0
  73. abstractruntime-0.0.1/tests/test_artifacts.py +689 -0
  74. abstractruntime-0.0.1/tests/test_integration_abstractcore.py +281 -0
  75. abstractruntime-0.0.1/tests/test_integrations_abstractcore.py +125 -0
  76. abstractruntime-0.0.1/tests/test_ledger_chain.py +57 -0
  77. abstractruntime-0.0.1/tests/test_pause_resume.py +98 -0
  78. abstractruntime-0.0.1/tests/test_queryable_run_store.py +360 -0
  79. abstractruntime-0.0.1/tests/test_real_integration.py +758 -0
  80. abstractruntime-0.0.1/tests/test_remote_llm_client.py +53 -0
  81. abstractruntime-0.0.1/tests/test_retry_idempotency.py +534 -0
  82. abstractruntime-0.0.1/tests/test_scheduler.py +700 -0
  83. abstractruntime-0.0.1/tests/test_snapshots.py +47 -0
  84. abstractruntime-0.0.1/tests/test_subworkflow.py +725 -0
  85. abstractruntime-0.0.0/.gitignore +0 -54
  86. abstractruntime-0.0.0/PKG-INFO +0 -89
  87. abstractruntime-0.0.0/README.md +0 -67
  88. abstractruntime-0.0.0/src/abstractruntime/__init__.py +0 -8
@@ -0,0 +1,88 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+
53
+ # mypy
54
+ .mypy_cache/
55
+ .dmypy.json
56
+ dmypy.json
57
+
58
+ # Environments
59
+ .env
60
+ .venv
61
+ env/
62
+ venv/
63
+ ENV/
64
+ env.bak/
65
+ venv.bak/
66
+
67
+ # IDEs and editors
68
+ .idea/
69
+ .vscode/
70
+ *.swp
71
+ *.swo
72
+
73
+ # Jupyter Notebook
74
+ .ipynb_checkpoints
75
+
76
+ # Pyre type checker
77
+ .pyre/
78
+
79
+ # profiling
80
+ .prof
81
+
82
+ # Local config
83
+ *.env
84
+ .env.*
85
+ # End Generation Here
86
+ ```
87
+
88
+ .DS_Store
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 AbstractRuntime Contributors
3
+ Copyright (c) 2025 Laurent-Philippe Albou
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -21,3 +21,5 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
22
 
23
23
 
24
+
25
+
@@ -0,0 +1,163 @@
1
+ Metadata-Version: 2.4
2
+ Name: AbstractRuntime
3
+ Version: 0.0.1
4
+ Summary: AbstractRuntime: a durable graph runner designed to pair with AbstractCore.
5
+ Project-URL: AbstractCore (website), https://www.abstractcore.ai/
6
+ Project-URL: AbstractCore (GitHub), https://github.com/lpalbou/abstractruntime
7
+ Author: Laurent-Philippe Albou
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: agents,checkpoint,durable,graph,llm,resume,workflow
11
+ Classifier: Development Status :: 1 - Planning
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+
23
+ ## AbstractRuntime
24
+
25
+ **AbstractRuntime** is a low-level **durable workflow runtime**:
26
+ - Execute workflow graphs (state machines)
27
+ - **Interrupt → checkpoint → resume** (hours/days) without keeping Python stacks alive
28
+ - Append-only **ledger** ("journal d’exécution") for audit/debug/provenance
29
+
30
+ **Status**: MVP kernel + file persistence + AbstractCore integration adapters are implemented.
31
+
32
+ ---
33
+
34
+ ### Key concepts
35
+ - **WorkflowSpec**: graph definition (node handlers keyed by id)
36
+ - **RunState**: durable state (`current_node`, `vars`, `waiting`, etc.)
37
+ - **Effect**: a side-effect request (`llm_call`, `tool_calls`, `ask_user`, `wait_event`, ...)
38
+ - **Ledger**: append-only step records (`StepRecord`) describing what happened
39
+
40
+ ---
41
+
42
+ ### Quick start (pause + resume)
43
+
44
+ ```python
45
+ from abstractruntime import Effect, EffectType, Runtime, StepPlan, WorkflowSpec
46
+ from abstractruntime.storage import InMemoryLedgerStore, InMemoryRunStore
47
+
48
+
49
+ def ask(run, ctx):
50
+ return StepPlan(
51
+ node_id="ask",
52
+ effect=Effect(
53
+ type=EffectType.ASK_USER,
54
+ payload={"prompt": "Continue?"},
55
+ result_key="user_answer",
56
+ ),
57
+ next_node="done",
58
+ )
59
+
60
+
61
+ def done(run, ctx):
62
+ return StepPlan(node_id="done", complete_output={"answer": run.vars.get("user_answer")})
63
+
64
+
65
+ wf = WorkflowSpec(workflow_id="demo", entry_node="ask", nodes={"ask": ask, "done": done})
66
+ rt = Runtime(run_store=InMemoryRunStore(), ledger_store=InMemoryLedgerStore())
67
+
68
+ run_id = rt.start(workflow=wf)
69
+ state = rt.tick(workflow=wf, run_id=run_id)
70
+ assert state.status.value == "waiting"
71
+
72
+ state = rt.resume(
73
+ workflow=wf,
74
+ run_id=run_id,
75
+ wait_key=state.waiting.wait_key,
76
+ payload={"text": "yes"},
77
+ )
78
+ assert state.status.value == "completed"
79
+ ```
80
+
81
+ ---
82
+
83
+ ### Built-in Scheduler
84
+
85
+ AbstractRuntime includes a zero-config scheduler for automatic run resumption:
86
+
87
+ ```python
88
+ from abstractruntime import create_scheduled_runtime
89
+
90
+ # Zero-config: defaults to in-memory storage, auto-starts scheduler
91
+ sr = create_scheduled_runtime()
92
+
93
+ # run() does start + tick in one call
94
+ run_id, state = sr.run(my_workflow)
95
+
96
+ # If waiting for user input, respond (auto-finds wait_key)
97
+ if state.status.value == "waiting":
98
+ state = sr.respond(run_id, {"answer": "yes"})
99
+
100
+ # Stop scheduler when done
101
+ sr.stop()
102
+ ```
103
+
104
+ For production with persistent storage:
105
+
106
+ ```python
107
+ from abstractruntime import create_scheduled_runtime, JsonFileRunStore, JsonlLedgerStore
108
+
109
+ sr = create_scheduled_runtime(
110
+ run_store=JsonFileRunStore("./data"),
111
+ ledger_store=JsonlLedgerStore("./data"),
112
+ )
113
+ ```
114
+
115
+ ---
116
+
117
+ ### AbstractCore integration (LLM + tools)
118
+
119
+ AbstractRuntime’s kernel stays dependency-light; AbstractCore integration lives in:
120
+ - `src/abstractruntime/integrations/abstractcore/`
121
+
122
+ Execution modes:
123
+ - **Local**: in-process AbstractCore providers + local tool execution
124
+ - **Remote**: HTTP to AbstractCore server (`/v1/chat/completions`) + tool passthrough (default)
125
+ - **Hybrid**: remote LLM + local tool execution
126
+
127
+ See: `docs/integrations/abstractcore.md`.
128
+
129
+ ---
130
+
131
+ ### Snapshots / bookmarks
132
+
133
+ Snapshots are named, searchable checkpoints of a run state:
134
+ - `Snapshot(snapshot_id, run_id, name, description, tags, run_state)`
135
+
136
+ See: `docs/snapshots.md`.
137
+
138
+ ---
139
+
140
+ ### Provenance (tamper-evident ledger)
141
+
142
+ You can wrap any `LedgerStore` with a hash chain:
143
+
144
+ - `HashChainedLedgerStore(inner_store)`
145
+ - `verify_ledger_chain(records)`
146
+
147
+ This is **tamper-evident**, not non-forgeable (signatures are optional future work).
148
+
149
+ See: `docs/provenance.md`.
150
+
151
+ ---
152
+
153
+ ### Documentation index
154
+
155
+ | Document | Description |
156
+ |----------|-------------|
157
+ | [Proposal](docs/proposal.md) | Design goals, core concepts, and scope |
158
+ | [ROADMAP](ROADMAP.md) | Prioritized next steps with rationale |
159
+ | [ADRs](docs/adr/) | Architectural decisions and their rationale |
160
+ | [Backlog](docs/backlog/) | Completed and planned work items |
161
+ | [Integrations](docs/integrations/) | AbstractCore integration guide |
162
+ | [Snapshots](docs/snapshots.md) | Named checkpoints for run state |
163
+ | [Provenance](docs/provenance.md) | Tamper-evident ledger documentation |
@@ -0,0 +1,141 @@
1
+ ## AbstractRuntime
2
+
3
+ **AbstractRuntime** is a low-level **durable workflow runtime**:
4
+ - Execute workflow graphs (state machines)
5
+ - **Interrupt → checkpoint → resume** (hours/days) without keeping Python stacks alive
6
+ - Append-only **ledger** ("journal d’exécution") for audit/debug/provenance
7
+
8
+ **Status**: MVP kernel + file persistence + AbstractCore integration adapters are implemented.
9
+
10
+ ---
11
+
12
+ ### Key concepts
13
+ - **WorkflowSpec**: graph definition (node handlers keyed by id)
14
+ - **RunState**: durable state (`current_node`, `vars`, `waiting`, etc.)
15
+ - **Effect**: a side-effect request (`llm_call`, `tool_calls`, `ask_user`, `wait_event`, ...)
16
+ - **Ledger**: append-only step records (`StepRecord`) describing what happened
17
+
18
+ ---
19
+
20
+ ### Quick start (pause + resume)
21
+
22
+ ```python
23
+ from abstractruntime import Effect, EffectType, Runtime, StepPlan, WorkflowSpec
24
+ from abstractruntime.storage import InMemoryLedgerStore, InMemoryRunStore
25
+
26
+
27
+ def ask(run, ctx):
28
+ return StepPlan(
29
+ node_id="ask",
30
+ effect=Effect(
31
+ type=EffectType.ASK_USER,
32
+ payload={"prompt": "Continue?"},
33
+ result_key="user_answer",
34
+ ),
35
+ next_node="done",
36
+ )
37
+
38
+
39
+ def done(run, ctx):
40
+ return StepPlan(node_id="done", complete_output={"answer": run.vars.get("user_answer")})
41
+
42
+
43
+ wf = WorkflowSpec(workflow_id="demo", entry_node="ask", nodes={"ask": ask, "done": done})
44
+ rt = Runtime(run_store=InMemoryRunStore(), ledger_store=InMemoryLedgerStore())
45
+
46
+ run_id = rt.start(workflow=wf)
47
+ state = rt.tick(workflow=wf, run_id=run_id)
48
+ assert state.status.value == "waiting"
49
+
50
+ state = rt.resume(
51
+ workflow=wf,
52
+ run_id=run_id,
53
+ wait_key=state.waiting.wait_key,
54
+ payload={"text": "yes"},
55
+ )
56
+ assert state.status.value == "completed"
57
+ ```
58
+
59
+ ---
60
+
61
+ ### Built-in Scheduler
62
+
63
+ AbstractRuntime includes a zero-config scheduler for automatic run resumption:
64
+
65
+ ```python
66
+ from abstractruntime import create_scheduled_runtime
67
+
68
+ # Zero-config: defaults to in-memory storage, auto-starts scheduler
69
+ sr = create_scheduled_runtime()
70
+
71
+ # run() does start + tick in one call
72
+ run_id, state = sr.run(my_workflow)
73
+
74
+ # If waiting for user input, respond (auto-finds wait_key)
75
+ if state.status.value == "waiting":
76
+ state = sr.respond(run_id, {"answer": "yes"})
77
+
78
+ # Stop scheduler when done
79
+ sr.stop()
80
+ ```
81
+
82
+ For production with persistent storage:
83
+
84
+ ```python
85
+ from abstractruntime import create_scheduled_runtime, JsonFileRunStore, JsonlLedgerStore
86
+
87
+ sr = create_scheduled_runtime(
88
+ run_store=JsonFileRunStore("./data"),
89
+ ledger_store=JsonlLedgerStore("./data"),
90
+ )
91
+ ```
92
+
93
+ ---
94
+
95
+ ### AbstractCore integration (LLM + tools)
96
+
97
+ AbstractRuntime’s kernel stays dependency-light; AbstractCore integration lives in:
98
+ - `src/abstractruntime/integrations/abstractcore/`
99
+
100
+ Execution modes:
101
+ - **Local**: in-process AbstractCore providers + local tool execution
102
+ - **Remote**: HTTP to AbstractCore server (`/v1/chat/completions`) + tool passthrough (default)
103
+ - **Hybrid**: remote LLM + local tool execution
104
+
105
+ See: `docs/integrations/abstractcore.md`.
106
+
107
+ ---
108
+
109
+ ### Snapshots / bookmarks
110
+
111
+ Snapshots are named, searchable checkpoints of a run state:
112
+ - `Snapshot(snapshot_id, run_id, name, description, tags, run_state)`
113
+
114
+ See: `docs/snapshots.md`.
115
+
116
+ ---
117
+
118
+ ### Provenance (tamper-evident ledger)
119
+
120
+ You can wrap any `LedgerStore` with a hash chain:
121
+
122
+ - `HashChainedLedgerStore(inner_store)`
123
+ - `verify_ledger_chain(records)`
124
+
125
+ This is **tamper-evident**, not non-forgeable (signatures are optional future work).
126
+
127
+ See: `docs/provenance.md`.
128
+
129
+ ---
130
+
131
+ ### Documentation index
132
+
133
+ | Document | Description |
134
+ |----------|-------------|
135
+ | [Proposal](docs/proposal.md) | Design goals, core concepts, and scope |
136
+ | [ROADMAP](ROADMAP.md) | Prioritized next steps with rationale |
137
+ | [ADRs](docs/adr/) | Architectural decisions and their rationale |
138
+ | [Backlog](docs/backlog/) | Completed and planned work items |
139
+ | [Integrations](docs/integrations/) | AbstractCore integration guide |
140
+ | [Snapshots](docs/snapshots.md) | Named checkpoints for run state |
141
+ | [Provenance](docs/provenance.md) | Tamper-evident ledger documentation |
@@ -0,0 +1,234 @@
1
+ # AbstractRuntime Roadmap
2
+
3
+ ## Current Status: MVP Complete (v0.1)
4
+
5
+ AbstractRuntime has a functional MVP kernel with:
6
+ - Durable workflow execution (start/tick/resume)
7
+ - Explicit waiting states (wait_event, wait_until, ask_user)
8
+ - Persistence (in-memory + JSON/JSONL file backends)
9
+ - Snapshots/bookmarks for named checkpoints
10
+ - Tamper-evident provenance (hash-chained ledger)
11
+ - AbstractCore integration (local/remote/hybrid execution modes)
12
+ - **QueryableRunStore** for listing/filtering runs ✅
13
+ - **Built-in Scheduler** with zero-config operation ✅
14
+ - Test coverage for core functionality (81% overall, 57 tests)
15
+
16
+ ---
17
+
18
+ ## Why AbstractRuntime Exists
19
+
20
+ AbstractRuntime is the **durable execution substrate** that sits below both AbstractAgent and AbstractFlow:
21
+
22
+ ```
23
+ AbstractFlow (UI graphs, multi-agent orchestration, templates)
24
+
25
+ AbstractAgent (ReAct, CodeAct, specialized agents like DeepSearch)
26
+
27
+ AbstractRuntime (interrupt/checkpoint/resume, ledger, snapshots)
28
+
29
+ AbstractCore (LLM calls, tool execution, server API)
30
+ ```
31
+
32
+ **Key insight**: You cannot keep Python stacks alive for days. When an agent needs to:
33
+ - Ask a user a question and wait hours/days for a response
34
+ - Wait until a scheduled time
35
+ - Wait for an external job to complete
36
+
37
+ ...you need **durable state that survives process restarts**. This is what AbstractRuntime provides.
38
+
39
+ **Why not in AbstractFlow?** Because individual agents need these primitives directly. A ReAct agent that calls `ask_user` needs to pause and resume — that's not orchestration, that's the agent itself needing durability.
40
+
41
+ ---
42
+
43
+ ## Phase 1: Core Completeness ✅ COMPLETE
44
+
45
+ ### 1.1 Built-in Scheduler (Zero-Config) ✅
46
+ **Status: COMPLETE** | **Backlog: 004**
47
+
48
+ **What shipped**:
49
+ - `WorkflowRegistry` for mapping workflow_id → WorkflowSpec
50
+ - `Scheduler` class with background polling thread
51
+ - `ScheduledRuntime` convenience wrapper
52
+ - `create_scheduled_runtime()` factory function
53
+ - Event ingestion via `scheduler.resume_event()`
54
+ - Stats tracking and callbacks
55
+
56
+ **Usage**:
57
+ ```python
58
+ # Zero-config: defaults to in-memory, auto-starts scheduler
59
+ sr = create_scheduled_runtime()
60
+
61
+ # run() does start + tick in one call
62
+ run_id, state = sr.run(my_workflow)
63
+
64
+ # respond() auto-finds wait_key
65
+ if state.status.value == "waiting":
66
+ state = sr.respond(run_id, {"answer": "yes"})
67
+
68
+ sr.stop()
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Phase 2: Composition and Examples (Next Priority)
74
+
75
+ ### 2.1 Subworkflow Support
76
+ **Priority: High** | **Effort: Medium** | **Backlog: 011**
77
+
78
+ **Why**: `EffectType.START_SUBWORKFLOW` exists but has no handler. Without this:
79
+ - Multi-agent orchestration is impossible
80
+ - Workflow composition (DeepSearch as a node) doesn't work
81
+ - AbstractFlow cannot compose agents
82
+
83
+ **Deliverables**:
84
+ - Workflow registry interface
85
+ - `START_SUBWORKFLOW` effect handler
86
+ - Sync and async subworkflow modes
87
+ - Tests for parent/child workflow interaction
88
+
89
+ **Success criteria**: A workflow can invoke another workflow by ID and receive its output.
90
+
91
+ ---
92
+
93
+ ### 2.2 Examples and Documentation
94
+ **Priority: High** | **Effort: Low** | **Backlog: 010**
95
+
96
+ **Why**: The MVP is functional but lacks concrete examples. Developers cannot understand how to build workflows without reading source code.
97
+
98
+ **Deliverables**:
99
+ - `examples/` directory with runnable workflows
100
+ - ask_user interrupt example (pause for days, resume)
101
+ - wait_until timer example
102
+ - LLM call + tool execution example
103
+ - Subworkflow composition example
104
+
105
+ **Success criteria**: A developer can copy an example and have a working workflow in 5 minutes.
106
+
107
+ ---
108
+
109
+ ## Phase 3: Production Readiness
110
+
111
+ ### 3.1 Artifact Store
112
+ **Priority: Medium** | **Effort: Medium** | **Backlog: 009**
113
+
114
+ **Why**: Large payloads (documents, images, tool outputs) embedded in `RunState.vars` cause performance issues. The constraint that vars must be JSON-serializable becomes painful without by-reference storage.
115
+
116
+ **Deliverables**:
117
+ - `ArtifactStore` interface
118
+ - File-based implementation
119
+ - `ArtifactRef` type for referencing stored artifacts
120
+ - Integration with RunState serialization
121
+
122
+ **Success criteria**: A workflow can store a 10MB document without bloating the checkpoint.
123
+
124
+ ---
125
+
126
+ ### 3.2 Effect Retries and Idempotency
127
+ **Priority: Medium** | **Effort: Medium** | **Backlog: 013**
128
+
129
+ **Why**: At-least-once execution is a real risk. If a process crashes after an LLM call but before checkpointing, the call may be duplicated on restart.
130
+
131
+ **Deliverables**:
132
+ - `EffectPolicy` protocol (max_attempts, backoff, idempotency_key)
133
+ - Ledger-based deduplication
134
+ - Retry logic in runtime loop
135
+
136
+ **Success criteria**: A workflow survives a crash/restart without duplicating side effects.
137
+
138
+ ---
139
+
140
+ ## Phase 4: Advanced Features
141
+
142
+ ### 4.1 Cryptographic Signatures
143
+ **Priority: Low** | **Effort: High** | **Backlog: 008**
144
+
145
+ **Why**: The hash chain provides tamper-evidence but not non-forgeability. For high-accountability scenarios (AI fingerprinting, regulatory compliance), cryptographic signatures are needed.
146
+
147
+ **Dependencies**: 007 (Hash Chain - complete)
148
+
149
+ **Deliverables**:
150
+ - Ed25519 keypair generation
151
+ - `actor_id` bound to public key
152
+ - Signed `StepRecord` entries
153
+ - Signature verification in `verify_ledger_chain`
154
+ - Key storage patterns (file, OS keychain, Vault)
155
+
156
+ **Success criteria**: A ledger can prove which actor produced each step.
157
+
158
+ ---
159
+
160
+ ### 4.2 Remote Tool Worker
161
+ **Priority: Low** | **Effort: Medium** | **Backlog: 014**
162
+
163
+ **Why**: Some deployments need centralized tool execution (thin clients, sandboxed environments). The current passthrough mode requires the host to execute tools; a worker service would handle this automatically.
164
+
165
+ **Deliverables**:
166
+ - Tool worker API contract
167
+ - `RemoteToolExecutor` implementation
168
+ - Job-based waiting semantics
169
+
170
+ **Success criteria**: A thin client can run workflows with tools by delegating to a worker service.
171
+
172
+ ---
173
+
174
+ ## Relationship to the Abstract Series
175
+
176
+ AbstractRuntime is the **durable execution substrate** that enables both agents and memory to have long-running, interruptible workflows.
177
+
178
+ ```
179
+ AbstractFlow (UI graphs, multi-agent orchestration, templates)
180
+
181
+ ├── AbstractSwarm (swarm of agents - future)
182
+
183
+ AbstractAgent (ReAct, CodeAct, DeepSearch, specialized agents)
184
+
185
+ ├── AbstractMemory (agentic memory - consolidation, reflection, forgetting)
186
+
187
+ AbstractRuntime (interrupt/checkpoint/resume, ledger, snapshots)
188
+
189
+ AbstractCore (LLM calls, tool execution, server API)
190
+ ```
191
+
192
+ **Why this layering?**
193
+ - **AbstractAgent** needs durability primitives directly (an agent might `ask_user` and wait days)
194
+ - **AbstractMemory** needs the same primitives (memory consolidation might run on a schedule)
195
+ - **AbstractFlow** composes agents and workflows, using AbstractRuntime for execution
196
+ - **AbstractRuntime** provides the substrate; it doesn't know about "agents" or "memory" — just workflows
197
+
198
+ **Snapshots enable time-travel debugging:**
199
+ - Save a named checkpoint at any point
200
+ - Restore a multi-agent system to a previous state
201
+ - Rebuild context from ledger + snapshot
202
+
203
+ ---
204
+
205
+ ## Decision Log
206
+
207
+ | Decision | Rationale |
208
+ |----------|-----------|
209
+ | Kernel stays dependency-light | Enables portability, stability, and clear integration boundaries |
210
+ | AbstractCore integration is opt-in | Layered coupling prevents kernel from breaking when AbstractCore changes |
211
+ | Hash chain before signatures | Provides value immediately without key management complexity |
212
+ | Built-in scheduler (not external) | UX principle: simplify as much as possible; zero-config for simple cases |
213
+ | Graph representation for all workflows | A loop is a simple graph; graphs enable visualization, checkpointing, composition |
214
+
215
+ ---
216
+
217
+ ## Timeline (Estimated)
218
+
219
+ | Phase | Items | Status |
220
+ |-------|-------|--------|
221
+ | 1.1 | Scheduler + RunStore Query | ✅ Complete |
222
+ | 2.1 | Subworkflow | 2-3 days |
223
+ | 2.2 | Examples | 1-2 days |
224
+ | 3.1 | Artifact Store | 2-3 days |
225
+ | 3.2 | Retries/Idempotency | 3-4 days |
226
+ | 4.1 | Signatures | 1 week |
227
+ | 4.2 | Remote Worker | 3-4 days |
228
+
229
+ **Phase 1 (Core Completeness)**: ✅ Complete
230
+ **Phase 2 (Composition)**: ~3-5 days
231
+ **Phase 3 (Production Readiness)**: ~1 week
232
+ **Phase 4 (Advanced Features)**: ~2 weeks
233
+
234
+ Remaining: ~3-4 weeks for full roadmap.
@@ -0,0 +1,27 @@
1
+ ## ADR 0001: Layered coupling with AbstractCore
2
+
3
+ ### Status
4
+ Accepted (2025-12-11)
5
+
6
+ ### Context
7
+ AbstractRuntime needs to reuse AbstractCore capabilities (LLM calls, tool execution, structured logging), but we must keep the **durable kernel** stable and dependency-light.
8
+
9
+ Mixing AbstractCore imports into the kernel creates:
10
+ - brittle coupling to AbstractCore internals
11
+ - larger runtime footprint for processes that only need bookkeeping (stores/ledger)
12
+ - harder evolution of the durable state machine
13
+
14
+ ### Decision
15
+ - The kernel (`abstractruntime.core`, `abstractruntime.storage`, `abstractruntime.identity`) must **not** import AbstractCore.
16
+ - AbstractCore integration is an explicit opt-in module:
17
+ - `abstractruntime.integrations.abstractcore`
18
+
19
+ ### Consequences
20
+ - Kernel remains stable and reusable across topologies.
21
+ - AbstractCore can evolve; only the integration module needs updates.
22
+ - We still support heavy reuse of AbstractCore in real deployments (local/remote/hybrid execution modes).
23
+
24
+ ### See Also
25
+ - Implementation: [`backlog/completed/005_abstractcore_integration.md`](../backlog/completed/005_abstractcore_integration.md)
26
+ - Code: `src/abstractruntime/integrations/abstractcore/`
27
+
@@ -0,0 +1,32 @@
1
+ ## ADR 0002: Execution modes (local, remote, hybrid)
2
+
3
+ ### Status
4
+ Accepted (2025-12-11)
5
+
6
+ ### Context
7
+ Agents/workflows must run in multiple deployment topologies:
8
+ - thin clients (mobile/web) calling a backend LLM gateway
9
+ - backend orchestration calling GPU inference fleets
10
+ - local/dev mode (everything on one machine)
11
+
12
+ AbstractCore already provides two compatible boundaries:
13
+ - in-process python API (`create_llm(...).generate(...)`)
14
+ - HTTP server boundary (`/v1/chat/completions`)
15
+
16
+ ### Decision
17
+ AbstractRuntime supports three execution modes:
18
+
19
+ - **Local**: in-process AbstractCore LLM + local tool execution
20
+ - **Remote**: HTTP to AbstractCore server; tools default to passthrough (untrusted)
21
+ - **Hybrid**: remote LLM + local tool execution
22
+
23
+ ### Consequences
24
+ - Thin-mode clients can run the workflow logic while delegating inference to a server.
25
+ - Remote mode supports AbstractCore per-request `base_url` routing (dynamic endpoint selection).
26
+ - Tool execution can be gated by trust/sandbox policy outside the router.
27
+
28
+ ### See Also
29
+ - Implementation: [`backlog/completed/005_abstractcore_integration.md`](../backlog/completed/005_abstractcore_integration.md)
30
+ - Integration guide: [`integrations/abstractcore.md`](../integrations/abstractcore.md)
31
+ - Code: `src/abstractruntime/integrations/abstractcore/factory.py`
32
+