Caldera docs
calderaapp.io

Blueprints, versions and install codes

A blueprint is a prepared agent, like a Dockerfile: a named, versioned bundle of files plus one manifest, caldera.agent.yaml, that says what the files are. One command, caldera init <code>, sets it up on a machine; afterwards Caldera can name a newer version and the agent applies it, checks it and keeps or rolls back.

Existing formats are composed, not replaced. The bundle carries ordinary files (a CLAUDE.md, a .claude/ directory, a .mcp.json, a compose file, your code). The manifest names them and adds only what none of them says: settings, secrets by name, bindings, state, health. The manifest is described field by field on The manifest.

A blueprint says how an agent works, not what it works on. Caldera assigns no work.

The life of a blueprint, in order: write the files and the manifest, zip them (the bundle), upload a version (a draft), publish it (immutable), issue an install code, run caldera init on a machine. Afterwards a desired version moves the agent: update, pin, roll back. The agent applies it, runs its health check and keeps the version or rolls back.

Bundles

A bundle is a zip archive with caldera.agent.yaml at its root. It holds the blueprint's files and nothing else: no secrets, no agent.env.

Limits (Caldera at upload and the runtime at install apply the same numbers):

Limit Value
Archive 20 MB
Entries 5000
Unpacked, in total 100 MB
One file, unpacked 50 MB
Manifest 256 KB

Refused whole, before anything is stored: an archive that is not a zip, is encrypted, spans disks or needs zip64; an entry with an unsafe path, or under .caldera/; a symlink, device, pipe or socket; a name twice; a missing file that the manifest names; a compressed entry that does not unpack to the size its header declares; a manifest that does not validate.

The stored bytes are the uploaded bytes, never a rewrite, so the checksum an agent verifies is the checksum of what was validated.

YAML

Caldera parses the manifest with a full YAML reader (aliases are refused). The runtime reads a subset, and refuses everything else by name: anchors, aliases, tags, multiple documents, complex keys, tabs as indentation, and a plain scalar that continues on the next line. Supported: block mappings and sequences, flow sequences and mappings ([a, b], {k: v}), plain, single and double quoted scalars, > and | block scalars, comments, one leading ---. Write plain block-style YAML. A construct outside the subset could pass the upload and fail at install.

The catalog

Blueprints Caldera ships itself, the same in every workspace, read-only, listed beside a workspace's own.

Name What it is
starter The smallest agent: a loop that writes a heartbeat to data/status.json. Start here to see an agent appear, then replace agent.py. No secrets, no bindings, no settings.
project-agent Works in one repository: clones it, sets it up, runs Claude Code in it at an interval. Settings: repository URL, branch, prompt, minutes between runs, highest cost of a run, model. Optional secrets GIT_TOKEN and ANTHROPIC_API_KEY.
ops-agent An operations agent for a task board: its own scheduler with a daily run limit, a budget per run, a model choice and a board name. Two bindings to the suite's other products (a member that reads and writes, a member that reads). Optional secret ANTHROPIC_API_KEY.

All three are version 1.0.0 today.

  • One version per blueprint: the one this release of Caldera ships. A catalog agent can fetch that version and no other, so a catalog update comes with a release of Caldera, and a local caldera rollback is how a catalog agent goes back.
  • Install it directly, or copy it into the workspace to change it. The copy is an editable blueprint with that version already published.

Workspace blueprints and versions

The life of a version

  • Create a blueprint: a name (^[a-z][a-z0-9-]{0,62}$, unique per workspace) and a description. It has no versions yet.
  • Upload a version: the archive (at most 20 MB). The version number comes from the manifest inside, and the manifest's name must equal the blueprint's name, because desired names a blueprint by name and a version of another blueprint under this one would hand an agent somebody else's code under its own name.
  • A draft can be uploaded again; the new upload replaces it.
  • Publish a version. This is idempotent; the time of the first publish stays. A published version never changes and cannot be deleted: it may be installed, and an agent can roll back to it. A change is a new version.
  • Delete a draft version. Delete a blueprint only while no agent is installed from it (otherwise those agents could never fetch another version).
  • Only published versions can be installed or named as the desired version.

