Runtime governance and conformance you can reproduce. SHACKLE adds a Python runtime guard for repeated tool calls, estimated LLM spend, timeouts, and policy decisions. It also publishes SP/1.0.1, a versioned mediation contract with public, hash-pinned test profiles.
Current status (2026-09-23). The reference code now includes model-aware pricing resolution, latched fail-closed aborts, pre-call timeout/budget gates, two-layer LiteLLM interception (including early-bound imports), native CrewAI hooks, and optional strict coverage-gap detection. These are shipped, regression-tested changes—not a claim that every framework path or deployment is covered. See INTEGRATIONS.md for path and version limits.
- Model-aware pricing: exact model IDs, provider prefixes, and delimiter-bounded dated variants resolve to known pricing rows; unknown models use the default row with a warning. This fixes a tested undercount for IDs such as
openai/gpt-4that previously landed on the generic default. - Terminal-abort latching: if a supported framework catches an interrupt, the original trigger remains latched and is surfaced at the
Guardboundary; later hooked calls are denied. - Pre-call gates: supported LLM paths check known elapsed-time and exhausted-budget conditions before sending another request. Usage/cost accounting still depends on each integration's available token data and can be eventual on callback paths.
- Broader tested hooks: LiteLLM module rebinding plus a call-time gate for early-bound imports, and native CrewAI before-tool / before-LLM / after-LLM hooks.
- Coverage visibility: detected hook gaps are reported;
Guard(strict=True)can refuse to run when detected gaps remain. Detection cannot prove that every custom/dynamic path has been found.
These controls improve tested integration paths; SHACKLE is not a universal process sandbox and does not guarantee exact provider invoices or prevent every possible spend overrun. Keep provider-side limits and monitoring enabled.
Certification is bound to an exact artifact. The public registry and verification report now bind the owner-verified reference v2 runtime to commit
a45eaa863a7d2afb0847ce81d0952737abdf98faand source archive SHA-2569aef63709dd0d8241398c0bea095521e5258067d0caca3ca24e1b9dc0fe078cd, with the four official hash-pinned profiles (15 + 14 + 31 + 22 = 82 cases). This is owner self-verification of that artifact and stated scope—not an independent certification or a guarantee of absolute security, production enforcement, legal sufficiency, or absence of vulnerabilities.
Fresh verification after the CrewAI/LiteLLM accounting fix:
pytest tests/passed 323 tests; the repository-root suite passed 394 tests;tools/verify_certification.pyreturned PASS ona45eaa863a7d2afb0847ce81d0952737abdf98fa; registry validation passed. The independent reviewer’s regression scenario was also reproduced: five fake provider requests yielded five accounting events, not ten. Earlier GitHub CI run 35928877645 passed all five jobs on the preceding runtime hardening commite93ef3c; that CI result is not a CI claim fora45eaa8.
Publication record. First release commit 2026-06-17 (
9fbf7c3a); V2 foundation 2026-06-18. SP/1.0 specification published 2026-06-24; SP/1.0.1 implementation tightening 2026-07-30. The original 15-vector surface has historical independent reproductions from July 4 and July 29. See PROVENANCE.md for dates, commits, attribution, and boundaries.
pip install pyshackleAI agents are capable, but their error handling is broken. When an agent hits an unhandled tool error (401 Unauthorized, a changed API payload, a dead endpoint), it rarely self-corrects. It enters a "Loop of Death": retrying the same tool with the same input, burning your context window and running up a large API bill in minutes.
Frameworks like CrewAI, AutoGen, and LangGraph don't ship a native, framework-agnostic spending guardrail or deterministic loop breaker.
SHACKLE is an in-process Python governance layer with a separate v2 sidecar option. Guard tracks execution state and attaches hooks to supported integration paths. When an observed tool/LLM call reaches a configured limit or policy gate, SHACKLE can deny, pause for operator input, or abort. Coverage depends on the framework path, installed integration, and configuration; it is not a universal process sandbox.
- Loop controls: detect repeated tool calls and tested error-cascade patterns
- Spend accounting: resolve exact, provider-prefixed, and dated model IDs against known pricing rows; unknown models fall back to the default row with a warning
- Pre-call checks: enforce known exhausted budget and elapsed-time limits at supported LLM call gates; post-call token usage remains integration-dependent
- Fail-closed handling: latch terminal aborts across tested framework exception-swallowing paths
- Integration coverage visibility:
Guard(strict=True)can reject startup when detected coverage gaps remain - Local by design for v1: execution hooks run in the user's Python process; v2 provides a separate daemon architecture
These are tested controls, not a guarantee of final provider billing accuracy, total framework coverage, or prevention of every spend overrun. Keep provider-side caps and monitoring enabled.
1. Install
# From PyPI (import name stays `shackle`)
pip install pyshackle
# Or from source
git clone https://github.com/Fame510/SHACKLE.git
cd SHACKLE && pip install -e .2. Guard your workflow
from shackle import Guard
from crewai import Crew
my_crew = Crew(agents=[...], tasks=[...])
# One line to add circuit breaking
@Guard(budget=0.25, max_repeat_calls=3, timeout_seconds=180)
def run():
return my_crew.kickoff()
run()For the supported hooks on the versions and execution paths you use, this can add governance without changing framework internals. Check Guard.last_coverage and consult INTEGRATIONS.md; the decorator alone does not establish that every provider/tool path is covered.
| Trigger | Condition | Default | Effect on a covered path |
|---|---|---|---|
| REPETITIVE_TOOL_CALL | Same tool + same input repeated, with greater sensitivity for tested error signals | 3 attempts | Routes to the configured operator / deny behavior |
| BUDGET_EXCEEDED | Estimated accumulated model cost reaches the configured limit | $0.20 | Denies or interrupts the next observed call; provider billing may differ |
| TIMEOUT_REACHED | Wall-clock execution exceeds the configured threshold | 180 seconds | Stops a subsequent covered operation; does not forcibly terminate arbitrary native code |
| MAX_TOOL_CALLS | Total observed tool invocations exceed the configured limit | 50 calls | Denies a subsequent covered tool call |
Model pricing is resolved against the local table, including recognized provider prefixes and dated IDs. Unknown model rates fall back to the configured default row with a warning. Cost tracking is an estimate; retain provider-side caps and monitoring.
| Framework | Current coverage | Boundary |
|---|---|---|
| CrewAI | Native before-tool / before-LLM / after-LLM hooks, plus detected tool/agent hooks | Verified against the supported CrewAI 1.x test path; hook API and provider path matter. Not a claim that every CrewAI version or custom provider path is covered. |
| LangChain / LangGraph | LiteLLM completion hooks and LangChain BaseTool.run/arun hooks where calls use those paths |
No framework-wide coverage claim; unhooked call paths must be assessed separately. |
| AutoGen | Supported AutoGen wrapper; LiteLLM gate applies to calls that route through LiteLLM | Guard does not ship a native AutoGen hook. Do not infer all AutoGen LLM calls are intercepted. |
| Smolagents | No native Guard hook | Coverage is conditional on routing through a supported LiteLLM path; otherwise use another enforcement integration. |
Guard.last_coverage reports detected coverage gaps. Guard(strict=True) can refuse to start when it detects a gap; it cannot identify every custom or dynamically loaded path. See INTEGRATIONS.md for exact setup and limitations.
Deployment modes: v1 runs in-process — ideal for development, CLI agents, and supervised workflows where a human can act on the HITL prompt. For headless production, the v2 runtime moves decisions to a sidecar daemon with distributed budget state, Ed25519-signed audit logs, and remote HITL control. Same SP/1.0 contract in both modes.
The front page keeps it short on purpose. Full detail lives in focused docs:
- INTEGRATIONS.md — LiteLLM guardrails, the supported AutoGen wrapper, and integration-specific coverage limits.
- CERTIFICATION.md — certification policy, exact claim scope, exclusions, evidence requirements, and lifecycle.
- CERTIFICATION-VERIFICATION-2026-09-23.md — owner verification record for the exact registry-bound runtime artifact and official profile hashes.
- fixtures/certification-profiles.json — official profile IDs, applicability and SHA-256 pins (four profiles, 82 cases total).
- CONFORMANCE.md — the SP/1.0 decision surface and conformance model.
- v2/README.md — sidecar daemon architecture and setup.
The 323/394 suite counts above and the fresh certification verification apply to the corrected source commit a45eaa863a7d2afb0847ce81d0952737abdf98fa; the earlier d9fb4e3 result is retained in the report as historical context.
SHACKLE, the Required ⊆ Supported conformance model, the decide() surface, and the SP/1.0 HITL transition contract are authored by Dante Bullock (@Fame510), sole author, founder of Sovereign Logic, first published 2026-06-17. Full provenance and attribution terms are in CONFORMANCE.md.
| Component | License |
|---|---|
| SP-1.0 Specification & conformance fixtures | CC BY 4.0 — free to implement, attribution required |
| pyshackle runtime & reference implementation | AGPL-3.0 — commercial licensing available |
Implementing the SP/1.0 specification or running the published fixtures against your own runtime requires no license from us beyond attribution. The pyshackle code stays AGPLv3 — free for individuals, hobbyists, and open-source projects; shipping it inside a closed-source or commercial product requires a commercial license, which removes the copyleft obligation and adds SLA support.
📧 Commercial licensing, production deployment, or conformance guidance: docspoc101@gmail.com
LLM orchestration is non-deterministic. SHACKLE is a best-effort circuit breaker and does not guarantee preventing all API spend overruns; you remain responsible for monitoring your own API limits and bills. See LICENSE for full terms.