AbstractRuntime 0.0.0__tar.gz → 0.2.0__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.
- abstractruntime-0.2.0/.gitignore +88 -0
- abstractruntime-0.2.0/CHANGELOG.md +132 -0
- {abstractruntime-0.0.0 → abstractruntime-0.2.0}/LICENSE +3 -1
- abstractruntime-0.2.0/PKG-INFO +163 -0
- abstractruntime-0.2.0/README.md +141 -0
- abstractruntime-0.2.0/ROADMAP.md +235 -0
- abstractruntime-0.2.0/docs/adr/0001_layered_coupling_with_abstractcore.md +27 -0
- abstractruntime-0.2.0/docs/adr/0002_execution_modes_local_remote_hybrid.md +32 -0
- abstractruntime-0.2.0/docs/adr/0003_provenance_tamper_evident_hash_chain.md +30 -0
- abstractruntime-0.2.0/docs/adr/README.md +37 -0
- abstractruntime-0.2.0/docs/backlog/README.md +42 -0
- abstractruntime-0.2.0/docs/backlog/completed/001_runtime_kernel.md +23 -0
- abstractruntime-0.2.0/docs/backlog/completed/002_persistence_and_ledger.md +23 -0
- abstractruntime-0.2.0/docs/backlog/completed/003_wait_primitives.md +18 -0
- abstractruntime-0.2.0/docs/backlog/completed/004_scheduler_driver.md +116 -0
- abstractruntime-0.2.0/docs/backlog/completed/005_abstractcore_integration.md +23 -0
- abstractruntime-0.2.0/docs/backlog/completed/006_snapshots_bookmarks.md +17 -0
- abstractruntime-0.2.0/docs/backlog/completed/007_provenance_hash_chain.md +22 -0
- abstractruntime-0.2.0/docs/backlog/completed/009_artifact_store.md +136 -0
- abstractruntime-0.2.0/docs/backlog/completed/010_examples_and_composition.md +59 -0
- abstractruntime-0.2.0/docs/backlog/completed/011_subworkflow_support.md +454 -0
- abstractruntime-0.2.0/docs/backlog/completed/012_run_store_query_and_scheduler_support.md +78 -0
- abstractruntime-0.2.0/docs/backlog/completed/013_effect_retries_and_idempotency.md +190 -0
- abstractruntime-0.2.0/docs/backlog/completed/016_runtime_aware_parameters.md +240 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/001_integrations_abstractcore.md +257 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/001_runtime_kernel.md +37 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/002_persistence_and_ledger.md +30 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/002_snapshots_bookmarks.md +186 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/003_provenance_ledger_chain.md +209 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/003_wait_resume_and_scheduler.md +28 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/004_effect_handlers_and_integrations.md +32 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/004_tests.md +134 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/005_docs_updates.md +113 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/005_examples_and_composition.md +20 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/006_ai_fingerprint_and_provenance.md +68 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/DEPRECATED_README.md +33 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/README.md +112 -0
- abstractruntime-0.2.0/docs/backlog/deprecated/abstractruntime_docs_final_02a7373b.plan.md +124 -0
- abstractruntime-0.2.0/docs/backlog/planned/008_signatures_and_keys.md +21 -0
- abstractruntime-0.2.0/docs/backlog/planned/014_remote_tool_worker_executor.md +69 -0
- abstractruntime-0.2.0/docs/backlog/planned/015_agent_integration_improvements.md +111 -0
- abstractruntime-0.2.0/docs/backlog/planned/017_limit_warnings_and_observability.md +141 -0
- abstractruntime-0.2.0/docs/integrations/abstractcore.md +97 -0
- abstractruntime-0.2.0/docs/limits.md +266 -0
- abstractruntime-0.2.0/docs/manual_testing.md +309 -0
- abstractruntime-0.2.0/docs/proposal.md +166 -0
- abstractruntime-0.2.0/docs/provenance.md +36 -0
- abstractruntime-0.2.0/docs/snapshots.md +47 -0
- abstractruntime-0.2.0/examples/01_hello_world.py +60 -0
- abstractruntime-0.2.0/examples/02_ask_user.py +134 -0
- abstractruntime-0.2.0/examples/03_wait_until.py +94 -0
- abstractruntime-0.2.0/examples/04_multi_step.py +100 -0
- abstractruntime-0.2.0/examples/05_persistence.py +173 -0
- abstractruntime-0.2.0/examples/06_llm_integration.py +102 -0
- abstractruntime-0.2.0/examples/07_react_agent.py +124 -0
- abstractruntime-0.2.0/examples/README.md +45 -0
- {abstractruntime-0.0.0 → abstractruntime-0.2.0}/pyproject.toml +6 -4
- abstractruntime-0.2.0/src/abstractruntime/__init__.py +110 -0
- abstractruntime-0.2.0/src/abstractruntime/core/__init__.py +26 -0
- abstractruntime-0.2.0/src/abstractruntime/core/config.py +101 -0
- abstractruntime-0.2.0/src/abstractruntime/core/models.py +282 -0
- abstractruntime-0.2.0/src/abstractruntime/core/policy.py +166 -0
- abstractruntime-0.2.0/src/abstractruntime/core/runtime.py +736 -0
- abstractruntime-0.2.0/src/abstractruntime/core/spec.py +53 -0
- abstractruntime-0.2.0/src/abstractruntime/core/vars.py +94 -0
- abstractruntime-0.2.0/src/abstractruntime/identity/__init__.py +7 -0
- abstractruntime-0.2.0/src/abstractruntime/identity/fingerprint.py +57 -0
- abstractruntime-0.2.0/src/abstractruntime/integrations/__init__.py +11 -0
- abstractruntime-0.2.0/src/abstractruntime/integrations/abstractcore/__init__.py +47 -0
- abstractruntime-0.2.0/src/abstractruntime/integrations/abstractcore/effect_handlers.py +119 -0
- abstractruntime-0.2.0/src/abstractruntime/integrations/abstractcore/factory.py +187 -0
- abstractruntime-0.2.0/src/abstractruntime/integrations/abstractcore/llm_client.py +397 -0
- abstractruntime-0.2.0/src/abstractruntime/integrations/abstractcore/logging.py +27 -0
- abstractruntime-0.2.0/src/abstractruntime/integrations/abstractcore/tool_executor.py +168 -0
- abstractruntime-0.2.0/src/abstractruntime/scheduler/__init__.py +13 -0
- abstractruntime-0.2.0/src/abstractruntime/scheduler/convenience.py +324 -0
- abstractruntime-0.2.0/src/abstractruntime/scheduler/registry.py +101 -0
- abstractruntime-0.2.0/src/abstractruntime/scheduler/scheduler.py +431 -0
- abstractruntime-0.2.0/src/abstractruntime/storage/__init__.py +25 -0
- abstractruntime-0.2.0/src/abstractruntime/storage/artifacts.py +519 -0
- abstractruntime-0.2.0/src/abstractruntime/storage/base.py +107 -0
- abstractruntime-0.2.0/src/abstractruntime/storage/in_memory.py +119 -0
- abstractruntime-0.2.0/src/abstractruntime/storage/json_files.py +208 -0
- abstractruntime-0.2.0/src/abstractruntime/storage/ledger_chain.py +153 -0
- abstractruntime-0.2.0/src/abstractruntime/storage/snapshots.py +217 -0
- abstractruntime-0.2.0/tests/README.md +274 -0
- abstractruntime-0.2.0/tests/conftest.py +20 -0
- abstractruntime-0.2.0/tests/test_artifacts.py +713 -0
- abstractruntime-0.2.0/tests/test_durable_toolsets.py +75 -0
- abstractruntime-0.2.0/tests/test_integration_abstractcore.py +287 -0
- abstractruntime-0.2.0/tests/test_integrations_abstractcore.py +125 -0
- abstractruntime-0.2.0/tests/test_ledger_chain.py +57 -0
- abstractruntime-0.2.0/tests/test_pause_resume.py +98 -0
- abstractruntime-0.2.0/tests/test_queryable_run_store.py +360 -0
- abstractruntime-0.2.0/tests/test_real_integration.py +758 -0
- abstractruntime-0.2.0/tests/test_remote_llm_client.py +53 -0
- abstractruntime-0.2.0/tests/test_retry_idempotency.py +557 -0
- abstractruntime-0.2.0/tests/test_scheduler.py +700 -0
- abstractruntime-0.2.0/tests/test_snapshots.py +47 -0
- abstractruntime-0.2.0/tests/test_subworkflow.py +725 -0
- abstractruntime-0.2.0/tests/test_trace_context_propagation.py +108 -0
- abstractruntime-0.0.0/.gitignore +0 -54
- abstractruntime-0.0.0/PKG-INFO +0 -89
- abstractruntime-0.0.0/README.md +0 -67
- 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
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to AbstractRuntime will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2025-12-17
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
#### Core Runtime Features
|
|
13
|
+
- **Durable Workflow Execution**: Start/tick/resume semantics for long-running workflows that survive process restarts
|
|
14
|
+
- **WorkflowSpec**: Graph-based workflow definitions with node handlers keyed by ID
|
|
15
|
+
- **RunState**: Durable state management (`current_node`, `vars`, `waiting`, `status`)
|
|
16
|
+
- **Effect System**: Side-effect requests including `LLM_CALL`, `TOOL_CALLS`, `ASK_USER`, `WAIT_EVENT`, `WAIT_UNTIL`, `START_SUBWORKFLOW`
|
|
17
|
+
- **StepPlan**: Node execution plans that define effects and state transitions
|
|
18
|
+
- **Explicit Waiting States**: First-class support for pausing execution (`WaitReason`, `WaitState`)
|
|
19
|
+
|
|
20
|
+
#### Scheduler & Automation
|
|
21
|
+
- **Built-in Scheduler**: Zero-config background scheduler with polling thread for automatic run resumption
|
|
22
|
+
- **WorkflowRegistry**: Mapping from workflow_id to WorkflowSpec for dynamic workflow resolution
|
|
23
|
+
- **ScheduledRuntime**: High-level wrapper combining Runtime + Scheduler with simplified API
|
|
24
|
+
- **create_scheduled_runtime()**: Factory function for zero-config scheduler creation
|
|
25
|
+
- **Event Ingestion**: Support for external event delivery via `scheduler.resume_event()`
|
|
26
|
+
- **Scheduler Stats**: Built-in statistics tracking and callback support
|
|
27
|
+
|
|
28
|
+
#### Storage & Persistence
|
|
29
|
+
- **Append-only Ledger**: Execution journal with `StepRecord` entries for audit/debug/provenance
|
|
30
|
+
- **InMemoryRunStore**: In-memory run state storage for development and testing
|
|
31
|
+
- **InMemoryLedgerStore**: In-memory ledger storage for development and testing
|
|
32
|
+
- **JsonFileRunStore**: File-based persistent run state storage (one file per run)
|
|
33
|
+
- **JsonlLedgerStore**: JSONL-based persistent ledger storage
|
|
34
|
+
- **QueryableRunStore**: Interface for listing and filtering runs by status, workflow_id, actor_id, and time range
|
|
35
|
+
- **Artifacts System**: Storage for large payloads (documents, images, tool outputs) to avoid bloating checkpoints
|
|
36
|
+
- `ArtifactStore` interface with in-memory and file-based implementations
|
|
37
|
+
- `ArtifactRef` type for referencing stored artifacts
|
|
38
|
+
- Helper functions: `artifact_ref()`, `is_artifact_ref()`, `get_artifact_id()`, `resolve_artifact()`, `compute_artifact_id()`
|
|
39
|
+
|
|
40
|
+
#### Snapshots & Bookmarks
|
|
41
|
+
- **Snapshot System**: Named, searchable checkpoints of run state for debugging and experimentation
|
|
42
|
+
- **SnapshotStore**: Storage interface for snapshots with metadata (name, description, tags, timestamps)
|
|
43
|
+
- **InMemorySnapshotStore**: In-memory snapshot storage for development
|
|
44
|
+
- **JsonSnapshotStore**: File-based snapshot storage (one file per snapshot)
|
|
45
|
+
- **Snapshot Search**: Filter by run_id, tag, or substring match in name/description
|
|
46
|
+
|
|
47
|
+
#### Provenance & Accountability
|
|
48
|
+
- **Hash-Chained Ledger**: Tamper-evident ledger with `prev_hash` and `record_hash` for each step
|
|
49
|
+
- **HashChainedLedgerStore**: Decorator for adding hash chain verification to any ledger store
|
|
50
|
+
- **verify_ledger_chain()**: Verification function that detects modifications or reordering of ledger records
|
|
51
|
+
- **Actor Identity**: `ActorFingerprint` for attribution of workflow execution to specific actors
|
|
52
|
+
- **actor_id tracking**: Support for actor_id in both RunState and StepRecord for accountability
|
|
53
|
+
|
|
54
|
+
#### AbstractCore Integration
|
|
55
|
+
- **LLM_CALL Effect Handler**: Execute LLM calls via AbstractCore providers
|
|
56
|
+
- **TOOL_CALLS Effect Handler**: Execute tool calls with support for multiple execution modes
|
|
57
|
+
- **Three Execution Modes**:
|
|
58
|
+
- **Local**: In-process AbstractCore providers with local tool execution
|
|
59
|
+
- **Remote**: HTTP to AbstractCore server (`/v1/chat/completions`) with tool passthrough
|
|
60
|
+
- **Hybrid**: Remote LLM calls with local tool execution
|
|
61
|
+
- **Convenience Factories**: `create_local_runtime()`, `create_remote_runtime()`, `create_hybrid_runtime()`
|
|
62
|
+
- **Tool Execution Modes**:
|
|
63
|
+
- Executed mode (trusted local) with results
|
|
64
|
+
- Passthrough mode (untrusted/server) with waiting semantics
|
|
65
|
+
- **Layered Coupling**: AbstractCore integration as opt-in module to keep kernel dependency-light
|
|
66
|
+
|
|
67
|
+
#### Effect Policies & Reliability
|
|
68
|
+
- **EffectPolicy Protocol**: Configurable retry and idempotency policies for effects
|
|
69
|
+
- **DefaultEffectPolicy**: Default implementation with no retries
|
|
70
|
+
- **RetryPolicy**: Configurable retry behavior with max_attempts and backoff
|
|
71
|
+
- **NoRetryPolicy**: Explicit no-retry policy
|
|
72
|
+
- **compute_idempotency_key()**: Ledger-based deduplication to prevent duplicate side effects after crashes
|
|
73
|
+
|
|
74
|
+
#### Examples & Documentation
|
|
75
|
+
- **7 Runnable Examples**:
|
|
76
|
+
- `01_hello_world.py`: Minimal workflow demonstration
|
|
77
|
+
- `02_ask_user.py`: Pause/resume with user input
|
|
78
|
+
- `03_wait_until.py`: Scheduled resumption with time-based waiting
|
|
79
|
+
- `04_multi_step.py`: Branching workflow with conditional logic
|
|
80
|
+
- `05_persistence.py`: File-based storage demonstration
|
|
81
|
+
- `06_llm_integration.py`: AbstractCore LLM call integration
|
|
82
|
+
- `07_react_agent.py`: Full ReAct agent implementation with tools
|
|
83
|
+
- **Comprehensive Documentation**:
|
|
84
|
+
- Architecture Decision Records (ADRs) for key design choices
|
|
85
|
+
- Integration guides for AbstractCore
|
|
86
|
+
- Detailed documentation for snapshots and provenance
|
|
87
|
+
- Limits and constraints documentation
|
|
88
|
+
- ROADMAP with prioritized next steps
|
|
89
|
+
|
|
90
|
+
### Technical Details
|
|
91
|
+
|
|
92
|
+
#### Architecture
|
|
93
|
+
- **Layered Design**: Clear separation between kernel, storage, integrations, and identity
|
|
94
|
+
- **Dependency-Light Kernel**: Core runtime remains stable with minimal dependencies
|
|
95
|
+
- **Graph-Based Execution**: All workflows represented as state machines/graphs for visualization and composition
|
|
96
|
+
- **JSON-Serializable State**: All run state and vars must be JSON-serializable for persistence
|
|
97
|
+
|
|
98
|
+
#### Test Coverage
|
|
99
|
+
- **81% Overall Coverage**: Comprehensive test suite with 57+ tests
|
|
100
|
+
- **Integration Tests**: Tests for AbstractCore integration, subworkflows, trace propagation
|
|
101
|
+
- **Core Tests**: Scheduler, snapshots, artifacts, pause/resume, retry/idempotency, ledger chain
|
|
102
|
+
- **Storage Tests**: Queryable run store, durable toolsets
|
|
103
|
+
|
|
104
|
+
#### Compatibility
|
|
105
|
+
- **Python 3.10+**: Supports Python 3.10, 3.11, 3.12, and 3.13
|
|
106
|
+
- **Development Status**: Planning/Alpha (moving toward Beta with 0.2.0)
|
|
107
|
+
|
|
108
|
+
### Known Limitations
|
|
109
|
+
|
|
110
|
+
- Snapshot restore does not guarantee safety if workflow spec or node code has changed
|
|
111
|
+
- Subworkflow support (`START_SUBWORKFLOW`) is implemented but undergoing refinement
|
|
112
|
+
- Cryptographic signatures (non-forgeability) not yet implemented - current hash chain provides tamper-evidence only
|
|
113
|
+
- Remote tool worker service not yet implemented
|
|
114
|
+
|
|
115
|
+
### Design Decisions
|
|
116
|
+
|
|
117
|
+
- **Kernel stays dependency-light**: Enables portability, stability, and clear integration boundaries
|
|
118
|
+
- **AbstractCore integration is opt-in**: Layered coupling prevents kernel breakage when AbstractCore changes
|
|
119
|
+
- **Hash chain before signatures**: Provides immediate value without key management complexity
|
|
120
|
+
- **Built-in scheduler (not external)**: Zero-config UX for simple cases
|
|
121
|
+
- **Graph representation for all workflows**: Enables visualization, checkpointing, and composition
|
|
122
|
+
|
|
123
|
+
### Notes
|
|
124
|
+
|
|
125
|
+
AbstractRuntime is the durable execution substrate designed to pair with AbstractCore, AbstractAgent, and AbstractFlow. It enables workflows to interrupt, checkpoint, and resume across process restarts, making it suitable for long-running agent workflows that need to wait for user input, scheduled events, or external job completion.
|
|
126
|
+
|
|
127
|
+
## [0.0.1] - Initial Development
|
|
128
|
+
|
|
129
|
+
Initial development version with basic proof-of-concept features.
|
|
130
|
+
|
|
131
|
+
[0.2.0]: https://github.com/lpalbou/abstractruntime/releases/tag/v0.2.0
|
|
132
|
+
[0.0.1]: https://github.com/lpalbou/abstractruntime/releases/tag/v0.0.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025
|
|
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.2.0
|
|
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 |
|