IntentLedger is a cancellation-safe prospective memory runtime for long-horizon agents. It keeps future intentions in an append-only event ledger and rechecks lifecycle state, trigger evidence, preconditions, version, and idempotency immediately before execution.
The repository includes a deterministic Python core, FastAPI service, command line interface, interactive simulated week, synthetic lifecycle benchmark, baseline suite, research artifacts, and a deployable web workbench.
This is an independent implementation. The repository contains no third-party paper, benchmark archive, copied source code, external dataset, or reproduced result.
Long-running agents need to remember more than what to do. They must also know when an instruction is no longer valid.
A reminder can become unsafe after it is cancelled, amended, completed elsewhere, suspended, expired, or replaced. IntentLedger treats these changes as first-class events. The current intention is a projection of immutable history, not a mutable note that silently loses context.
The runtime follows one rule:
active
and trigger is true
and preconditions are true
and time is valid
and this version is current
and this instance has not executed
If any condition fails, the runtime returns a structured suppression reason.
| Area | Implementation |
|---|---|
| Lifecycle | Draft, active, suspended, completed, cancelled, expired, invalidated, and superseded states |
| Event store | SQLite append-only log with per-stream sequence numbers, idempotency keys, and SHA-256 hash chains |
| Triggers | Exact time, windows, typed events, state predicates, recurrence, and constrained semantic matching |
| Safety | Version-bound proposals, approval gates, execution rechecks, sandbox-only actions, and duplicate prevention |
| Parsing | Deterministic date, recurrence, lifecycle, negation, modality, and approval-precondition parsing |
| Interfaces | FastAPI, command line tools, JSON export, replay, invariant checks, and an interactive workbench |
| Evaluation | Seeded lifecycle episodes, ten baselines, failure metrics, bootstrap intervals, and randomization tests |
| Testing | Unit, property, state machine, concurrency, corruption, API, replay, safety, and leakage tests |
| Research | Claims ledger, benchmark card, model card, formal semantics, statistical plan, and reproducibility checklist |
User instruction or simulator event
|
v
Deterministic parser and validators
|
v
Append-only SQLite event store
|
replay projection
|
v
trigger + precondition + lifecycle monitors
|
eligibility decision
/ \
suppressed proposal
|
approval if needed
|
final recheck
|
sandbox execution
The Python engine is the reference implementation. The browser workbench mirrors the same safety model for an interactive, credential-free demonstration.
Python 3.11 or newer is required.
python -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
intentledger simulate --config configs/smoke.yamlOn Windows PowerShell:
py -3.12 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
intentledger simulate --config configs/smoke.yamlStart the API:
intentledger serve --host 127.0.0.1 --port 8000 --database intentledger.dbOpenAPI documentation is available at http://127.0.0.1:8000/docs.
Node.js 22.13 or newer is required.
npm ci
npm run devThe local workbench runs at http://localhost:3000.
from datetime import UTC, datetime, timedelta
from intentledger import ActionSpec, IntentLedgerEngine, IntentSpec, TriggerSpec
from intentledger.models import TriggerKind
start = datetime(2026, 3, 2, 9, tzinfo=UTC)
engine = IntentLedgerEngine(start_time=start)
due = start + timedelta(hours=1)
intent = engine.create(
IntentSpec(
title="Inspect the validation run",
trigger=TriggerSpec(kind=TriggerKind.AT, at=due),
action=ActionSpec(
kind="notify",
description="Notify the operator to inspect the validation run",
),
deadline=due,
)
)
engine.advance(due)
proposal = engine.propose(intent.intent_id)
result = engine.execute(proposal.proposal_id)
assert result["status"] == "simulated"
assert engine.check_invariants().passedNo external message or tool is invoked. Execution is recorded as a sandbox result.
intentledger simulate --config configs/smoke.yaml
intentledger benchmark --config configs/pm_lifecycle.yaml
intentledger replay --stream examples/week.json
intentledger check-invariants --run intentledger.db
intentledger parse "Remind me to inspect tests tomorrow at 10"Each command is deterministic unless a model adapter is explicitly added by the caller.
| Method | Path | Purpose |
|---|---|---|
POST |
/v1/parse |
Parse an instruction into a typed candidate |
POST |
/v1/intents |
Create a draft or active intention |
POST |
/v1/intents/{id}/amend |
Create a new immutable version |
POST |
/v1/intents/{id}/{action} |
Suspend, reactivate, cancel, complete, or invalidate |
POST |
/v1/events |
Ingest a typed environment observation |
POST |
/v1/environment |
Update a deterministic precondition value |
POST |
/v1/clock/advance |
Move the virtual clock forward |
GET |
/v1/proposals/due |
Return currently eligible intentions |
POST |
/v1/proposals |
Create a version-bound action proposal |
POST |
/v1/proposals/{id}/approve |
Approve a proposal |
POST |
/v1/proposals/{id}/execute |
Recheck and simulate execution |
GET |
/v1/replay |
Return ordered ledger events |
GET |
/v1/invariants |
Verify hash, lifecycle, dependency, and execution invariants |
draft -> active <-> suspended
active -> completed
active -> cancelled
active -> expired
active -> invalidated
suspended -> completed
suspended -> cancelled
suspended -> expired
suspended -> invalidated
Terminal intentions cannot execute or transition back to active. A new intention must be created when a terminal instruction needs to be restored. This keeps the prior cancellation or completion intact.
An amendment increments the version and invalidates outstanding proposals for earlier versions. Approval for version 2 can never authorize version 3.
See formal semantics and architecture for the complete rules.
The bundled generator creates synthetic seven-day episodes that target cancellation, rescheduling, completion by another actor, recurrence, failed preconditions, stale retrieval, duplicate triggers, timezone shifts, retries, and abstention.
The default smoke configuration creates 50 offline episodes. Larger runs are generated from a seed.
intentledger benchmark --config configs/pm_lifecycle.yamlImplemented baselines:
- Raw context
- Always-injected intentions
- Vector-style retrieval
- Flat structured checklist
- Calendar and TTL
- ReAct-style agent
- IntentLedger without semantic matching
- IntentLedger without lifecycle guards
- Full IntentLedger
- Complete-state oracle
Generated scores are software validation signals. They are not model study results and do not establish empirical superiority.
Run the Python suite:
pytestRun the web contract tests:
npm run test:webRun lint and all web checks:
npm run verifyThe Python suite covers lifecycle transitions, cancellation races, stale approvals, repeated execution, hash-chain corruption, duplicate webhook delivery, event ordering, replay equivalence, dependency cycles, parser ambiguity, semantic negation, API contracts, benchmark leakage, and statistical utilities.
CI runs the deterministic suite without API keys.
Benchmark runs record:
- Code commit
- Seed
- Virtual clock configuration
- Complete event stream
- Final projections
- Predictions and metrics
- Baseline name
- Artifact status
Build the local paper artifacts with:
python scripts/build_paper_artifacts.py --config configs/pm_lifecycle.yamlThe command writes machine-readable results and a LaTeX table under paper/results/generated. Generated files remain clearly labeled as synthetic validation outputs.
- External messaging, purchases, calendar changes, deletion, and payment are not implemented
- Consequential candidates require explicit approval
- Approval is bound to one intention version
- Execution performs a final lifecycle and trigger check
- Every recurrence instance has an idempotency key
- Terminal and superseded versions cannot propose or execute
- Semantic matching can provide evidence but cannot bypass deterministic guards
- The benchmark never exposes future events to a policy
Review security and the threat model before connecting an external tool.
IntentLedger is a working research prototype with a complete deterministic path. The repository does not claim compatibility with any external benchmark. It does not include third-party empirical results.
The paper package separates hypotheses from verified findings. Claims remain marked as untested until a preregistered multi-model study is completed.
app/ Interactive web workbench
src/intentledger/ Python reference runtime
tests/python/ Python unit and property tests
tests/ Web render and source contract tests
configs/ Reproducible run configurations
schemas/ Machine-readable intention and event schemas
docs/ Architecture, semantics, cards, and threat model
paper/ Claims, outline, statistics, tables, and results
scripts/ Reproducible artifact builders
Read CONTRIBUTING.md before opening a change. New lifecycle behavior must include an invariant, a replay test, and a failure case.
Licensed under Apache License 2.0. See LICENSE.