Write the safety policy once. Run it everywhere your agents can act.
JamJet sits underneath your agent (Claude Code, OpenAI Agents SDK, MCP clients, LangChain, CrewAI, ADK, Spring AI, custom code) and enforces what prompts cannot:
- π‘οΈ Block unsafe tool calls at runtime: database deletes, payments, file writes
- β Pause for human approval on risky actions, durably
- πΈ Cap cost per agent, per run, per project
- π Record an audit trail that survives a regulator's review
- βͺ Replay or resume crashed runs from the last checkpoint
Keep your agent framework. Add JamJet where tool calls need control.

See it in 60 seconds
pip install jamjet
jamjet demo unsafe-tool-call
No API key. No Docker. No cloud account. The model is mocked; the enforcement path is real. Three more demos run the same way:
jamjet demo approval # pause-for-approval flow
jamjet demo budget-cap # $0.05 cost cap
jamjet demo mcp-tool-policy # MCP-shaped policy (preview of JamJet Gateway)
Works alongside Claude Code Β· OpenAI Agents SDK Β· MCP clients Β· LangChain Β· CrewAI Β· ADK Β· Spring AI Β· LangChain4j.
On the JVM: one dependency
Spring AI and LangChain4j teams get the same layer without writing glue code. The Spring Boot starter auto-injects JamJet advisors into your ChatClient: every call becomes durable and audited, with no changes to your application code.
<dependency>
<groupId>dev.jamjet</groupId>
<artifactId>jamjet-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency>
spring.jamjet.runtime-url=http://localhost:7700
spring.jamjet.approval.enabled=true # opt-in human-in-the-loop approval
Crash recovery, event sourcing, and a REST endpoint to approve or reject held actions. Falls back gracefully if the runtime is unreachable.
Prefer no sidecar at all? JamJet Java Runtime embeds durable execution directly in your JVM process: Java 21, no Docker, 8.9Γ faster than calling out to a REST sidecar (benchmark and launch post). Works with Spring AI, LangChain4j, and Google ADK.
β See a Spring Boot agent survive kill -9 mid-run in examples/loan-underwriter-agent: resumes from disk checkpoints, gates disbursement on human approval, emits a signed receipt bundle.
The same policy, everywhere
Every agent toolchain is inventing its own safety layer. JamJet gives you one policy file and one audit trail across all of them.
All adapters load the same policy.yaml. All emit conformant audit JSONL to ~/.jamjet/audit/. Run jamjet audit show to tail every decision across every adapter in one chronological view.
JamJet does not replace the hook points these platforms give you. It makes them do more: Claude Code's PreToolUse hook gets a real policy engine, approval flow, and audit trail, and the same rules carry unchanged to OpenAI Agents SDK, MCP clients, Spring AI, and your own Python or TypeScript code.
One policy, every adapter
# ~/.jamjet/policy.yaml
version: 1
rules:
- { match: "*delete*", action: block }
- { match: "payments.*", action: require_approval }
- { match: "shell.exec", action: block }
Drop this file in ~/.jamjet/. Every adapter listed above uses it automatically.
Prompts are not a security boundary. The runtime is.
β Read When AI Deletes the Database for why this is a runtime architecture problem, not a model problem.
β See the deeper durability demo at jamjet.dev/demo for what happens when an agent crashes mid-tool-call.
Policy in your own code
Drop a policy beside your agent code. The runtime intercepts any matching tool call before it leaves the agent's process: blocked_tools are refused outright, require_approval_for pauses execution durably and waits for an out-of-band decision. Crashes don't lose the approval; execution resumes when it arrives.
# workflow.yaml
policy:
blocked_tools:
- "*delete*"
- "payments.refund"
require_approval_for:
- "database.*"
- "payment.transfer"
- "user.suspend"
Python, with the hosted control plane:
import jamjet
jamjet.cloud.configure(api_key="jj_...", project="my-agent")
jamjet.cloud.policy("block", "*delete*")
jamjet.cloud.policy("require_approval", "database.*")
# Every OpenAI / Anthropic call in this process is now policy-gated.
β Runnable approval workflow in examples/hitl-approval Β· Cloud Quickstart
Where JamJet sits
Your Agent / Framework
(LangChain Β· CrewAI Β· ADK Β· custom Β· MCP client)
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββ
β JamJet Safety Layer β
β policy Β· approval Β· budget Β· audit Β· replay β
βββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
Tools Β· MCP servers Β· APIs Β· DBs Β· Agents
Use JamJet when your agent canβ¦
- call MCP servers or arbitrary tools
- write to a database
- send emails or Slack messages
- trigger payments or external API calls
- access customer data or PII
- run for minutes/hours and needs to survive crashes
- spend real model budget at scale
- delegate to other agents
What JamJet adds
| Without JamJet | With JamJet |
|---|
| Agent crashes lose progress | Resume from the last checkpoint |
| Tool calls rely on scattered app logic | Runtime policy blocks unsafe actions |
| Human approval is custom glue | Approval is a durable workflow step |
| Costs are discovered after the bill | Budgets enforced per agent / per run |
| Audit evidence is stitched from logs | Append-only event log, signed export |
| Memory is framework-specific | Pair with Engram for portable memory (MCP Β· REST Β· Python Β· Java) |
| Frameworks stay siloed | MCP + A2A connect tools and agents |
A full runtime underneath
The safety layer runs on a durable, event-sourced execution engine. When you want more than enforcement, it's already there: