Skip to main content

Lightweight agentic loop detector and safety monitor. No LLM required.

Project description

agentguard

PyPI version Python versions License: MIT CI

Lightweight agentic loop detector and safety monitor. Zero required dependencies.

The problem

LLM agents get stuck. A loop, a dangerous command, a runaway budget, and your agent keeps going. Existing guardrail frameworks are heavy, opinionated, and require you to rewrite your agent around them.

agentguard is different: one method call, drop-in anywhere, no LLM required.

Quick start

pip install nakata-agentguard
from agentguard import AgentGuard, Action

guard = AgentGuard()

# In your tool execution loop:
report = guard.record("bash", {"cmd": "git status"})
if report.action == Action.HALT:
    raise RuntimeError(report.reason)

What it catches

Loop detection (5 modes)

from agentguard import AgentGuard, GuardConfig

guard = AgentGuard(GuardConfig(exact_threshold=3))

# Exact: same (tool, args) repeated N times
for _ in range(3):
    guard.record("bash", {"cmd": "git status"})
# report.action == Action.HALT, "loop detected ('bash:...' called 3x)"

# Also catches:
# Near-duplicate: args differ only in whitespace/numbers
# Error-loop: tool returning errors repeatedly
# Pattern: ABCABC repeating sequence
# Stall: same tool called N times with any args

Dangerous pattern detection (110+ patterns)

No LLM required, pure regex across 9 categories:

Category Examples
DESTRUCTIVE rm -rf, DROP TABLE, docker system prune, terraform destroy
DATA_WIPE dd if=, mkfs, > /dev/sda
PRIVILEGE_ESCALATION sudo, chmod 777, docker run --privileged, nsenter
EXFILTRATION reverse shells, curl -d, /dev/tcp/, Metasploit payloads
CODE_INJECTION eval $(), shell=True, pickle.loads, curl | bash, SQL injection
SECRETS SSH keys, AWS/GCloud creds, OpenAI keys, Stripe live keys, kubeconfig
NETWORK nmap, masscan, ettercap, C2 frameworks, crypto miners
DESTRUCTIVE (cloud) aws s3 rm --recursive, gcloud ... delete, kubectl delete --all
DESTRUCTIVE (git) git push --force, git reset --hard, git filter-branch
report = guard.record("bash", {"cmd": "rm -rf /"})
# report.action    == Action.HALT
# report.dangers[0].category == DangerCategory.DESTRUCTIVE
# report.dangers[0].severity == 10

Budget monitoring

guard = AgentGuard(GuardConfig(token_limit=100_000, cost_limit_usd=5.0))
report = guard.record("llm", {"prompt": "..."}, tokens=1500, cost_usd=0.002)
# report.budget.token_pct   → 0.015
# report.budget.is_warning  → False (< 80%)
# report.budget.is_exceeded → False

Output monitoring

Catches the "464MB cat" class of bugs, tool output that is too large, binary, or stuck in a repeated-line loop.

guard = AgentGuard(GuardConfig(output_max_bytes=512_000, output_warn_bytes=100_000))
report = guard.record("bash", {"cmd": "cat bigfile"}, output="A" * 600_000)
# report.action == Action.HALT

Rate limiting

guard = AgentGuard(GuardConfig(rate_halt_cps=25.0, rate_warn_cps=10.0))
# 26 calls/second → Action.HALT

Configuration

from agentguard import AgentGuard, GuardConfig

guard = AgentGuard(GuardConfig(
    # Loop
    exact_threshold=3,
    stall_threshold=5,
    halt_on_loop=True,
    # Danger
    halt_on_severity=9,
    warn_on_severity=6,
    # Budget
    token_limit=50_000,
    cost_limit_usd=2.0,
    # Rate
    rate_halt_cps=25.0,
    rate_warn_cps=10.0,
    # Custom rules file (TOML or JSON)
    rules_file="agentguard.toml",
))

Config file

Generate a starter config:

agentguard init                     # creates agentguard.toml
agentguard init --output my.toml    # custom path
# agentguard.toml
[guard]
halt_on_severity = 9
warn_on_severity = 6
token_limit      = 100000

[[patterns]]
pattern     = "my_internal_secret_func"
category    = "secrets"
severity    = 8
description = "internal secret function"

[[allowlist]]
tool    = "bash"
pattern = "ls\\s+-la"
reason  = "safe directory listing"

Load it:

guard = AgentGuard(GuardConfig(rules_file="agentguard.toml"))

Allowlist

Skip danger checks for known-safe patterns:

