DARM Guard
See what your agent is doing. Then govern it.
An agent tool-authorization guard, grounded in a machine-checked Lean 4 theory of assurance transfer.
PerceptraAI Lab
Install
pip install darm-guard
Quick Start
from darm_guard import DARMGuard, Policy, Credential
guard = DARMGuard(
policy=Policy(authorized_tools=frozenset(["file_read", "web_search"])),
credential=Credential(tools=frozenset(["file_read"])),
)
guard.check({"file_read"}) # admitted, within credential
guard.check({"code_exec"}) # admitted in OBSERVE mode, but reported
Three Modes
OBSERVE (default) -- logs and classifies every call. Never blocks. Prints a warning saying so.
GOVERN -- returns a rejection with a typed diagnosis. Your code must honour it.
ENFORCE -- as GOVERN, plus an append-only JSON-lines audit file.
from darm_guard import Mode
guard = DARMGuard(policy=p, credential=c, mode=Mode.GOVERN)
result = guard.check({"code_exec"})
# result.admitted == False
# O-failure: code_exec -- not in observation model
What is and is not guaranteed
DARM Guard v0.1.x operates at the tool-name level. It is grounded in a machine-checked Lean theory, but the Python runtime itself is not formally verified.
Guaranteed by the runtime:
- Credentials and policies are immutable once constructed.
- The delta (requested tools not in the credential) is computed exactly.
- Decisions are deterministic: the same inputs give the same result.
- Within one process, every check is appended to the session audit log.
Proved in Lean about this runtime (darm-monitor):
- The v0.1.0 decision rule is formalized exactly and proved equivalent to a single inclusion condition (IC1RuntimeSemantics).
- Because v0.1.x observes only tool names, no authorizer built on its observations can separate a safe call from a forbidden call to the same tool (R22RuntimeImplementationCorrespondence).
- A runtime that also observes arguments recovers that distinction (R22). This is the specification for v0.2.
Not guaranteed -- assumed:
- Complete mediation: calls that bypass the guard are invisible to it.
- Enforcement: in GOVERN mode the guard returns a decision; it cannot stop code that ignores it.
- Argument-level or effect-level safety: file_read on any path is treated the same.
- Authorization of credential expansion: update_credential is not access-controlled.
- Freshness at execution time: expiry is checked when check() runs, not when the tool runs.
- Session state across processes or restarts.
- The D (domain) and S (semantic) conditions: classified in the theory, not enforced at runtime.
ODATS Diagnosis
| Code | Condition | v0.1.x runtime |
|---|---|---|
| O | Observation -- tool unknown to the policy | enforced |
| D | Domain completeness | not enforced |
| A | Authority -- tool known but not authorized | enforced |
| T | Temporal freshness -- credential expired | enforced at check time |
| S | Semantic boundary | not enforced |
Each condition is proved independently necessary in the Lean theory: removing any one admits a countermodel.
Session Scope Tracking
Tracks cumulative scope across a session, within one process.
guard.check({"file_read"})
guard.check({"web_search"})
print(guard.scope()) # cumulative scope and drift
Temporal Freshness
from datetime import datetime, timedelta
cred = Credential(tools=frozenset(["file_read"]),
issued_at=datetime(2026, 9, 1), ttl=timedelta(hours=4))
LangChain Integration
from darm_guard.integrations import guard_tools
guarded = guard_tools(agent.tools, guard=my_guard)
Formal Backing
The conditions behind each check are proved in darm-monitor. See FORMAL_BACKING.md for the theorem map. 1,100+ theorems, zero sorry, CI-audited for sorryAx.
Roadmap
- v0.2 -- invocation-level authorization (tool + arguments), gated credential expansion, invocation-bound decision tokens.
- v0.3 -- decision computed by a Lean kernel via the existing C-ABI.
- v0.4 -- credential-holding enforcement broker for one domain.
License
MIT
Olusanya Gbolahan V -- PerceptraAI Lab
Release files for darm-guard 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| darm_guard-0.1.1.tar.gz | 9.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| darm_guard-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.7 kB
Release files / darm_guard-0.1.1.tar.gz
| Download URL | darm_guard-0.1.1.tar.gz |
|---|---|
| Size | 9.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
44f9c8f432c6cea6cb094aae193dd40d668ae69fa45c8ebd10ea65ac40396a79
|
|
BLAKE2b-256 checksum How to use checksums |
8d0e35591251d73488c6c8d2bc3b4de5f18d9c456f3892674f0cd6576ac69bb4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / darm_guard-0.1.1-py3-none-any.whl
| Download URL | darm_guard-0.1.1-py3-none-any.whl |
|---|---|
| Size | 9.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5fc56c52289ee4fa91c9d96d671f4cfa34fd0620c90353e427c0e1ae368434d6
|
|
BLAKE2b-256 checksum How to use checksums |
3b3f09786142bfa450874b6392e987f5c27f475b3f07d1df25d89d5a35f6f143
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|