{"slug": "sp-1-0-deterministic-reproducible-verdicts-for-ai-agent-decisions", "title": "SP/1.0: deterministic, reproducible verdicts for AI-agent decisions", "summary": "Sovereign Logic released SP/1.0, the first open-source runtime circuit breaker for AI agents, on June 25, 2026. The protocol provides deterministic, cryptographically audited verdicts on tool execution, addressing documented production failures such as agent infinite loops that consumed $6,000+ in API costs. SHACKLE operates as a sidecar daemon or in-process library, enforcing 9 mathematical invariants and Ed25519-signed append-only audit logs.", "body_md": "**Version:** 1.0.0\n\n**Status:** Published\n\n**Date:** 2026-06-25\n\n**Authors:** Dante Bullock, Sovereign Logic\n\n**License:** Creative Commons Attribution 4.0 International (CC-BY 4.0)\n\n**Reference Implementation:** [https://github.com/Fame510/SHACKLE](https://github.com/Fame510/SHACKLE)\n\n**First Public Commit:** 2026-06-17 23:12 UTC\n\nImplementations of this specification are subject to the SHACKLE license terms.The reference implementation is dual-licensed: AGPLv3 (open source) and Commercial (proprietary). Contact:[docspoc101@gmail.com]\n\nSHACKLE is a runtime circuit breaker for autonomous AI agents. It answers one question:\n\nShould this agent be allowed to execute this tool with these parameters at this moment?\n\nThe protocol defines a deterministic, verifiable decision function backed by 9 mathematical invariants, a language-agnostic message schema, Ed25519-signed append-only audit logging, and a Redis-backed distributed state engine. It operates as a sidecar daemon with gRPC/Unix socket transport, or as an in-process library for single-agent deployments.\n\nSHACKLE is the **first open-source runtime circuit breaker for AI agents** with cryptographic audit chain-of-custody. This specification is the definitive reference for the SP/1.0 protocol.\n\nAutonomous AI agents execute tools — web search, file I/O, API calls, code execution — with no runtime oversight. The framework's recursion limit or token cap is the only guardrail. When an agent enters a retry loop (same tool, same error, burning tokens each time), there is no mechanism to detect, intercept, and stop it before the wallet is empty.\n\nThis is not hypothetical. Production deployments have documented:\n\n- Agent infinite loops consuming $6,000+ in API costs before the recursion limit fired\n- Duplicate tool calls repeating 50+ times with no variation\n- Spawned child processes hanging indefinitely while consuming tokens\n\nThe industry consensus — independently reached by multiple teams in June 2026 — is that **generation authority is not release authority.** The model generates candidates. A separate mediation layer must authorize execution.\n\nSHACKLE is that mediation layer.\n\n| Principle | Meaning |\n|---|---|\nDeterministic core |\n`decide(state, call) → Verdict` is a pure function. Same inputs always produce same outputs. |\nDaemon as authority |\nThe SHACKLE daemon is the sole source of truth for time, state, and verdicts. Agents are untrusted. |\nAppend-only audit |\nEvery decision is Ed25519-signed and written to an immutable audit log. Chain-of-custody is cryptographically verifiable. |\nMathematically verified |\n9 invariant properties hold under all inputs, proven by property-based testing (Hypothesis, 500+ examples each). |\nGraceful degradation |\nAgents function in local/library mode without a daemon. Distributed state is an upgrade path. |\nFail-closed |\nNetwork failure, daemon crash, or timeout → DENY. No execution without explicit authorization. |\n\nThis specification covers:\n\n- The decision function and its 9 mathematical invariants (§3)\n- Message schemas and semantics (§4)\n- State model (§5)\n- Transport bindings (§6)\n- Audit and security (§7)\n- Compliance framework (§8)\n\nThis specification does NOT cover:\n\n- Daemon persistence layer (implementation detail)\n- HITL console UI (presentation concern)\n- Pricing or commercial terms\n\n```\nMODEL A — Library Mode (In-Process)\n┌─────────────────────────┐\n│  Agent Process          │\n│  ┌───────────────────┐  │\n│  │ @Guard decorator  │  │\n│  │ Local state only  │  │\n│  └───────────────────┘  │\n└─────────────────────────┘\n\nMODEL B — Sidecar Daemon (Production)\n┌─────────────────┐     Unix/gRPC      ┌──────────────────────────┐\n│  Agent Process  │ ◄────────────────► │  SHACKLE Daemon          │\n│  ┌───────────┐  │   pre_exec         │  ┌────────────────────┐  │\n│  │ Thin      │  │   post_exec        │  │ Policy Engine      │  │\n│  │ Client    │  │   register         │  │ - Budgets          │  │\n│  │ Shim      │  │   heartbeat        │  │ - Counters         │  │\n│  └───────────┘  │                    │  │ - Circuit Breakers │  │\n└─────────────────┘                    │  └────────────────────┘  │\n                                        │  ┌────────────────────┐  │\n                                        │  │ Audit Log          │  │\n                                        │  │ Ed25519-signed     │  │\n                                        │  │ Append-only        │  │\n                                        │  │ Chain-linked       │  │\n                                        │  └────────────────────┘  │\n                                        └──────────────────────────┘\n\nMODEL C — Distributed (Enterprise)\n┌──────────┐  ┌──────────┐  ┌──────────┐\n│ Agent A  │  │ Agent B  │  │ Agent C  │\n└────┬─────┘  └────┬─────┘  └────┬─────┘\n     └─────────────┬─────────────┘\n                   │  gRPC/TLS\n          ┌────────┴────────┐\n          │  SHACKLE        │\n          │  Daemon Cluster │\n          │  Redis (state)  │\n          │  Postgres (logs)│\n          └─────────────────┘\n┌──────────────────────────────────┐\n│    Policy Language (future)      │  ← DSL for guard rules\n├──────────────────────────────────┤\n│    Decision Function             │  ← decide(state, call) → Verdict\n├──────────────────────────────────┤\n│    Message Protocol              │  ← This specification\n├──────────────────────────────────┤\n│    Transport (Unix/gRPC/WS)      │  ← Binding layer\n└──────────────────────────────────┘\n```\n\nThe decision function is the heart of SHACKLE. It is a pure function — no I/O, no side effects, no allocations in the hot path. It is human-auditable in under 10 minutes. It is under 200 lines of logic.\n\n```\nfunction decide(\n    state: SessionState,\n    call: ToolCall,\n    config: GuardConfig,\n    rng_float: float\n) → Verdict\nLayer 1: Circuit Breaker\n    IF state.circuit_tripped:\n        → DENY(CIRCUIT_OPEN)\n\nLayer 2: Nonce Validation (Anti-Replay)\n    IF call.nonce IN state.seen_nonces:\n        → DENY(POLICY_VIOLATION)\n\nLayer 3: Budget Guard\n    IF config.budget_usd > 0:\n        IF state.budget_remaining_usd <= 0:\n            → DENY(BUDGET_EXHAUSTED)\n        IF hitl_mode == ON_THRESHOLD AND fraction <= threshold:\n            → HITL(\"budget threshold reached\")\n        IF call.cost > state.budget_remaining:\n            IF hitl_mode IN (ON_DENY, ALWAYS):\n                → HITL(\"cost exceeds remaining budget\")\n            → DENY(BUDGET_EXHAUSTED)\n\nLayer 4: Repeat Call Guard\n    IF config.max_repeat_calls > 0:\n        IF is_repeat(call, state.last_call):\n            limit = max_repeat_calls\n            IF error_amplification AND has_error_signal(call):\n                limit = max(1, limit - 1)\n            IF repeat_count >= limit:\n                → DENY(MAX_REPEAT_EXCEEDED)\n\nLayer 5: Time Window Guard\n    IF config.window_max_calls > 0:\n        IF window_count >= window_max_calls:\n            → DENY(WINDOW_EXCEEDED)\n\nLayer 6: Global Call Limit\n    IF config.max_total_calls > 0 AND total_calls >= max_total_calls:\n        → DENY(GLOBAL_LIMIT)\n\nLayer 7: Probabilistic Denial (Adversarial Hardening)\n    IF probabilistic_deny AND budget_ratio < 0.2:\n        IF rng < deny_jitter_ratio * (1.0 - budget_ratio):\n            → DENY(BUDGET_EXHAUSTED, probabilistic=true)\n\nLayer 8: HITL Always\n    IF hitl_mode == ALWAYS:\n        → HITL(\"HITL required for all calls\")\n\nDefault:\n    → ALLOW\n```\n\nThese 9 properties are verified by property-based testing (Hypothesis, Python) with 500+ randomly generated inputs each. Properties P1-P9 are **provably correct.**\n\n| # | Property | Formal Statement |\n|---|---|---|\nP1 |\nBudget monotonically non-increasing | ∀ calls: budget_after ≤ budget_before |\nP2 |\nRepeat counts non-decreasing | ∀ tool: repeat_count never decreases |\nP3 |\nOnce tripped, always tripped | circuit_tripped ⇒ all subsequent verdicts = DENY |\nP4 |\nBudget never negative | budget_remaining ≥ 0 |\nP5 |\nRepeat limit triggers DENY | repeat_count ≥ max_repeat_calls ⇒ verdict = DENY |\nP6 |\nFresh state ALLOWs first call | fresh SessionState + any ToolCall ⇒ ALLOW |\nP7 |\nDeterministic output | identical (state, call, config, rng) ⇒ identical Decision |\nP8 |\nHITL_ALWAYS produces HITL | hitl_mode = ALWAYS ∧ ¬circuit_tripped ⇒ verdict = HITL |\nP9 |\nNonce uniqueness enforced | duplicate nonce ⇒ DENY |\n\n| Verdict | Meaning | Agent Action |\n|---|---|---|\nALLOW |\nExecute as requested | Proceed with tool call |\nDENY |\nBlock execution | Abort, surface deny reason |\nHITL |\nHuman decision required | Pause, await human verdict via HITL console |\n\n| Reason | Trigger |\n|---|---|\n`CIRCUIT_OPEN` |\nCircuit breaker was previously tripped |\n`BUDGET_EXHAUSTED` |\nBudget remaining ≤ 0 or cost > remaining |\n`MAX_REPEAT_EXCEEDED` |\nSame tool + same params repeated too many times |\n`WINDOW_EXCEEDED` |\nToo many calls in the current time window |\n`GLOBAL_LIMIT` |\nSession-wide call limit reached |\n`POLICY_VIOLATION` |\nDuplicate nonce (replay attack) |\n`AUTH_FAILED` |\nAuthentication failure |\n\nSHACKLE detects error signals in tool parameters WITHOUT regex (no ReDoS attack surface). When `error_amplification`\n\nis enabled, the repeat call threshold is reduced by 1 if the parameters contain known error signals:\n\n```\nError signals: 401, unauthorized, 403, forbidden, 500, 502, 503,\n               504, timeout, connection refused, connection reset,\n               permission denied, rate limit, quota exceeded,\n               invalid api key, token expired, model not found,\n               resource exhausted, deadline exceeded\n```\n\nThis catches the \"loop of death\" — agent hits 401, retries, gets 401, retries — without waiting for the full repeat threshold.\n\nWhen `probabilistic_deny`\n\nis enabled and the agent is below 20% budget, a random factor is introduced:\n\n```\nprobability = deny_jitter_ratio × (1.0 − budget_ratio)\nIF rng < probability:\n    → DENY (appears as BUDGET_EXHAUSTED)\n```\n\nThis prevents adversarial agents from probing the exact budget threshold and gaming it. The denial appears identical to a real budget exhaustion, making it impossible to distinguish signal from noise.\n\nEvery SHACKLE message is wrapped in a Protocol Buffers envelope:\n\n```\nmessage Envelope {\n  string protocol_version = 1;       // \"1.0.0\"\n  string message_id = 2;             // UUIDv7, client-generated\n  string correlation_id = 3;         // Request/response pairing\n  int64 client_timestamp_ns = 4;     // Client clock (informational)\n  int64 server_timestamp_ns = 5;     // Set by daemon on receipt\n  bytes hmac = 6;                    // HMAC-SHA256 over payload\n  oneof payload {\n    PreExecRequest pre_exec = 10;\n    PreExecResponse pre_exec_response = 11;\n    PostExecNotification post_exec = 12;\n    RegisterRequest register = 13;\n    RegisterResponse register_response = 14;\n    Heartbeat heartbeat = 15;\n    HeartbeatAck heartbeat_ack = 16;\n    Error error = 17;\n  }\n}\nmessage RegisterRequest {\n  string agent_id = 1;\n  string agent_version = 2;\n  string framework = 3;              // \"crewai\" | \"autogen\" | \"langgraph\"\n  string session_id = 4;             // Optional: resume existing session\n  string organization_id = 5;\n  string runtime = 6;\n  map<string, string> metadata = 7;\n}\n\nmessage RegisterResponse {\n  string session_id = 1;\n  string daemon_version = 2;\n  string negotiated_protocol = 3;\n  GuardConfig active_config = 4;\n  int64 daemon_time_ns = 5;\n}\nmessage PreExecRequest {\n  string session_id = 1;\n  uint64 call_number = 2;            // Monotonically increasing\n  string tool_name = 3;\n  bytes tool_params_hash = 4;        // SHA-256 of canonical JSON params\n  double estimated_cost_usd = 5;\n  string parent_guard_id = 6;        // For nested guard trees\n  uint64 nonce = 7;                  // Anti-replay\n  map<string, string> tags = 8;\n}\n\nmessage PreExecResponse {\n  string session_id = 1;\n  uint64 call_number = 2;\n  Verdict verdict = 3;\n  DenyReason deny_reason = 4;\n  string human_readable_reason = 5;\n  double budget_remaining_usd = 6;\n  int32 repeat_count = 7;\n  int64 daemon_time_ns = 8;\n  bool probabilistic_deny = 9;\n}\n```\n\nFire-and-forget. No response expected.\n\n```\nmessage PostExecNotification {\n  string session_id = 1;\n  uint64 call_number = 2;\n  double actual_cost_usd = 3;\n  bool success = 4;\n  string error_message = 5;\n  int64 duration_ms = 6;\n  uint64 tokens_in = 7;\n  uint64 tokens_out = 8;\n  string model_used = 9;\n}\n```\n\nAgents SHOULD send heartbeats every 30 seconds. 3 consecutive missed heartbeats → session marked STALE.\n\n```\nmessage Heartbeat {\n  string session_id = 1;\n  uint64 last_call_number = 2;\n  double local_budget_remaining = 3;  // For drift detection\n}\n\nmessage HeartbeatAck {\n  string session_id = 1;\n  double daemon_budget_remaining = 2; // Authoritative view\n  bool drift_detected = 3;\n  int64 daemon_time_ns = 4;\n}\nservice ShackleDaemon {\n  rpc Register(RegisterRequest) returns (RegisterResponse);\n  rpc PreExec(PreExecRequest) returns (PreExecResponse);\n  rpc PostExec(PostExecNotification) returns (google.protobuf.Empty);\n  rpc Heartbeat(Heartbeat) returns (HeartbeatAck);\n  rpc GetSessionState(GetSessionStateRequest) returns (SessionState);\n}\nmessage SessionState {\n  string session_id = 1;\n  string agent_id = 2;\n  string organization_id = 3;\n  SessionStatus status = 4;          // ACTIVE | PAUSED | TERMINATED | STALE\n\n  // Budget\n  double budget_initial_usd = 10;\n  double budget_remaining_usd = 11;\n  double budget_spent_usd = 12;\n\n  // Counters\n  uint64 total_calls = 20;\n  map<string, uint32> repeat_counts = 21;   // tool_name → consecutive identical calls\n  map<string, uint32> window_counts = 22;   // tool_name → calls in current window\n\n  // Circuit\n  bool circuit_tripped = 30;\n  string circuit_trip_reason = 31;\n  int64 circuit_tripped_at_ns = 32;\n\n  // Time\n  int64 window_start_ns = 40;\n  uint32 window_duration_s = 41;\n  uint32 window_max_calls = 42;\n\n  // Last known\n  string last_tool_name = 50;\n  bytes last_tool_params_hash = 51;\n  int64 last_activity_ns = 52;\n\n  // Metadata\n  map<string, string> metadata = 60;\n}\n\nenum SessionStatus {\n  ACTIVE = 0;\n  PAUSED = 1;       // HITL in progress\n  TERMINATED = 2;\n  STALE = 3;        // Heartbeat timeout\n}\nmessage GuardConfig {\n  // Budget\n  double budget_usd = 1;              // 0 = disabled\n  BudgetScope budget_scope = 2;       // PER_SESSION | PER_AGENT | PER_ORG\n\n  // Repeat calls\n  uint32 max_repeat_calls = 10;       // 0 = disabled\n  bool error_amplification = 11;      // Lower threshold on error signals\n\n  // Timeout\n  uint32 timeout_seconds = 20;        // Wall-clock timeout. 0 = disabled\n\n  // Time window\n  uint32 window_duration_s = 30;\n  uint32 window_max_calls = 31;\n\n  // Global limits\n  uint32 max_total_calls = 40;        // 0 = disabled\n\n  // Adversarial hardening\n  bool probabilistic_deny = 50;\n  double deny_jitter_ratio = 51;      // 0.0–1.0\n\n  // HITL\n  HitlMode hitl_mode = 60;            // NEVER | ON_DENY | ON_THRESHOLD | ALWAYS\n  double hitl_budget_threshold = 61;  // 0.0–1.0\n\n  // Hierarchy\n  string parent_guard_id = 70;        // For nested guard trees\n}\n\nenum BudgetScope {\n  PER_SESSION = 0;\n  PER_AGENT = 1;\n  PER_ORGANIZATION = 2;\n}\n\nenum HitlMode {\n  HITL_NEVER = 0;\n  HITL_ON_DENY = 1;\n  HITL_ON_BUDGET_THRESHOLD = 2;\n  HITL_ALWAYS = 3;\n}\n```\n\nState is NEVER mutated by the decision function. The daemon applies state changes AFTER the verdict is returned:\n\n**After ALLOW:** Increment counters, record nonce, update repeat/window counts**After DENY:** Trip circuit breaker (session-wide block)**After HITL:** Set session status to PAUSED, await human verdict**After PostExec:** Update budget (budget_spent += actual_cost)\n\n```\nPath:       /var/run/shackle.sock\nPermissions: 0660, owned shackle:agents\nFraming:    Length-prefixed protobuf (4-byte big-endian length + protobuf bytes)\nSLA:        5ms for pre_exec, 1s for register\nEndpoint:   grpc://localhost:9000 or grpcs:// for TLS\nService:    ShackleDaemon (see §4.6)\nAuth:       mTLS with client certificates\nSLA:        5ms for pre_exec, 1s for register\nEndpoint:   wss://shackle.example.com/v1/control\nAuth:       Bearer token in initial connect\nMessages:   JSON-encoded protobuf over text frames\nPurpose:    Remote HITL console, cross-network agents\nmessage AuditEntry {\n  string entry_id = 1;               // UUIDv7\n  int64 timestamp_ns = 2;            // Daemon time\n  string session_id = 3;\n  string agent_id = 4;\n  string organization_id = 5;\n  uint64 call_number = 6;\n  string tool_name = 7;\n  bytes tool_params_hash = 8;\n  Verdict verdict = 9;\n  DenyReason deny_reason = 10;\n  double budget_before_usd = 11;\n  double budget_after_usd = 12;\n  string operator_id = 13;           // Human operator if HITL override\n  bytes signature = 14;              // Ed25519 over fields 1–13\n  bytes previous_entry_hash = 15;    // Chain-link to previous entry\n}\n```\n\n| Property | Mechanism |\n|---|---|\nAuthenticity |\nEd25519 signature over all entry fields |\nIntegrity |\nChain-linked via `previous_entry_hash` (SHA-256) |\nImmutability |\nAppend-only file (O_APPEND, no seek permitted) |\nNon-repudiation |\nSigning key held exclusively by daemon; verification key is public |\nVerifiability |\nAny third party can verify the chain with only the public verification key |\n\n| Component | Trust Level | Rationale |\n|---|---|---|\n| SHACKLE Daemon | Fully trusted |\nHolds state, writes audit log, issues verdicts |\n| Agent Process | Untrusted |\nMay be compromised, buggy, or adversarial |\n| Transport | Authenticated + integrity-protected |\nHMAC on every message |\n| HITL Console | Authenticated user |\nHuman decision with audit trail |\n\n| Threat | Mitigation |\n|---|---|\n| Replay attack | Nonce per call; daemon tracks seen nonces (§3.2, Layer 2) |\n| Identity spoofing | Registration with org-level auth (§4.2) |\n| Clock manipulation | Daemon is sole time authority; client timestamps are informational |\n| Budget drift | Heartbeat sync with authoritative state (§4.5) |\n| Adversarial probing | Probabilistic denial near thresholds (§3.7) |\n| Audit tampering | Append-only file; Ed25519 signatures; chain-linked entries (§7.2) |\n| DoS | Rate limiting per session; message size cap (1MB) |\n| Protocol parser exploits | Separate process for parsing; seccomp sandbox |\n\n- Daemon runs as dedicated user (\n`shackle`\n\n), NOT root - Unix socket owned\n`shackle:agents`\n\n, mode 0660 - Audit log file owned\n`shackle:shackle`\n\n, mode 0640, append-only - Rate limit: 1,000 pre_exec/sec/session; 10 register/sec/IP\n- Max message size: 1MB\n- Daily log rotation with compression and archival\n\n| SOC2 TSC | SHACKLE Feature | Evidence |\n|---|---|---|\nCC6.1 Logical Access |\nSession registration + authentication | RegisterRequest with org_id |\nCC6.3 Security Incidents |\nCircuit breaker trip events | AuditEntry with DENY verdict |\nCC7.2 System Monitoring |\nHeartbeat + drift detection | Heartbeat/HeartbeatAck messages |\nCC7.3 Incident Response |\nHITL console with operator audit trail | operator_id in AuditEntry |\nCC8.1 Change Management |\nVersion negotiation + LTS policy | §9 |\nA1.2 Availability |\nTimeout enforcement | timeout_seconds in GuardConfig |\nC1.1 Confidentiality |\nOn-premise daemon, no telemetry | Model B/C deployment; local-only |\nPI1.3 Processing Integrity |\nDeterministic decision function | §3.3 properties P1–P9 |\n\nSHACKLE audit logs are designed to satisfy:\n\n**SOC2 Type II** auditor requests**ISO 27001** Annex A.12.4 (Logging and Monitoring)**GDPR Article 30**(Records of Processing) — for agent actions on personal data** Cyber insurance**underwriting requirements\n\nProtocol versions follow SemVer: `MAJOR.MINOR.PATCH`\n\n**MAJOR:** Incompatible message schema changes**MINOR:** New message types, backward-compatible additions**PATCH:** Clarifications, bug fixes, no schema changes\n\n| Version | Date | Changes |\n|---|---|---|\n1.0.0 |\n2026-06-25 | Initial release. 9 invariant properties. Unix/gRPC transport. Ed25519 audit. |\n\n- SP/1.0 is the LTS version, guaranteed support through 2031\n- New major versions coexist with previous LTS for minimum 2 years\n- Audit log schema is append-only: fields added, never removed\n- Deprecated fields marked with annotation, never deleted\n\n```\nClient → Daemon: protocol_version = \"1.2.0\"\nDaemon checks:   can support up to 1.0.0\nDaemon → Client: negotiated_protocol = \"1.0.0\"\n```\n\nNo compatible version → Error with code `PROTOCOL_VERSION_MISMATCH`\n\n.\n\nThe Python reference implementation lives at:\n\n[https://github.com/Fame510/SHACKLE](https://github.com/Fame510/SHACKLE)\n\n| Component | File | Status |\n|---|---|---|\n| Decision function | `v2/spec/decide.py` |\n✅ Production (187 lines) |\n| Property-based tests | `v2/tests/test_decide_properties.py` |\n✅ 18/18 passing |\n| Protocol definitions | `v2/protocol/shackle.proto` |\n✅ Complete |\n| Service definitions | `v2/protocol/shackle_service.proto` |\n✅ Complete |\n| CI pipeline | `.github/workflows/ci.yml` |\n✅ Configured |\n| TypeScript library | `v2/ts/` |\n✅ Published |\n| Docker image | `Dockerfile` |\n✅ Multi-stage |\n\n``` python\nfrom shackle import Guard\n\n@Guard(budget=0.50, max_repeat_calls=3, timeout_seconds=180)\ndef my_agent():\n    # Agent logic here\n    # SHACKLE intercepts every tool call\n    pass\n```\n\nInstall: `pip install git+https://github.com/Fame510/SHACKLE.git`\n\n```\n1.  Agent → Daemon: REGISTER(agent_id=\"research-bot\", framework=\"crewai\")\n2.  Daemon → Agent: REGISTER_RESPONSE(session_id=\"s_01\", config={budget:0.50, max_repeat:3})\n\n3.  Agent → Daemon: PRE_EXEC(call=1, tool=\"web_search\", hash=0xDEAD, cost=0.002)\n4.  Daemon → Agent: PRE_EXEC_RESPONSE(verdict=ALLOW, budget_remaining=0.498)\n\n5.  Agent: [executes web_search]\n6.  Agent → Daemon: POST_EXEC(call=1, actual_cost=0.0015, success=true)\n\n7.  Agent → Daemon: PRE_EXEC(call=2, tool=\"web_search\", hash=0xDEAD, cost=0.002)\n8.  Daemon → Agent: PRE_EXEC_RESPONSE(verdict=ALLOW, budget_remaining=0.496, repeat_count=1)\n\n    ... agent repeats 2 more times ...\n\n9.  Agent → Daemon: PRE_EXEC(call=4, tool=\"web_search\", hash=0xDEAD, cost=0.002)\n10. Daemon → Agent: PRE_EXEC_RESPONSE(verdict=DENY, reason=MAX_REPEAT_EXCEEDED, repeat_count=3)\n\n11. Daemon: [writes AuditEntry to append-only log]\n12. Daemon: [trips circuit breaker for session — all subsequent calls DENY]\n```\n\n| Code | Description |\n|---|---|\n`PROTOCOL_VERSION_MISMATCH` |\nNo compatible protocol version |\n`SESSION_NOT_FOUND` |\nUnknown or expired session_id |\n`AUTHENTICATION_FAILED` |\nInvalid credentials or duplicate nonce |\n`RATE_LIMITED` |\nToo many requests |\n`MESSAGE_TOO_LARGE` |\nExceeds 1MB limit |\n`DAEMON_UNAVAILABLE` |\nInternal daemon error |\n`ORGANIZATION_QUOTA_EXCEEDED` |\nOrg-level limit reached |\n`PARENT_GUARD_DENIED` |\nParent guard rejected the call |\n\n| Term | Definition |\n|---|---|\nAgent |\nAn autonomous AI process that executes tools |\nCircuit Breaker |\nOnce tripped, all subsequent calls are DENY |\nDaemon |\nThe SHACKLE server process — sole authority for state and verdicts |\nGuard |\nA configured policy (budget, repeat limit, timeout) applied to an agent |\nHITL |\nHuman-in-the-Loop — manual authorization step |\nNonce |\nA number used once — anti-replay mechanism |\nTool Call |\nA single invocation of an agent tool (API, file I/O, code exec) |\nVerdict |\nThe decision: ALLOW, DENY, or HITL |\n\n*SP/1.0 — Sovereign Logic, June 2026. Licensed under CC-BY 4.0.*\n\n*Reference implementation: AGPLv3 + Commercial. Contact: docspoc101@gmail.com*", "url": "https://wpnews.pro/news/sp-1-0-deterministic-reproducible-verdicts-for-ai-agent-decisions", "canonical_source": "https://github.com/Fame510/SHACKLE/blob/master/SP-1.0-SPECIFICATION.md", "published_at": "2026-07-26 17:41:16+00:00", "updated_at": "2026-07-26 17:52:36.064535+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-tools", "ai-infrastructure"], "entities": ["Sovereign Logic", "Dante Bullock", "SHACKLE", "SP/1.0"], "alternates": {"html": "https://wpnews.pro/news/sp-1-0-deterministic-reproducible-verdicts-for-ai-agent-decisions", "markdown": "https://wpnews.pro/news/sp-1-0-deterministic-reproducible-verdicts-for-ai-agent-decisions.md", "text": "https://wpnews.pro/news/sp-1-0-deterministic-reproducible-verdicts-for-ai-agent-decisions.txt", "jsonld": "https://wpnews.pro/news/sp-1-0-deterministic-reproducible-verdicts-for-ai-agent-decisions.jsonld"}}