Precedent
Uses a Gemini API key for live model-backed runs, enabling model-assisted rule drafting and decision reasoning.
Uses an OpenAI API key for live model-backed runs, enabling model-assisted rule drafting and decision reasoning.
Ingests Slack exports to discover Q&A threads and draft evidence-linked rules for the rulebook.
Ingests WhatsApp chat exports, including Android and iOS formats, to mine Q&A threads, draft rule proposals, and link each proposed rule to its source messages.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Your AI agent doesn't know how your business makes decisions. When to refund. Who approves a discount. What to say about allergies. What never to do. Precedent learns those rules from the conversations your team is already having, has a person approve every one, and puts a deterministic gate in front of every action your agents take.
New in 0.2: halting a run that's already going. Approving the start of an action isn't enough. Agents now re-check before every step and after Done, and Precedent halts the run when a step goes beyond what was approved, a rule changes mid-run, or a decision is reused or stale. Each halt leaves a record of which rule, which run, and who halted it. How it works.
๐งญ The problem
Every agent deployment hits the same wall: the agent is capable, but it doesn't know the house rules.
The usual fix | Why it breaks |
๐ "Write a knowledge base" | It describes how the founder thinks the business runs. It takes weeks, and it's stale weeks later. |
๐ "Let the agent learn from the tools" | CRMs and inboxes show what happened, never why, and can't tell a precedent from a mistake. |
๐ค "Let the agent figure it out" | Models are poorly calibrated about when not to act. That is the one decision you can't hand them. |
The real process lives in the moments when someone asks a colleague "how do we handle X?" and gets an answer. Precedent treats those moments as the source, a person as the authority, and the agent's uncertainty as the signal for what to learn next.
Related MCP server: M3Mgine
โจ What you get
โ๏ธ Rules mined, not written
Point it at a WhatsApp export, a Slack export or JSONL. It finds the Q&A threads and drafts one rule per answer, each linked to the exact messages it came from. Fixing a draft takes minutes; writing from a blank page takes weeks.
โ A person approves everything
There is exactly one door into the rulebook: an approved proposal. Models draft; people decide. Every change is versioned, attributed and replayable.
๐ฆ A gate before every action, and while it runs
Agents call consult_rulebook before acting. Five deterministic gates outside the model return one of three outcomes: act, ask a human to approve, or escalate. Then check_action re-checks before each step and after Done, and halts the run if the step goes beyond what was approved.
๐ Every escalation becomes a rule
Gaps are clustered into a weekly digest. A human answers once; the answer becomes a draft rule and a regression test, so the same question never escalates twice.
๐ Drift caught early
Rules that are overridden, unused, past their review date or duplicated get flagged, with a drafted fix, before they cause damage.
๐๏ธ Plain files, in git
YAML rules, JSONL logs. No database, no vector store, no server. Review rule changes in pull requests and gate merges with precedent eval in CI.
๐ Quick start
No API key needed. Python 3.10+.
pip install precedent-aiThe package on PyPI is precedent-ai; you import it and run it as precedent.
See the whole loop in about 20 seconds on a sample bakery WhatsApp group:
git clone https://github.com/burhan-mujahid/precedent && cd precedent
pip install -e .
bash examples/demo.sh # offline
bash examples/demo.sh --live # with GEMINI_API_KEY / MOONSHOT_API_KEY / ANTHROPIC_API_KEY / OPENAI_API_KEY set
bash examples/demo.sh --pause # step by step, for presentingOr on your own team's chat:
precedent init my-rulebook --pack support # packs: general support ops sales finance hr oncall
cd my-rulebook
precedent ingest ~/Downloads/"WhatsApp Chat with Ops.txt"
precedent review # approve / edit / reject drafts, with the source messages shown
precedent ask "Customer says the birthday cake arrived damaged"[NEEDS APPROVAL] D-20261109T1154-1eadcb90d0 confidence 0.88 risk high
answer : Ask for a photo first. If the damage is clear we remake it for free or refund in full, their choice. Don't argue about it, it's never worth the review.
rules : R-003 v1
why : reasoner: matched R-003 on: arrived, cake, customer, damaged
why : high-risk action: a human must approveWhatsApp: open the chat โ โฎ โ More โExport chat โ Without media. Android and iOS formats in all common locales work, including Urdu and other right-to-left chats.
๐ How it works
flowchart LR
subgraph sources ["Where the knowledge already is"]
A["๐ฌ WhatsApp / Slack / JSONL"]
B["๐ Session notes"]
C["โ Human overrides"]
end
A -- "mine Q&A threads" --> P["๐ Proposals<br/>(drafts with evidence)"]
B -- "precedent wrap" --> P
C -- "precedent feedback" --> P
G["๐ณ๏ธ Gaps"] -- "a person answers once" --> P
P -- "a person approves" --> R[("๐ Rulebook<br/>versioned YAML, in git")]
AG["๐ค Agent"] -- "consult_rulebook" --> GATES{"๐ฆ 5 gates"}
R --> GATES
GATES --> ACT["๐ข ACT<br/>cites rule versions"]
GATES --> APP["๐ก NEEDS APPROVAL<br/>high-risk: a human signs off"]
GATES --> ESC["๐ด ESCALATE<br/>logged as a gap"]
ESC --> G
ACT -- "each step + after Done" --> CHK{"๐ check_action"}
APP -- "after sign-off" --> CHK
CHK --> CONT["continue"]
CHK --> HALT["HALT<br/>halt record ยท run stopped"]
HALT -- "a person answers once" --> GThe five gates
Every consult_rulebook call goes through these, in order. The first failure wins, and every failure opens a gap for a human to answer.
# | Gate | Escalates when | Why it's outside the model |
1 | Coverage | no approved rule mentions enough of the situation (IDF-weighted) | the model never sees an off-topic rulebook it could stretch to fit |
2 | Judgement | the model says the rules don't settle it, or two rules conflict | an honest "I'm not sure" is a feature, not a failure |
3 | Grounding | the model cites a rule it wasn't given, or its answer uses a number found in neither the rule nor the situation | invented rules and prompt-injected amounts never reach the agent |
4 | Confidence | confidence is below the threshold for the rule's risk tier | thresholds are yours to set, and |
5 | Risk | the rule is high-risk (money, legal, health, personal data, irreversible) | โ NEEDS APPROVAL: the agent prepares, a person signs off |
๐ The execution gate: halting a run that's already going
The five gates decide whether an action may start. They can't stop one that's already running, and they never see what actually happened. So there is a second gate. While acting, the agent calls check_action (or kb.check, or precedent check) with its decision id before each step that changes something, and once more after Done. Every call returns continue or halt. None of the checks calls a model.
# | Check | Halts when | Reason |
1 | Known | the agent cites a decision the rulebook never issued |
|
2 | Sticky | this decision, or any decision in the same run, was halted before |
|
3 | Single use | the decision already passed its after-Done check |
|
4 | Authorised | the decision was ESCALATE, or NEEDS APPROVAL with no sign-off recorded |
|
5 | Fresh | the decision, or its sign-off, is older than |
|
6 | Rules unchanged | a cited rule was retired, re-versioned or edited since the decision |
|
7 | In scope | the step uses an amount, or a high-risk word (bank, refund, deleteโฆ), that's in neither the decision nor its rules |
|
Every halt is a halt record in logs/events.jsonl: the decision, the run, the cited rule versions, the stage (during or after), the reason, and who created it. That's precedent:check for the checks above, or the person or probe that called precedent halt. Halts are final. Once a run is halted, every later check in it halts too, so an agent can't retry its way past one. Out-of-scope and external halts also open a gap, so a person's answer becomes a rule fix and a regression test.
> check: Refunding 5000 to the customer's card
[HALT] H-20261109T1428-e1f2fb8921 D-20261109T1428-2ed8117143 during run run-cake
why : out_of_scope: the step uses 5000, which the decision did not authorise
gap : G-20261109T1428-80363d1ecc
> check: Refunded the cake in full
[HALT] H-20261109T1428-e1f2fb8921 D-20261109T1428-2ed8117143 after run run-cake
why : halted: H-20261109T1428-e1f2fb8921 (out_of_scope) already stopped this decision; a person starts a new runBring your own monitor. If something outside Precedent halts a run, such as an execution monitor or a person watching, it calls report_outcome with verdict: "halt" (or precedent halt D-โฆ "why" --fix "what should happen"). Precedent records the halt, stops the rest of the run, opens a gap and drafts the rule fix. Approving the fix adds a regression case.
๐ Plug it into your agent
Precedent isn't an agent framework or a memory store. It's the decision layer underneath whatever you already use.
from precedent import Precedent
kb = Precedent.open("./my-rulebook")
d = kb.resolve("Customer wants a refund, order arrived 3 days late", context={"order_value": 4500},
run_id="run-42")
if d.outcome == "answer": # act; d.cited == [{"id": "R-004", "version": 2, "sha": "f1733b9bf477"}]
...
elif d.outcome == "needs_approval": # covered, but high risk: a human signs off (kb.sign_off(d.id, "owner"))
...
else: # "escalate": a gap was logged and will come back as a rule
...
# While acting: before each step, and once after Done
if kb.check(d.id, "Refunding 4500 to the original card").halted:
stop_the_run()
kb.check(d.id, "Refunded 4500", stage="after")For function-calling APIs, kb.tool_spec() gives a JSON Schema tool definition and kb.handle_tool_call(args) runs it. The tool call never raises: any error comes back as escalate with "Do NOT act". kb.check_tool_spec() and kb.handle_check_call(args) do the same for the execution gate, and any error there comes back as halt. Ready-made snippets: Anthropic tool use ยท LangGraph.
{ "mcpServers": { "precedent": { "command": "precedent", "args": ["mcp", "--root", "/path/to/my-rulebook"] } } }Tool | What it does |
| the runtime gate: answer / needs_approval / escalate, with cited rule versions and the approved wording |
| the execution gate, before each step and after Done: continue / halt |
| confirm (becomes a regression test), override (drafts a rule fix for human review), or halt (an outside monitor stopped the run: halt record + gap + draft fix) |
Agents can't sign off their own NEEDS APPROVAL decisions: there is no sign-off tool over MCP.
| search_rules | read-only lookup of approved rules |
| open_gaps | what agents couldn't handle, waiting for a human |
precedent ask "Supplier emailed saying their bank account has changed" --jsonPrints the full decision as JSON. The exit code is 0 only when the agent may act on its own and 3 otherwise, so a script can't proceed by accident.
precedent export skill # an Agent Skills folder (agentskills.io): Claude, Codex, Cursor, Gemini CLI, Hermes...
precedent export agents # an AGENTS.md / CLAUDE.md block
precedent export parlant # a script that loads every approved rule as a Parlant guideline
precedent export json | markdownStatic files can't run the gates, so every export tells the agent to escalate when no rule clearly fits and never to act alone on high-risk rules. For the full gates, use MCP or the Python API.
Every pull request that changes a rule must keep all regression cases passing and introduce no critical drift. Copy examples/integrations/rulebook-ci.yml:
- run: precedent eval --min-pass 1.0
- run: precedent health --strict๐งช Results with real models
The same sample chat and five situations, run through Gemini, Kimi and the offline baseline. Nothing below is edited; full transcripts and token counts are in docs/LIVE-RESULTS.md.
Situation | Gemini | Kimi | Offline baseline |
Brownies safe for a nut allergy? | ๐ก approval | ๐ก approval | ๐ก approval |
Delivery 1.5 hours late | ๐ข act | ๐ก approvalยน | ๐ข act |
Cancel an order for the day after tomorrow | ๐ก approval | ๐ก approval | ๐ด escalateยฒ |
Birthday cake arrived damaged | ๐ก approval | ๐ก approval | ๐ก approval |
Supplier says their bank details changed | ๐ด escalate | ๐ด escalate | ๐ด escalate |
ยน Kimi rated "message the customer and add a free cookie box" as high risk when drafting; a reviewer settles that once, at approval. ยฒ The keyword baseline matched only "cancel" and "order" (confidence 0.52, under the 0.55 approval floor), so a person decides. The models worked out that "the day after tomorrow" is more than 24 hours away.
Ingest of the 9 Q&A threads: Gemini 9.4 s, Kimi 57 s, offline 0.3 s. Each decision is one model call (none when the coverage gate escalates first).
๐๏ธ The weekly loop: about 30 minutes for a founder
precedent cycleOne digest, in order of leverage:
Answer these. Escalations clustered by similarity ("7 cases about supplier bank details"). One answer per cluster becomes a draft rule.
Review these drafts. From chat mining, overrides, session wraps and drift checks.
Rulebook health. Stale, overridden, unused and duplicate rules, and the escalation rate.
Failing regression cases, if a change broke something that used to work.
Command | What it does |
| create a rulebook ( |
| mine WhatsApp / Slack / JSONL into rule drafts |
| the only way into the rulebook: walk the drafts and approve / edit / reject each ( |
| the runtime gate |
| a person approves a NEEDS APPROVAL decision so it may run |
| the execution gate: continue (exit 0) or halt (exit 3) |
| a person or monitor halts a running action; |
| every halt: decision, run, rule versions, stage, reason, who created it |
| turn an escalation (and similar open ones) into a draft rule |
| a correct decision becomes a regression case |
| a wrong decision opens a gap and drafts a fix to the rule it cited |
| end-of-session wrap: decisions in your notes become proposals |
| the weekly digest |
| drift report; drafts deprecate / reconfirm proposals; non-zero exit in CI |
| replay every regression case against the current rulebook |
| recommend confidence thresholds from evidence |
| what would the rulebook have said on that date? |
| browse rules and their version history |
| compile for other tools |
| check the model setup end to end |
| run the MCP server on stdio |
Every command takes --root DIR (or PRECEDENT_ROOT). Set PRECEDENT_USER so approvals are attributed.
๐ค Using a model
The offline reasoner is a deterministic keyword baseline for tests and demos. For real use, pick a provider in precedent.yaml, export its key, and run precedent doctor. It lists the models your key can use, makes a test call, and runs one real decision.
Provider |
| Key env var | Notes |
Google Gemini |
|
| Gemini 3 models reason first, so the preset uses |
Kimi (Moonshot) |
|
| key from platform.moonshot.ai (a Kimi Coding key won't work) |
Anthropic |
|
| native Messages API |
OpenAI |
|
| |
OpenRouter / Groq |
|
| |
Ollama (local) |
| none | nothing leaves your machine |
Anything OpenAI-compatible |
|
| vLLM, LM Studio, Azure, Togetherโฆ |
provider:
kind: gemini
model: <a current Flash model: see `precedent doctor --filter flash`>Model names change often, so Precedent never hard-codes one. If a model rejects temperature or reasoning_effort, the client drops it and retries. Mining runs ingest.workers (default 4) model calls in parallel and prints the calls and tokens it used.
On python.org builds of Python for macOS, HTTPS fails until you runInstall Certificates.command. Or install the extra: pip install "precedent-ai[certs]".
policy:
min_confidence: { low: 0.55, medium: 0.70, high: 1.01 } # > 1.0 = never act alone
approval_floor: 0.55 # high-risk matches below this escalate instead of going to sign-off
stale_penalty: 0.8 # confidence multiplier for rules past their review date
runtime:
redact: true # strip personal data and secrets before the model and the log
max_situation_chars: 4000
decision_ttl_minutes: 60 # how long a decision (or its sign-off) authorises action
retrieval: { top_k: 5, min_coverage: 0.30 }
rules: { review_days: 90 }
drift: { unused_days: 60, override_limit: 2, duplicate_similarity: 0.6 }
ingest: { redact: true, episode_window_hours: 12, episode_max_replies: 8, workers: 4 }
risk: { high_terms: [], medium_terms: [] } # domain packs fill these inSafety settings are range-checked on load, so a typo like 0,7 stops with an error instead of silently opening a gate.
๐ Safety by design
Precedent's job is deciding when an agent may act alone, so it's built to fail closed: when anything is in doubt, a person decides.
๐งฑ The model is untrusted. It can only cite rules it was shown. An answer with a number found in neither the rule nor the situation (a prompt-injected "refund 5000") escalates. Model errors escalate. Agents also receive the approved rule text word for word.
๐ Privacy floor. API keys, tokens, passwords, private keys, emails, phone numbers, card and IBAN numbers, IPs and URL query strings are redacted before anything is stored or sent to a model, both at ingest and at runtime. Use
ollamaand nothing leaves your machine.๐ Halts are deterministic and final. The execution gate halts a step that goes beyond its decision, a decision reused after Done or past its lifetime, and any run whose rules changed underneath it. A halted run stays halted.
๐งพ Audit trail. Every decision records the id, version and content hash of each rule it relied on. Logs are append-only, and any past decision can be replayed against the rulebook as it stood that day.
๐ Hardened storage. Ids are validated before they become file names, approvals take a cross-process lock, API keys only travel over HTTPS, and inputs and responses are size-capped.
๐งฌ Supply chain. One runtime dependency. CI runs
pip-audit, Actions are pinned to commit SHAs, releases ship with signed build provenance.
The full threat model, what is not defended, and how to report a vulnerability: SECURITY.md.
๐บ๏ธ How it compares
The pieces exist separately; the combination doesn't.
Where rules come from | Who decides what's true | Gate before acting | Escalation โ rule โ test | Drift detection | |
Behaviour engines (e.g. Parlant) | written by developers | developers | guideline matching | โ | conflict checks |
Memory layers (Mem0, Zep/Graphiti, Letta) | conversations with users | the system | โ | โ | temporal invalidation |
Self-improving agents (ACE, Hermes) | the agent's own attempts | the agent | โ | โ | playbook curation |
LLM Wiki pattern | your documents | the LLM writes, people read | โ | โ | lint |
Support SaaS (e.g. Sierra) | ticket resolutions | reviewers | inside a closed product | support only | โ |
Precedent | your team's own Q&A + escalations | a person approves every change | โ 5 deterministic gates, plus halt during and after | โ automatic | stale ยท overridden ยท unused ยท duplicate ยท coverage |
Precedent can export to Parlant, so it complements rather than competes. Details and related research: docs/DESIGN.md ยง9.
๐๏ธ Project layout
precedent/
ingest/ WhatsApp, Slack and JSONL parsers, redaction, Q&A episode detection
retrieve.py dependency-free BM25 + coverage scoring
reasoner.py extract / decide / wrap: model-backed and deterministic offline versions
runtime.py the five gates
guard.py the execution gate: check during and after an action, halt records, sign-off
loop.py mining, review, gaps, feedback, session wrap
drift.py health checks evals.py regression replay
calibrate.py evidence-based thresholds export.py Skill / AGENTS.md / Parlant / JSON
mcp.py stdio MCP server packs.py domain packs cli.py
skill/precedent/ use Precedent from Claude or any Agent Skills client
examples/ sample WhatsApp export, end-to-end demo, integration snippets
docs/ DESIGN.md ยท LIVE-RESULTS.md ยท DEMO.md๐ Status and limits
v0.2.3, alpha. 139 tests, run by CI on Linux (Python 3.10 to 3.13), macOS and Windows; ruff and strict mypy clean. Known limits:
The offline reasoner is lexical. It's a deterministic baseline for tests and demos; real deployments should use a model for
extractanddecide.Retrieval is BM25. It suits rulebooks of tens to low thousands of rules written in the team's own words. Stemming is English-only; Urdu and Roman Urdu chats parse fine, but rules match on exact words. An embedding retriever can drop in behind the same one-method interface.
Calibration needs evidence. Thresholds are only recommended once a risk tier has enough regression cases.
No built-in authentication. Whoever can write the rulebook folder can approve rules. Keep it in a git repo with reviewed pull requests (SECURITY.md).
Roadmap: direct connectors (Slack, WhatsApp Business, Gmail, helpdesks) ยท an optional embedding retriever ยท agreement across several model samples as a confidence signal ยท a static review UI ยท multi-reviewer quorum for high-risk rules.
๐ค Contributing
Contributions are welcome. See CONTRIBUTING.md. Good first issues: more chat formats (Teams, Discord, Telegram, email), domain packs, an embedding retriever, a review UI.
pip install -e ".[dev]" && pytest -q && ruff check . && mypyLive provider tests (skipped without keys): GEMINI_API_KEY=โฆ MOONSHOT_API_KEY=โฆ pytest -m live.
๐ Citing
If Precedent helps your research or product, please cite it. GitHub's "Cite this repository" button (from CITATION.cff) gives APA and BibTeX:
@software{mujahid_precedent_2026,
author = {Mujahid, Muhammad Burhan},
title = {Precedent: human-approved operating rules and deterministic action gates for AI agents},
year = {2026},
version = {0.2.3},
doi = {10.5281/zenodo.24087058},
url = {https://github.com/burhan-mujahid/precedent}
}๐ฌ Contact
Muhammad Burhan Mujahid: burhanmujahid552@gmail.com ยท @burhan-mujahid
Questions and ideas: Discussions. Bugs: Issues. Security reports: privately, please.
๐ License
MIT ยฉ Muhammad Burhan Mujahid
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelogโฆ
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
MCP enforcement layer that intercepts AI agent actions and blocks rule violations before execution.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enforces runtime governance on AI agent actions โ file access, command execution, delegation chains, and permission escalation.MIT
- AlicenseNot gradedqualityCmaintenanceMCP server enabling AI agents to enforce corrected rules as durable pre-output checks, manage processed memory, and query a temporal knowledge graph.Apache 2.0
- AlicenseAqualityDmaintenanceAn MCP server that acts as an AI assumption firewall, intercepting risky decisions, detecting contradictions, and routing human approval requests via Telegram or Slack.81MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that provides human-in-the-loop approval for risky AI agent actions, with durable state and audit logs.MIT