safelabs-guard
A deterministic checkpoint between an AI agent's perception and its actions.
safelabs-guard is a pure-Python (no dependencies) port of the guard core from
SafeLabs Guard, a security
checkpoint for AI agents built for the Meta Global AI Developer Hackathon by
Safe Labs AI Inc. It checks the evidence an agent receives and the action it
proposes before an important action is allowed to run. If the evidence does not
match, the action does not run.
- Live demo (TypeScript reference app): https://guard.agentsafelabs.com/live
- Demo video: https://www.youtube.com/watch?v=thHwl6IJM7Y
- Source and full documentation: https://github.com/AgentSafeLabs/safelabs-guard
Status: alpha, reference port. This is not a client for the hosted demo (the demo has no public API for third-party agents), and it is not a full agent framework. The ledger is fixed to the demo order (
ORDER-1042: mug, notebook, cable, seal, ship). Configurable ledgers are on the roadmap, not in this release.
Install
pip install safelabs-guard
Python 3.11 or newer (tested on 3.11, 3.12 and 3.13). No runtime dependencies.
Quick start
from safelabs_guard import create_ledger, guard_action
ledger = create_ledger() # starts at step VERIFY_MUG
gate = guard_action(
ledger_state=ledger,
spark_claimed_objects=["red mug"], # what your model claims is in the frame
sam_detected_objects=["red mug"], # what an independent detector found
voice_transcript="confirmed", # "" when nothing was said
image_text="", # text read from the frame (OCR)
proposed_action="ADVANCE", # ADVANCE | SEAL | SHIP | HOLD
)
if gate.decision == "ALLOW":
# ...perform the real action here, then move the ledger forward...
ledger = gate.next_state
else:
print(gate.decision, gate.reason) # HOLD or BLOCK: nothing runs
A wrong object is blocked, and the ledger does not move:
gate = guard_action(
ledger_state=create_ledger(),
spark_claimed_objects=["red mug"],
sam_detected_objects=["red mug", "banana"],
voice_transcript="", image_text="",
proposed_action="ADVANCE",
)
print(gate.decision, "-", gate.reason)
# BLOCK - Perception mismatch: unexpected banana
Decisions
| Decision | Meaning |
|---|---|
ALLOW |
Verified. Run the action and move the ledger to gate.next_state. |
HOLD |
The agent chose to hold. Nothing runs. |
BLOCK |
The guard refused: the action is not the legal one for the step, the evidence does not match the ledger, an injection was detected, or the input was unusable. Nothing runs. |
What it checks, in order
- The ledger state is one this library issued, and the order is not complete.
- Input types are valid (otherwise BLOCK; the guard never raises).
- Instruction injection in the image text, in the voice transcript, and in both joined (a command split across a sign and a voice).
- The detector's objects equal the objects expected at this step (missing or unexpected objects BLOCK).
- The model's claim equals what the detector found.
- The voice transcript is empty or only a short, allow-listed confirmation.
Only ALLOW advances the ledger. Model output, image text and transcripts have
no write access to it, and each ALLOW can be redeemed once.
How faithful is the port?
This port reproduces lib/guard/ from the TypeScript reference implementation
(reconcile, ledger, action-gate, injections). It was checked against the
original in two ways:
- all 30 hand-written ASI-MM cases from the repository (5 ALLOW, 25 BLOCK) give the expected decision and reason;
- 8,000 randomized inputs (including paraphrased, leetspeak, Unicode look-alike and zero-width injections, and voice-allowlist edge cases) were run through both the TypeScript original and this port with no differences in decision, reason or next state.
Limitations
- Fixed ledger. Only the PackProof order (
ORDER-1042) is built in. Other workflows need a code change. - The guard trusts its inputs. It compares the detector's objects with the ledger. If your detector wrongly reports every required item, the step passes. There is no freshness check, so a replayed frame that shows the right items looks the same as a fresh one.
- English only. Injection patterns and the voice allowlist are English. Benign phrases outside the allowlist (for example "ready to ship") are blocked.
- Not a security audit. The reference benchmark is a small offline replay of recorded responses; see the repository for results and caveats. This library is not a guarantee against all attacks.
- Python cannot hide internals as strictly as TypeScript. The ledger protections hold against untrusted data (JSON, model output), not against code in the same process that deliberately reaches into module internals.
- Not an SDK for the hosted demo. The demo's HTTP routes accept only the allow-listed browser origin.
Development
pip install -e . pytest
pytest
License
Apache License 2.0. Copyright 2026 Safe Labs AI Inc.
Metadata
Release files for safelabs-guard 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| safelabs_guard-0.1.0.tar.gz | 18.8 kB | Without provenance | Details for safelabs_guard-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| safelabs_guard-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for safelabs_guard-0.1.0-py3-none-any.whl |
Total release size: 36.2 kB
Release files / safelabs_guard-0.1.0.tar.gz
| Download URL | safelabs_guard-0.1.0.tar.gz |
|---|---|
| Size | 18.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5f9bbcdf63fda3bb0c19245596fa6f487fd37eaa532a0a46cc3accf97d84acb7
|
|
BLAKE2b-256 checksum How to use checksums |
20359f8f85e9156ec15a5ce83547085fcbcc95fe7b1386b10a0737a22d24f39c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|
Release files / safelabs_guard-0.1.0-py3-none-any.whl
| Download URL | safelabs_guard-0.1.0-py3-none-any.whl |
|---|---|
| Size | 17.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
093920df2f6ee0dfbedd6afe151e8e9fb86e05aa5972977ce5669da9572a3e9a
|
|
BLAKE2b-256 checksum How to use checksums |
c2f5b4618ea901f0d1ef727345b970145938cb7b18f0c233affb198b9c5be760
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|
Security for safelabs-guard 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.