JamJet ADK
The agent kit that's durable and governed by default.
Build an agent in nine lines. Ship it to production without rewriting. Every run is durable, every tool call is policy-checked, every action lands in a signed audit trail.
from jamjet import Agent, tool
@tool
def get_weather(city: str) -> str:
return fetch_weather(city)
weather = Agent(
model="anthropic/claude-opus-4-8",
instructions="Answer weather questions.",
tools=[get_weather],
)
print(weather.run("What should I pack for Tokyo this weekend?")) Durable. Governed. Audited. Replayable. You wrote none of it.
- crash recovery
- policy enforced
- approval-ready
- receipt minted
Proof
Kill the worker. The agent finishes.
JamJet checkpoints every turn to a durable event log. When the process dies, another worker restores from the last checkpoint and continues. The completed run mints a verifiable receipt.
$ python agent.py run_id: run_8f2a1c · worker_id: w-01 [turn 1] model call started... [turn 1] tool: get_weather("Tokyo") ok [turn 1] checkpoint committed [turn 2] model call started... SIGTERM received · worker w-01 terminated scheduler: lease expired on run_8f2a1c worker w-02: restoring from checkpoint... [turn 2] resumed from turn-1 snapshot [turn 2] tool: get_weather("Tokyo") skipped (idempotent) [turn 2] model call completed run complete · receipt: ab3f7c91...
Recorded simulation of the crash-recovery sequence. The idempotency key
on get_weather prevents the tool from re-running on resume.
Lost state on crash
A worker dies mid-run. JamJet restores from the last committed turn and continues. No work is lost; no step reruns unnecessarily.
Skipped approvals
A risky tool reaches for production. The run pauses at a durable hold. Once a person approves, it continues from exactly that point.
Runaway cost
A reflection loop keeps calling the model. Budget caps and loop-detection halt the run before it crosses the configured ceiling.
Quickstart
Up and running in five minutes.
Install the SDK, scaffold a project, and start the whole local stack with one command. Durable execution and governance are on by default. No config files, no infrastructure to wire up.
- Scaffold $ jamjet create myagent
A runnable agent and a project layout, ready to go.
- Start the stack $ cd myagent && jamjet dev
Model sidecar, durable engine, and tool worker. One command.
- Run it
Every run checkpoints turns, checks policy, and emits a receipt. You wrote none of that.
Lock the behavior in: jamjet eval trajectory-diff is a
deterministic replay-regression gate for CI.
$ pip install jamjet $ jamjet create myagent created myagent/ agent.py pyproject.toml README.md $ cd myagent && jamjet dev model sidecar ready durable engine ready :7700 python worker ready $ python agent.py run_id run_4a8b2f policy ok receipt 3e9f1d2a
Build
Agents, tools, teams, memory.
The authoring surface stays out of your way. One import, one class, one decorator. Add capabilities by adding arguments.
Agent
The front door for most agents. Supply a model, instructions, and tools. Everything else is defaults you can override.
agent = Agent(
model="openai/gpt-4o",
instructions="...",
tools=[search, file_read],
)
result = agent.run("Summarise last week's reports") @tool
Any Python function becomes a governed tool. The runtime handles schema inference, idempotency keys, and audit on every call.
@tool
def send_email(to: str, body: str) -> str:
# policy-checked, idempotent, audited
return mailer.send(to, body) Sessions and memory
A session is a long-running, resumable conversation thread. Engram bridges long-term memory so context persists across restarts and sessions without you managing it.
session = agent.session(id="user-42")
session.run("What did we discuss last week?") MCP tools
Any MCP server's tools are usable directly. JamJet can also expose your agents and tools as an MCP server for other clients.
agent = Agent(
tools=[
MCPClient("github", "npx @github/mcp"),
MCPClient("postgres", "npx @pg/mcp"),
]
) Multi-agent
Compose agents into a team.
Wire specialists into a sequence, fan them out in parallel, or let a coordinator route to the right one. Each sub-agent is its own governed durable run.
Sequential
Chain agents end to end. Each agent's output becomes the next one's input.
pipeline = Sequential(
agents=[draft, review, publish],
)
pipeline.run_durable("Ship the Q3 note") Parallel
Fan one input out to many agents at once, then merge their results.
collect keeps them all; first takes the
fastest.
board = Parallel(
agents=[legal, finance, risk],
merge="collect",
) Coordinator
A coordinator agent reads the input and routes it to the right specialist. One front door, many experts.
desk = Team(
agents=[billing, support, sales],
coordinator=router,
)
desk.run("Where is my refund?") Loop
Run one agent in a loop, refining its own output until a predicate passes or the iteration cap is hit.
refine = Loop(
critic,
until=is_clean,
max_iters=5,
)
Call .run(input) to orchestrate in-process, or
.run_durable(input) to run each sub-agent on the engine.
Both return a TeamResult carrying every step's output.
Governance
Policy. Approval. Audit. Receipts.
Every agent runs under policy. Risky tool calls wait for a human. Every decision lands in a signed audit trail. The whole loop shipped. You add it with arguments.
- Policy Declarative YAML rules: block/allow/approve by tool, model, cost, or regex. Sane defaults on; tighten per agent.
- Approval / HITL Mark a tool
approval_requiredand the run holds durably. Approve via API, CLI, or the Cloud dashboard. The run resumes at exactly that point. - Budget caps Per-run and per-tenant token/cost ceilings. The runtime halts before the cap is crossed. No after-the-fact surprises.
- Receipts Every run emits a signed AgentBoundary receipt with content hashes. Externally verifiable. On by default.
agent = Agent(
model="anthropic/claude-opus-4-8",
tools=[search, send_email, book_flight],
policy="policies/travel.yaml",
budget="$2.00/run",
approval_required=[book_flight],
) rules:
- tool: send_email
action: audit
- tool: book_flight
action: approve
- model: "*"
pii_redaction: true The end-to-end approval loop is shipped: runtime hold, Cloud approval endpoint, and CLI/dashboard. See docs.jamjet.dev.
Any model
One string, any provider.
Pass a provider-routed string as the model. The ADK routes through a governed model seam that enforces policy, logs token usage, and applies PII redaction on every call, regardless of provider.
anthropic/claude-opus-4-8 openai/gpt-4o gemini/gemini-2.0-flash bedrock/meta.llama3-70b ollama/llama3.2 User code never calls a provider directly. The seam is the enforcement point: every call passes the policy middleware, budget check, and audit node before it reaches the wire.
Provider breadth and the governed seam are the first track in the ADK
build, alongside the Agent loop facade.
Reliability
Built for production failures, not just sunny paths.
Model calls are hundreds of milliseconds. Durable turn commits are sub-millisecond. Per-step durability and governance cost essentially nothing against model latency.
Crash recovery
shippedEvery turn commits atomically to a durable event log. On worker death, another worker restores from the last committed turn and continues. O(1) resume from the latest snapshot.
Exactly-once tools
shippedEach tool call gets a deterministic idempotency key from (run_id, segment, step). On resume the runtime skips already-completed side effects. Paying twice after a crash is not a failure mode.
Budget caps and loop detection
shippedPer-run and per-tenant cost ceilings are engine-enforced, not suggestions. Reflection loops are detected and halted before they cross the cap.
Durable waits on provider outage
shippedWhen a model provider returns 429 or goes down, the run parks as a durable wait with backoff rather than failing. It resumes automatically on recovery, freeing the worker in the meantime.
Residency by design
shippedRun state and payloads stay in the region where the agent was dispatched. Only content hashes travel for the global audit index. Residency requirements are a first-class design property, not an afterthought.
Determinism contract
in progressThe boundary between recorded outputs (model responses, tool results, time, randomness) and deterministic orchestration is explicit and tested. Replay-based regression lets you diff a run against a new model or prompt with a deterministic test.
Replay-based regression is in the v1 build.
Languages
Python and Java. First-class.
Python
The primary authoring surface. pip install jamjet.
The Agent, @tool, Team, sessions,
Engram memory bridge, policy, approval, and audit all ship in the
Python SDK.
Java
First-class JVM authoring, at parity with Python. A fluent
Agent.builder(), a @Tool annotation on your
methods, and a Spring Boot starter. Tools run on the same governed
durable engine, executed exactly-once by a Java tool worker.
TypeScript
The @jamjet/cloud SDK gives TypeScript access to the
Cloud APIs and governance checks today. A full TypeScript authoring
surface, and Kotlin, are on the roadmap.
The Java surface, in full
@Tool
String sendEmail(String to, String body)
return mailer.send(to, body); // governed, exactly-once, audited
var agent = Agent.builder("support")
.model("anthropic/claude-sonnet-4-6")
.tools(new SupportTools())
.budget(new Budget(100_000, 2.50))
.approvalRequired(List.of("delete_*"))
.build();
var result = agent.runDurable("Refund order 7785");
The Spring Boot starter (jamjet-agent-spring-boot-starter)
auto-wires the worker: annotate your @Tool @Components, declare the Agent as a
@Bean, and durable governed tool calls run on startup.
Deploy
Local. Self-host. Cloud.
The IR artifact runs identically across all three. Start on SQLite, ship to a cell. No rewriting.
Local
pip install + runSQLite. Zero infrastructure. Your laptop. The same IR runs identically here as in production.
Self-host
Docker + PostgresDocker Compose or Kubernetes. Bring Postgres for the event log and artifact store. You own the infra.
JamJet Cloud
Managed cellsManaged control plane on Fly.io. Policy dashboard, approval inbox, cost analytics, Engram memory, multi-tenant. No infra to run.
One artifact (the IR) runs identically across all three tiers. Develop on SQLite, ship to a cell when you're ready.
Fits your stack
Keep your framework. Add JamJet where it counts.
LangGraph, CrewAI, Spring AI, Claude Code, OpenAI Agents SDK: keep what you have. Drop JamJet at the tool boundary for policy, approval, and audit. No rewrites.
Most kits help you author the loop. Durability, spend caps, approval gates, audit, and PII redaction are mostly left to you. Here is what each ships on by default, not what you could wire up by hand.
| On by default | LangGraph | Google ADK | CrewAI | JamJet |
|---|---|---|---|---|
| Author agents & tools | on by default | on by default | on by default | on by default |
| Durable replay after a crash | built-in but you wire it | built-in but you wire it | built-in but you wire it | on by default |
| Token + $ budget that halts the run | your own code or a separate product | your own code or a separate product | your own code or a separate product | on by default |
| Human approval that survives a crash | built-in but you wire it | built-in but you wire it | built-in but you wire it | on by default |
| Model allowlist / blocked tools | your own code or a separate product | your own code or a separate product | your own code or a separate product | on by default |
| PII redaction at the model seam | built-in but you wire it | your own code or a separate product | your own code or a separate product | on by default |
| Signed, verifiable receipt per run | your own code or a separate product | your own code or a separate product | your own code or a separate product | on by default |
● on by default ◐ built-in, but you wire it (opt-in / not durable / partial) ○ your own code, or a separate product
JamJet isn't another column. It's the row underneath.
How to read this: sources and caveats
- Built-in defaults as of mid-2026: LangChain / LangGraph 1.x, Google ADK 2.3.0, CrewAI OSS 1.15.x. The CrewAI column is the open-source framework, not the paid AMP platform.
- Durable replay: each ships persistence (LangGraph checkpointers, ADK
ResumabilityConfig, CrewAI Flows@persist), but it is opt-in and not auto-resumed, so the default loses in-flight state. JamJet's engine is event-sourced and durable by default. - Approval that survives a crash: each ships a human-in-the-loop primitive (LangGraph
interrupt(), ADKrequire_confirmation(experimental), CrewAIhuman_input). Surviving a restart needs a durable backend you wire (LangGraph), is unsupported on the persistent session backends (ADK), or is Enterprise-only (CrewAI). - Model allowlist: each exposes callback or middleware hooks to write a tool-deny yourself; none ships a declarative model allowlist.
- PII redaction: LangGraph ships a regex redactor at the model boundary; ADK and CrewAI route PII to a separate product (Google Model Armor / DLP, or CrewAI AMP trace redaction after the run).
- Signed receipt: tracing (LangSmith, OpenTelemetry, AgentOps) is not a signed, tamper-evident per-action record; in each, per-action signed audit is an open feature request. JamJet emits a signed AgentBoundary receipt per run.
@jamjet/mcp-shim
Drop governance onto any MCP client (Claude Desktop, Cursor, any MCP host) without touching the client code.
@jamjet/claude-code-hook
PreToolUse hook for Claude Code. Every tool call passes JamJet policy before execution.
@jamjet/openai-guardrail
Guardrail wrapper for the OpenAI Agents SDK. Same policy engine, different host.
jamjet.integrations
Python guardrail for the OpenAI Agents SDK. Already in the jamjet package.
The same policy engine that governs JamJet ADK agents runs as an ext-authz PDP / guardrail webhook for other frameworks. One policy plane across all your agents.
Start building.
Install the SDK, write nine lines, get durable execution and governed tool calls out of the box. Apache 2.0. No account needed to start.
Questions? Join the Discord or start a discussion.