from agentguard import AgentGuard, GuardConfig
from agentguard.allowlist import Allowlist

guard = AgentGuard(GuardConfig(
    allowlist=Allowlist.from_list([
        {"tool": "bash", "pattern": r"ls\s+-la", "reason": "safe listing"},
    ])
))

CLI commands

# Start stateful daemon (enables loop detection across calls)
agentguard serve --port 7420 --halt-severity 9 --token-limit 100000
agentguard serve --webhook-url https://hooks.example.com/alert  # POST on halt/warn

# Check status / reset session
agentguard status
agentguard reset

# One-shot explain (diagnostic output)
agentguard explain bash '{"cmd": "rm -rf /"}'
agentguard explain bash '{"cmd": "sudo apt update"}'

# Analyse a saved session
agentguard audit session.json

# Generate config file
agentguard init

# Claude Code hooks (PreToolUse + PostToolUse)
agentguard hooks                    # print JSON
agentguard hooks --install          # write to ~/.claude/hooks.json

Metis integration

agentguard's check command is designed as a Metis PostToolUse hook.

agentguard hooks --install   # one-time setup

Or add to ~/.metis/hooks.toml manually:

[[hooks]]
event      = "SessionStart"
command    = "agentguard serve --port 7420"
background = true

[[hooks]]
event   = "PreToolUse"
command = "agentguard check"

[[hooks]]
event   = "PostToolUse"
command = "agentguard check"

The daemon maintains session state across calls, enabling loop detection. Without the daemon, agentguard check runs stateless (danger + budget only).

HTTP daemon

pip install "nakata-agentguard[serve]"
agentguard serve --port 7420
# Record a tool call
curl -s -X POST http://localhost:7420/record \
  -H 'Content-Type: application/json' \
  -d '{"tool":"bash","args":{"cmd":"ls -la"}}'

# Status
curl http://localhost:7420/status

# Multi-session
curl http://localhost:7420/status?session=agent-1

# Prometheus metrics
curl http://localhost:7420/metrics

# Health
curl http://localhost:7420/health

# Reset
curl -X POST http://localhost:7420/reset
curl -X POST "http://localhost:7420/reset?session=all"

Webhook

agentguard serve --webhook-url https://hooks.example.com/agentguard

The daemon POSTs {"action":"halt","reason":"...","session":"default","ts":1234567890} to the URL on every halt or warn event. Webhook failures never block the agent.

Prometheus metrics

GET /metrics returns Prometheus text exposition:

agentguard_uptime_seconds 42.1
agentguard_active_sessions 3
agentguard_records_total 158
agentguard_tool_calls_total 158
agentguard_loop_events_total 2
agentguard_danger_events_total 4
agentguard_total_tokens 45200
agentguard_total_cost_usd 0.091

Session snapshot

# Save
guard.save("session.json")

# Load and audit
guard2 = AgentGuard.load("session.json")
print(guard2.stats())

# CLI audit
# agentguard audit session.json

nakata cluster

agentguard is part of the nakata AI reliability cluster:

  • halluguard, reverse-RAG hallucination detector
  • adaptmem, domain-adapted retrieval memory
  • claimcheck, end-to-end claim verification pipeline
  • agentguard, agentic loop and safety monitor

License

MIT

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

nakata_agentguard-0.4.0.tar.gz (38.4 kB view details)

Uploaded Source

Built Distribution

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

nakata_agentguard-0.4.0-py3-none-any.whl (31.6 kB view details)

Uploaded Python 3

File details

Details for the file nakata_agentguard-0.4.0.tar.gz.

File metadata

  • Download URL: nakata_agentguard-0.4.0.tar.gz
  • Upload date:
  • Size: 38.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for nakata_agentguard-0.4.0.tar.gz
Algorithm Hash digest
SHA256 5887ca0dc072388b030eeea09cfd54212a3bf5105aaecc8a33799500b6ad7f96
MD5 504251d13c4c165c9dbfb4fcf2cf80e8
BLAKE2b-256 253ad62f727ea0c82c7e1905121baa9c9f84683a98cb6a5621c3d890c20fc611

See more details on using hashes here.

File details

Details for the file nakata_agentguard-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for nakata_agentguard-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 79513a1e0b6618f8b711ac68dae3f777d61aad9ac5da60cfe73984c2a447340a
MD5 7513c23fc7d7d97055cbb26e38156887
BLAKE2b-256 7ac20cf6ccc9e6fd8b007ba35f75cb6f201b1a7458273b428eeb199a9ea3f2dd

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