Deployment
Ship an agent with agent.deploy(). One IR, three runtimes (local, self-host, cloud). The honest cloud model, the env vars, and what the engine actually stores.
Deployment
A finished agent ships with agent.deploy(). The same compiled IR that
run_durable() builds is registered onto a JamJet engine, so one agent deploys
unchanged to your laptop, your own server, or a hosted engine. The three
runtimes differ only by URL and token. One IR, three URLs.
result = await agent.deploy(runtime="local")
print(f"deployed '{result.workflow_id}' to {result.runtime} ({result.url})")
print(f" scheduled={result.scheduled} cloud_governance={result.cloud_governance}")deploy() registers the workflow on the engine; it does not start an execution
(use run_durable() for that). A Team deploys too: team.deploy() registers
each sub-agent's workflow.
The three runtimes
runtime= | Engine URL | Auth | Notes |
|---|---|---|---|
None / "local" | http://127.0.0.1:7700 | none | the jamjet dev engine; the default |
"self-host" | $JAMJET_RUNTIME_URL | $JAMJET_RUNTIME_TOKEN (optional) | your own engine |
"cloud" | $JAMJET_CLOUD_RUNTIME_URL | $JAMJET_CLOUD_TOKEN or $JAMJET_API_KEY | your hosted engine + Cloud governance |
| a URL string | used directly | none | any engine endpoint |
A bare agent.deploy() with no runtime always targets local, so you never
hit a remote engine by accident. A remote engine is reached only when you pass
its leg name or URL.
await agent.deploy(runtime="self-host")
await agent.deploy(runtime="cloud")
await agent.deploy(runtime="https://my-engine.example.com")A named remote leg with no configured URL raises a clear error rather than falling back to local.
The honest cloud model
runtime="cloud" deploys the same IR to your hosted engine (a URL you run,
for example on Fly) and also turns on JamJet Cloud governance span-push.
JamJet Cloud is the governance and observability plane, not a workflow execution
engine. There is no managed multi-tenant "cell" that runs your workflows for you;
runtime="cloud" is a hosted engine URL plus Cloud governance, and the deploy
client is never pointed at the Cloud API. Cloud governance is never load-bearing:
the deploy succeeds even if Cloud is unreachable.
Cloud is the governance plane, independent of the runtime. See Reliability for exactly what the engine guarantees, and what it does not.
Governance travels with the deploy
The agent's governance (PII redaction, signed audit, receipts, plus any budget or policy you set) is compiled into the IR and ships unchanged. Deploy never strips those knobs. See Governance.
Scheduling
Pass a cron expression to install a recurring schedule so the engine fires the workflow on that cadence:
await agent.deploy(runtime="self-host", schedule="0 9 * * *")Cron requires the SQLite backend and an embedded cron worker on the target engine
(set JAMJET_EMBED_CRON). The recurring intent belongs in the agent's
instructions; a scheduled run is seeded with an empty user turn.
What a self-hosted deployment runs
A durable deployment is three processes:
-
The engine (
jamjet-server) registers IR, drives executions, and owns the state store. -
A tool worker runs your
@toolfunctions. Run one or more dedicated workers against the same engine, pointed at your tool modules:jamjet worker --runtime $JAMJET_RUNTIME_URL --queue python_tool --modules my_toolsSet
JAMJET_EMBED_WORKERSon the engine to run an in-process worker pool instead of dedicated worker processes. -
The model sidecar keeps the engine's model calls on the governed seam. Run it and point the engine at it with
JAMJET_MODEL_SEAM_URL. See Any model.
Locally, jamjet dev runs all three with one command.
Storage backends
The engine has exactly two storage backends, selected by STORAGE_BACKEND:
sqlite(the default) is the durable, single-writer store used for self-host and hosted deployments. The database URL defaults tosqlite://.jamjet/runtime.db; override it withDATABASE_URL.memoryis an ephemeral, per-process backend. State does not survive a restart. Useful for tests and throwaway runs.
There is no Postgres backend in the engine. Cron scheduling requires the SQLite backend.
Engine configuration
The engine is configured by environment variables:
| Variable | Default | Description |
|---|---|---|
STORAGE_BACKEND | sqlite | sqlite (durable) or memory (ephemeral). |
DATABASE_URL | sqlite://.jamjet/runtime.db | SQLite connection string for the durable backend. |
JAMJET_EMBED_WORKERS | (unset) | Run an in-process worker pool inside the engine. |
JAMJET_EMBED_CRON | (unset) | Run the cron scheduler in-process (needs SQLite). |
JAMJET_MODEL_SEAM_URL | (unset) | Route the engine's model calls to the governed sidecar. |
OTEL_EXPORTER_OTLP_ENDPOINT | (unset) | Export traces and metrics over OTLP. |
The deploy client reads its target from JAMJET_RUNTIME_URL /
JAMJET_RUNTIME_TOKEN (self-host) and JAMJET_CLOUD_RUNTIME_URL /
JAMJET_CLOUD_TOKEN or JAMJET_API_KEY (cloud). Model provider keys
(ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY) are read by the model
sidecar.
Health check
curl http://localhost:7700/health