Observed since 21 Oct, 10:37 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Semantic side-effect tracking for AI agents
Semantic side-effect tracking for AI agents.
When an AI agent crashes mid-task, what happens on restart? Without effect-log, irreversible actions (emails, payments, deployments) get repeated. With effect-log, the system knows what completed and what didn't — it returns sealed results for finished work and resumes from where it left off.
Every tool declares its effect kind at registration time. This drives all recovery behavior:
| EffectKind | Recovery (completed) | Recovery (crashed) |
|---|---|---|
| ReadOnly | Replay for fresh data | Replay safely |
| IdempotentWrite | Return sealed result | Replay with same key |
| Compensatable | Return sealed result | Compensate, then replay |
| IrreversibleWrite | Return sealed result | Escalate to human |
| ReadThenWrite | Return sealed result | Escalate to human |
from effect_log import EffectKind, EffectLog, ToolDef
def send_email(args):
return smtp.send(args["to"], args["subject"], args["body"])
tools = [
ToolDef("read_file", EffectKind.ReadOnly, read_file),
ToolDef("send_email", EffectKind.IrreversibleWrite, send_email),
ToolDef("upsert", EffectKind.IdempotentWrite, upsert_record),
]
log = EffectLog(execution_id="task-001", tools=tools, storage="sqlite:///effects.db")
log.execute("read_file", {"path": "/tmp/report.csv"})
log.execute("send_email", {"to": "ceo@co.com", "subject": "Report", "body": "..."})
log.execute("upsert", {"id": "report-001", "data": data})
Recovery — just add recover=True, re-run the same steps:
log = EffectLog(execution_id="task-001", tools=tools, storage="sqlite:///effects.db", recover=True)
log.execute("read_file", {"path": "/tmp/report.csv"}) # Replayed (fresh data)
log.execute("send_email", {"to": "ceo@co.com", ...}) # Sealed — NOT re-sent
log.execute("upsert", {"id": "report-001", ...}) # Replayed (idempotent)
Built-in middleware for major agent frameworks:
| Framework | Middleware | Entry Point |
|---|---|---|
| LangGraph | effect_log.middleware.langgraph | EffectLogToolNode, effect_logged_tools |
| OpenAI Agents SDK | effect_log.middleware.openai_agents | effect_logged_agent, wrap_function_tool |
| CrewAI | effect_log.middleware.crewai | effect_logged_crew, effect_logged_tool |
See examples/ for runnable demos:
crash_recovery.py — Core crash recovery demo (Phase 1 milestone)langgraph_integration.py — LangGraph ToolNode + tool wrappingopenai_agents_integration.py — OpenAI Agents SDK wrappingcrewai_integration.py — CrewAI tool + crew wrappingA write-ahead log with two record types:
Intent without completion = crash detected. The recovery engine uses the effect kind to decide: replay, return sealed, compensate, or escalate.
# Rust
cargo build --release
cargo test --workspace --all-features
# Python
cd bindings/python
pip install maturin
maturin develop --all-features
pytest tests/ -v
The idea behind this project was inspired by a blog post from Guanlan Dai. He introduced the concepts of effect log and semantic correctness.
Apache-2.0
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.0 | 15 Mar 2026 | 0 |
This describes our collected data; it is not a security assessment.
Observed since 21 Oct, 10:37 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:e2306bcdf838444b52039a99df54e045e7762b6e708828edd1ef81c6b15fc2e6