Skip to main content

Reference Python SDK for the Explicit Decision Protocol (EDP)

Project description

EDP — Explicit Decision Protocol (Python SDK)

Reference implementation of the Explicit Decision Protocol in Python.

Status: v0.1 alpha — implements spec version edp/2026-05-24. Conformance breaking changes may still happen before v1.0.

What this is

EDP is a small protocol that gives AI agents an external working memory of their architectural decisions, so they can remember and respect them across long sessions and across multiple sessions. The agent records commitments via four tools (record, show, check, supersede), the SDK stores them in a local SQLite store, and an adapter injects a 2–4 line snippet of each active decision into the agent's context on every turn.

Full problem statement, evidence, and a real two-session dogfood trace on Opus 4.7 are at the top-level README.

Install

pip install explicit-decision-protocol            # core SDK + CLI + MCP server
pip install "explicit-decision-protocol[langgraph]"  # + LangGraph binding (langchain >= 1.1)

This installs two console scripts on PATH:

  • edp — the CLI (edp init, edp record, edp list, edp show, edp supersede, edp inject, edp events)
  • edp-mcp-server — an MCP stdio server exposing the four EDP tools to any MCP client (Claude Code, Claude Desktop, Cursor, Cline, Continue)

Quick start — Python

from edp import DecisionStore

store = DecisionStore.open(".edp")

dec_id = store.record(
    title="Cache miss is an exception, not a None sentinel",
    decision="Cache.get raises CacheMiss (a KeyError subclass) on miss.",
    key_constraints=[
        "Cache.get must raise on miss, never return a sentinel",
        "CacheMiss remains a KeyError subclass for backwards compatibility",
    ],
    revision_conditions=[],  # event-based re-examination triggers
    evidence=["src/cache.py:CacheMiss"],
    tags=["api-surface"],
    confidence=0.9,
    actor="human:you",
)
print(dec_id)  # "DEC-0001"

# Later: render the active block your agent should see
from edp.selector import get_active_block

block = get_active_block(store, version=1)
print(block.text)
# <edp:active version="1">
# DEC-0001 [active] conf=0.9
#   Title: Cache miss is an exception, not a None sentinel
#   ...
# </edp:active>

Quick start — CLI

cd your-project
edp init
edp record --title "your first decision" --decision "..." --constraint "..." --evidence "@..."
edp list --active
edp inject --version 1     # prints the <edp:active> block; pipe to hook stdout

Quick start — LangGraph

from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

from edp import DecisionStore
from edp.bindings.langgraph import edp_tools, edp_before_model

store = DecisionStore.open(".edp")

agent = create_agent(
    model=ChatOpenAI(model="gpt-4.1-mini"),
    tools=edp_tools(store),
    middleware=[edp_before_model(store)],  # MUST be ordered before SummarizationMiddleware
)

Two runnable examples (auto-pick the model based on OPENROUTER_API_KEY / OPENAI_API_KEY) are at adapters/middleware-langgraph/examples/ in the main repo.

Quick start — Claude Code

Two commands (v0.1.3+):

cd your-project
edp claude-code install
claude

edp claude-code install auto-creates .edp/, writes .claude/settings.json (hooks → python -m edp.hook), .claude/.mcp.json (registers edp-mcp-server), and copies six /edp-* slash commands. Idempotent: re-running merges with your existing .claude/ config instead of overwriting. To remove: edp claude-code uninstall (preserves .edp/).

On SessionStart the agent sees a ~280-token protocol primer + the current <edp:active> block. On every UserPromptSubmit it sees the active block again (primer omitted). The four EDP tools (edp_record, edp_show, edp_check, edp_supersede) are exposed via the bundled MCP server; slash commands give a manual escape hatch.

Full Claude Code install matrix, MCP-client variants (Cursor, Cline, Continue, Claude Desktop), and the LangGraph adapter docs are in the main repo.

What's in the box

Module Purpose
edp.models Pydantic Decision model, Status enum, Alternative
edp.store SQLite store (WAL + FTS5 + append-only events table + markdown projection)
edp.selector Builds the <edp:active> snippet block with token-budget + trim policy
edp.render Snippet rendering, full-body markdown, PROTOCOL_PRIMER constant
edp.server FastMCP 3.x server exposing the four tools + two resources
edp.cli Typer CLI (init, record, list, show, inject, events, supersede, due)
edp.bindings.langgraph LangChain v1.1+ AgentMiddleware + helper inject_into_messages

48 unit tests, 9 Claude-Code-hook tests, 5/5 MCP protocol probes, 6/6 explicit-prompt LangGraph integration, 2/3 naturalistic-prompt LangGraph integration (honest snippet-first failure on turn 2).

Dependencies

  • fastmcp >= 3.3, < 4.0 — MCP server framework
  • pydantic >= 2.0, < 3.0 — schema models
  • typer >= 0.12, < 1.0 — CLI
  • (optional [langgraph]) langchain >= 1.1, langgraph >= 0.2

No vector store, no embeddings, no semantic search in v0.1. SQLite FTS5 (built-in) covers full-text needs.

License

MIT — see the top-level repo for the full text.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

explicit_decision_protocol-0.1.3.tar.gz (35.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

explicit_decision_protocol-0.1.3-py3-none-any.whl (34.9 kB view details)

Uploaded Python 3

File details

Details for the file explicit_decision_protocol-0.1.3.tar.gz.

File metadata

File hashes

Hashes for explicit_decision_protocol-0.1.3.tar.gz
Algorithm Hash digest
SHA256 17ba8d523d4d983e17fcf24c16773134a88ad3641aa747670656dcbc5c0b7c38
MD5 23c44630e69ef50e870d21bbffe5fdba
BLAKE2b-256 7756fbba45529211bfa97f4cabd540b28e0fa7a2701080f7fb638785323c672a

See more details on using hashes here.

File details

Details for the file explicit_decision_protocol-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for explicit_decision_protocol-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 b96d3e63c5cdc86372ee73b958901aa1258c98e2ed48c947717dc75e42c66dae
MD5 89a4944fb69d129c6eeccd7dfd065699
BLAKE2b-256 f07b7d11366f84b37102149bf7ee1c05f34875391a1fb6780852811c7be0e228

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page