Versions are ordered by semantic version (1.10.0 above 1.9.0; a pre-release below its release).

The version rule in practice

The manifest's version is the version. To release a change you edit the manifest's version, rebuild the bundle, upload, publish. Re-using a version number that is published is refused (version_published). The same applies to versions you uploaded as a test: if 1.0.1 and 1.0.2 exist, the next real version is at least 1.0.3.

Install codes

An admin presses "Install" on a published version (or a catalog blueprint), chooses the agent name and gets a one-time code.

  • Shape: caldera_inst_ plus a long random string. Only a hash is stored. Shown once.
  • Valid once, for 15 minutes, for one installation of one version.
  • The agent name (^[a-z][a-z0-9-]{0,62}$) becomes the agent's name in Caldera and the directory name. It must not be an agent's name in the workspace yet.
  • At issue, Caldera already checks what would fail later, so the dialog says it and not a terminal ten minutes on: the agent name is free, every binding's product is activated for the workspace, a same-named bot does not exist with another role, the issuer may lend the role, and the workspace stays within ten bots.
  • The dialog shows two commands: fetch and verify caldera.pyz, then python3 caldera.pyz init <code> --url <origin>. The warning says the code sets up an agent with a token and a bot token for each product, works once and is shown once.
  • Needs an admin role. Install codes are session-only: no personal token can issue one, because a token that could would be a credential that issues credentials.

Preview, then redeem

Both calls take no token; the code is the credential (the protocol).

  1. Preview reads what the code would install and creates and spends nothing: blueprint, version, description, agent name, runtime, secrets (name, purpose, optional), bindings. The CLI asks for secrets and notices a taken directory before the code is used.
  2. Redeem does it in one transaction: it claims the code (two redemptions racing for one code: exactly one wins), creates the agent and its token, creates or reuses one bot per binding with a token each, and returns the bundle once.

A refusal rolls back all of it, the claim included, so a refused redemption leaves the code usable after the cause is mended:

Status When
403 A bound product is not activated; or the person who issued the code may no longer install agents (it is checked as they stand now); or the workspace is not activated for Caldera.
409 The workspace would hold more than ten bots; a bot of that name exists with another role; the workspace has an agent of that name already.
404 An unknown, expired and used code: all the same answer, on both calls, so a code cannot be probed.
429 More than twenty install calls a minute from one address (preview and redeem together).

An unredeemed code leaves no agent behind, and because the preview comes first, neither does a setup that is aborted at a secrets prompt.

Bindings and bots

A binding gives the agent access to one of the suite's other products without any person's credential on the machine.

