Quickstart
A sandboxed agent, step by step.
What Constle does, step by step, with its output, abridged.
-
01
The CLI
The current source and its signed releases aren’t public yet.
The steps below show Constle’s commands with their output, abridged.
By signing up you agree to get release news by email. Privacy
-
02
Check the example Agentfile
Nothing runs yet.
constle validateoutput, abridged
$ constle validate examples/basic-agent/agent.yaml ✓ examples/basic-agent/agent.yaml is valid name: basic-agent version: 0.1.0 isolation: network (inferred from capabilities) image: basic-agent:latest memory: 512MB time limit: none allowed: api.groq.com credentials: GROQ_API_KEY, AGENT_TASK ⚠️ warning: spending limits are declared but NOT enforced: no mcp.servers entry declares a pricing block, so there is nothing to meter. cost is measured only at the MCP gate proxy (constle does not TLS-intercept generic allowed_hosts traffic); declare pricing on the MCP servers that cost money. ⚠️ warning: some declared credentials are not available on this machine: GROQ_API_KEY (not set on the host), AGENT_TASK (not set on the host) `constle run` will refuse to start until each one resolves — export the variable, or point credentials[].secret_ref at the one that holds itThe spending warning is the design working. A declared cap with nothing metering it is called out loudly instead of quietly looking real.
-
03
Create the agent’s identity
$ constle identity create basic-agent --owner=you@example.comPaste the printed
did:key:…into the manifest underidentity.did. Only the public DID goes there, while the private key stays in~/.constle/identities/and never enters the sandbox. Withidentity.didset, every audit entry is signed, andconstle runfails closed, so without a matching private key on this machine the run refuses to start. -
04
Build the image and run it
$ docker build -t basic-agent:latest examples/basic-agent $ export GROQ_API_KEY=gsk_... $ export AGENT_TASK="What is 2+2?" $ constle run examples/basic-agent/agent.yamlWhere’s--env?There isn’t one. An agent receives exactly the host variables its manifest names under
credentials:(the example namesGROQ_API_KEYandAGENT_TASK), and nothing else from your environment. Only the variable name goes in the manifest. The value stays in your shell and is never written to the image, the manifest or the audit log. Declare nothing, and no host variable crosses in. -
05
Verify the audit log
$ constle audit verify ~/.constle/logs/basic-agent-$(date -u +%F).jsonlUnpinned, it reports that the signatures are valid under the log’s own key, which was not pinned. Edit a single byte of that file and run it again, and it names the line that was changed. Pin the key with
--agentfile=examples/basic-agent/agent.yaml(or--did=) and a clean log reports✓ audit log verified. -
06
Gate a tool call
Name an MCP tool, and its calls that pass through the gate wait for a person’s yes. By default, no answer in five minutes means the call is refused and the run stops.
$ constle webhook-keygen approveragent.yamlthe gate
human_gates: enabled: true require_approval_for: - pay_invoice # exact MCP tool name approver_pubkey: did:key:z6Mk… # required when gating notify: - channel: webhook url_secret_ref: HUMAN_GATE_WEBHOOK_URL on_timeout: abort # default; stop, never proceedAt run time the call waits for whichever answers first, the terminal prompt or a signed decision from your endpoint.
07Reference
The constle commands.
constle [--no-animation] | Startup screen and command overview |
constle init | Write a starter Agentfile (agent.yaml) in the current directory |
constle run [--backend=docker|firecracker] [--accept-isolation=<level>] <agentfile> | Run an agent in an isolated sandbox. --accept-isolation (none, process, network) knowingly runs below the declared level, and is recorded. |
constle validate <agentfile> | Validate without running. It prints the resolved isolation, and warns when declared gates or spend caps won’t be enforced and when the declared identity or credentials aren’t available here, and names each field you wrote that it accepts but does not enforce, and each A2A peer reached over plain http |
constle ps | List running and recent Constle-managed agents |
constle stop <run-id> | Stop a running agent by run ID |
constle identity create <name> [--owner=<email>] | Generate an agent DID (Ed25519 keypair) |
constle identity show <name> | Show an agent’s DID and key location |
constle webhook-keygen <name> | Generate a human-gates approver keypair (did:key) for approver_pubkey |
constle audit verify [--agentfile=<path>] [--did=…] [--approver-pubkey=…] <logfile> | Verify signatures and the hash chain, and re-verify recorded gate decisions. --agentfile takes both pins from the Agentfile. |
constle version | Print the version |
CONSTLE_ANIMATION | auto (default), never, always. The intro is always skipped for non-interactive output, NO_COLOR, TERM=dumb or terminals under 80×24. |
url_secret_ref target | The host variable you name (for example HUMAN_GATE_WEBHOOK_URL) holds the webhook URL, so it never sits in the Agentfile. |
credentials names | The only host variables passed into the sandbox, by name. |
Next: your own Agentfile
$ constle init
Field reference ↗constle initwrites a starteragent.yamlwith the imagepython:3.12-alpineand a one-line command.The full quickstart
Every step, plus gating a tool call end to end, in the documentation.
Quickstart in the docs ↗Read the limits first
The known limitations, each traced to the code that makes it so.
Where each rule stops ↗