Context-driven scheduled tasks for LLMs with persistent memory — inspired by OpenClaw's Heartbeat.
Project description
🧠 context-driven-llm-scheduler
Context-driven scheduled tasks for LLMs with persistent memory.
Most scheduled tasks and cron jobs are stateless — they wake up with no memory of prior runs.
context-driven-llm-scheduler solves this by giving LLM-powered recurring tasks persistent context and memory across executions.
It lets you build reliable, intelligent scheduled agents that remember what they've seen, what they've done, and what still needs attention.
Inspired by the Heartbeat pattern from OpenClaw.
What is context-driven-llm-scheduler?
context-driven-llm-scheduler is a lightweight Python library for defining and running memoryful LLM scheduled tasks (called pulses).
You define each pulse in a markdown file (schedule, memory rules, model, and instructions). The library handles the complex parts:
- Recalling relevant memory and context from previous runs
- Assembling token-efficient prompts (with transparent trimming)
- Atomic persistence of the LLM's decisions
- Built-in deduplication (
seen) and rate-limiting (throttle)
You bring your own scheduler, LLM adapter, and storage backend (or use some default options we provide).
Features
- Markdown-first configuration — prompts, schedules, and rules are easy to edit
- True persistent memory — notes, seen items, key-value facts, throttles
- No lock-in — compatible with cron, APScheduler, Lambda, Airflow, etc.
- Production-ready — concurrency-safe, atomic transactions, honest token budgeting
- Minimal dependencies
Quickstart
1. Create a pulse definition at pulses/inbox-triage.md:
---
id: inbox-triage
schedule: "*/15 * * * *"
throttle: { notify: 1h }
keep: { notes: 20, seen: 500 }
model: anthropic/claude-sonnet-4-6
---
You are my inbox triage assistant.
For each new urgent email:
- Decide if it genuinely needs my attention.
- If yes and the `notify` throttle allows, alert me and record the throttle.
- Always mark the email as `seen`.
Be conservative. Never notify about the same thing twice.
2. Wire it up in Python:
from context_driven_llm_scheduler import PulseManager, FileStore, LiteLLMAdapter
manager = PulseManager.from_dir("pulses", FileStore("./state"))
adapter = LiteLLMAdapter("anthropic/claude-sonnet-4-6")
@manager.pulse("inbox-triage")
def triage(pulse, extra=None):
prompt = pulse.recall(extra={"emails": fetch_urgent_emails()})
ops = adapter.propose_memory_ops(prompt)
return pulse.persist(ops)
3. Trigger the pulse:
manager.trigger("inbox-triage") # Call from cron, scheduler, Lambda, etc.
Core Concepts
The Pulse Interface
Pull Data into the LLM Context Before the Scheduled Job
pulse.recall(...) — assembles instructions + historical memory + fresh input data
Store Data After the Scheduled Job
pulse.persist(ops) — atomically applies the LLM's structured memory operations
Supported Memory Operations
The LLM outputs operations via tool calling:
note — free-text observation
seen — mark item as handled (deduplication)
throttle — record action for rate limiting
set / forget — key/value persistent facts
Installation
pip install context-driven-llm-scheduler
Optional extras:
pip install "context-driven-llm-scheduler[litellm,sqlite,scheduler]"
Examples
See the examples/ directory.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file context_driven_llm_scheduler-1.0.0.tar.gz.
File metadata
- Download URL: context_driven_llm_scheduler-1.0.0.tar.gz
- Upload date:
- Size: 39.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a40def6c294d3e4c7932486b96760cc03fb354aed3a464a43614ea1ab9b609f0
|
|
| MD5 |
e89fc668d9e82e4f23a94b82662b52d5
|
|
| BLAKE2b-256 |
c645d106e1e038ab249876e1709ab3c57c2f2d935d237c7ce48d28e1d37bcde1
|
File details
Details for the file context_driven_llm_scheduler-1.0.0-py3-none-any.whl.
File metadata
- Download URL: context_driven_llm_scheduler-1.0.0-py3-none-any.whl
- Upload date:
- Size: 36.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
038512b570299f31fb30bd437f29155cfb7665c2b64dfa3a5f06b9b5f2b9abcf
|
|
| MD5 |
670797631807fbc4794b6917e3e8b69a
|
|
| BLAKE2b-256 |
2c34690ae38eb7f91f54664784825eb578fce54a98b5c8a7d02b07e98103b706
|