At redemption, for each binding Caldera creates (or reuses) one bot in the workspace, with the declared role, and mints a token with the declared scopes, stamped for that product (it works at that product's address and nowhere else). It writes the result into .caldera/agent.env:

Variable Is
CALDERA_BINDING_<PRODUCT>_URL the product's origin
CALDERA_BINDING_<PRODUCT>_WORKSPACE the id of the workspace the bot belongs to (the product's API addresses it by id)
CALDERA_BINDING_<PRODUCT>_TOKEN the bot's token

<PRODUCT> is the upper-cased product id. A blueprint's .mcp.json can refer to these before anything is installed, for example ${CALDERA_BINDING_<PRODUCT>_URL}/mcp with the product id filled in. The runtime does not rewrite that file; it passes the variables in the agent's environment and whatever reads the file resolves them (Claude Code expands ${VAR} in .mcp.json).

Rules:

  • The bot is named <agent name> (<product>) and keeps that name when the agent is renamed.
  • The bot's owner is the person who issued the code. It is capped at their role as it stands at redemption; a bot is a member or guest, never more.
  • An existing bot of that name and role is reused and never changed; one with another role is a 409.
  • A workspace holds at most ten bots; the refusal says how many are needed and held.
  • The product must be activated for the workspace.
  • Binding tokens are valid for a year, the longest a token may be. Nothing renews one. After a year the binding breaks; see Operating agents.
  • A bot is a workspace member, not product content.

Binding health. For each binding the runtime adds a health item Binding <product> to its report (at most once in five minutes), from one request to the product with the bot's token. ok for 200 and for 403 (a token whose scopes do not cover that read still works); bad for 401 (revoked, expired or deleted token) and 404 (the bot is no longer a member); warn when the product cannot be reached. Caldera shows bad as a broken binding on the agent's page. Only the product's own bot settings can mend it. These items never count in the agent's own level, so they cannot roll back an update.

Deleting an agent does not revoke its bots

Revoking is the product's own act. Caldera cannot do it. When an agent is deleted, its bots and their tokens stay. The delete confirmation names the bots so they can be revoked in the product's bot settings. A deleted agent's bot token still works until it expires or is revoked.

Updating, pinning and rolling back

All three are one field: the desired version of the agent. It must be a published version of the agent's own blueprint (a catalog agent: the one shipped version), or empty to withdraw the wish.

You want Name
Update a newer published version
Roll back the previous version
Pin the version it runs (the agent sees nothing to do)
Withdraw the wish nothing

The agent's page ("Blueprint" panel) shows three versions: installed (what the code brought), running (what the agent says it runs now) and wanted (Caldera's wish), the last outcome in the agent's own words, and the broken bindings. The change is followed to the agent's answer: waiting for the next report, then applied, rolled back by the agent, or failed.

The runtime then fetches the bundle with its own token (its own blueprint's published versions only; another blueprint's version and an unknown one answer 404). See the runtime and Operating agents.

Writing your own blueprint, step by step

The example is a private assistant that sorts new mail and writes reply drafts.

  1. Make the agent one long-running process that does its own scheduling and writes a status file. The example has one process, started with python3 -m agent.cli serve, one thread per job, writing data/status.json every 30 seconds and on every change. Pause and resume are then the runtime stopping and starting that process. (An agent that cannot be one process uses an adapter instead.)

  2. Decide what is state. Anything the agent learns or stores must live under a state path, or an update will not keep it. The example keeps its secrets and database outside the blueprint entirely (in the user's own config and state directories) and declares only data/ for its status file.

  3. Write the manifest. The example's is short:

    name: mail-assistant
    version: 1.0.0
    description: >-
      Sorts new mail and writes reply drafts. It never sends. Only numbers go out
      to Caldera, never contents.
    runtime:
      type: process
      command: [python3, -m, agent.cli, serve]
    state: [data/]
    status: data/status.json
    controls: [pause, resume, run_now]
    health:
      command: [python3, -m, agent.cli, health]
      timeout_seconds: 40
    

    It declares no secrets (so init asks for nothing), no settings and no logs (so nothing is asked for and no log ever leaves the machine).

  4. Write the health check so that it needs the new version to have worked. The example's check verifies its configuration and that the programs it calls are in the path, then waits for a heartbeat in the status file that is newer than CALDERA_AGENT_STARTED. A fresh-looking file the old version left behind does not pass.

  5. Build the bundle from a fixed list of files, never "everything except". The example's build script includes code, prompts, templates, schemas, a config example and the manifest; a name that looks like a secret, state or .git stops the build; fixed order, timestamps and modes mean the same files give the same bytes. A bundle never holds secrets or state.

  6. Validate by uploading a draft. Caldera validates the manifest and the archive at upload and stores nothing on a refusal. The refusal names the field (manifest_invalid carries its path) or the rule. A draft can be uploaded again as often as needed; nothing is installable until it is published.

  7. Upload and publish. In the workspace: Blueprints, "New blueprint" (the name must equal the manifest's name), "Upload a version" with the zip, then "Publish".

  8. Issue a code and install on a machine (the runtime).

  9. Prove independence and an update with a forced failure (Connecting an agent). The example's check was: offline pause and resume, an update, and a deliberately broken version whose health command exits 1, rolled back within a second.

  10. Release the next version by raising version in the manifest (never to a number that exists), rebuilding, uploading, publishing, and naming it as the desired version.

Not built

  • Cloud spawning of agents and declared dependencies between blueprints.
  • A marketplace or sharing across workspaces.
  • Third-party credentials held by Caldera: they stay on the machine.
  • A package registry for the runtime.