constle docs constle docs pre-1.0

Agentfile in 5 minutes

An Agentfile is one YAML file that says what an agent may reach, call, spend and receive. Constle reads it once, when the run starts, and enforces it from outside the agent.

On this page

Source release coming soon

The source and installers are not public yet, so there is nothing to install today. This guide documents Constle as it behaves now. More in Project status.

What you'll getLink to this section

  • A minimal Agentfile that validates, for an agent that calls one model API.
  • The sections most agents need, and the part of the runtime that enforces each one.
  • The mistakes that make a control look real when it isn't, and what constle validate says about each.

The policy is data, not code: there is no rule language, and every field the runtime reads is listed in the Field reference with one of four labels, ENFORCED, VALIDATED, DECLARED or INFORMATIONAL. A DECLARED field parses and changes nothing. More in The Agentfile.

1. Scaffold a fileLink to this section

constle init writes agent.yaml in the current directory, with a comment on every field. The file it writes passes constle validate as it stands, so you start from something valid and change it.

shell
constle init
constle validate agent.yaml

Keys are checked strictly: a key the schema does not define is an error, not a silent no-op, and the message names the keys that section accepts and the nearest match. A typo such as capabilties fails validation instead of quietly turning a control off.

2. Name the agent and its imageLink to this section

yaml
identity:
  name: report-writer          # lowercase letters, digits, hyphens; names the audit log
  version: "1.0.0"

sandbox:
  image: report-writer:1.0.0   # pin a digest or an immutable tag
  memory_mb: 512               # the default; exceeding it kills the workload

The agent is an ordinary container image. sandbox.command overrides the image's own command, in exec form (a list of arguments, no shell interpolation). The audit log is named after identity.name, in ~/.constle/logs/<name>-<YYYY-MM-DD>.jsonl.

3. Write the network policyLink to this section

yaml
sandbox:
  network:
    allowed_hosts:
      - api.groq.com           # the only host on the internet this agent can reach

allowed_hosts is the entire network policy. An empty or absent list reaches no host at all; only Constle's own MCP and A2A gates stay reachable. Entries are plain lowercase hostnames, with one optional leading . to include subdomains. A scheme, port, path or wildcard is rejected at validate time.

sandbox.network.egress parses and is ignored (limitation 5). How the proxy enforces the list, and what it refuses besides undeclared names: Stop an AI agent exfiltrating data.

4. Declare what crosses from your shellLink to this section

yaml
credentials:
  - name: GROQ_API_KEY         # the value stays in your shell; only the name is here
  - name: AGENT_TASK           # non-secret input crosses the same way

This list is complete and exclusive for host environment variables: the sandbox receives these and no other variable from your environment. Declare nothing and the agent receives nothing. secret_ref reads the value from a differently named host variable, so two agents can both see GROQ_API_KEY with different values. Names that Constle sets itself (anything starting CONSTLE_, and the proxy variables) are refused.

Declared values do enter the sandbox, as environment variables the agent can read. That is the price of not intercepting the agent's TLS (What Constle is not).

5. Set the isolation floorLink to this section

yaml
capabilities:
  - external_api               # outbound API calls: network isolation at least

capabilities is a list of action classes, and its one enforced job is the isolation floor: read_file and write_file need process, web_search, external_api and send_email need network, and spawn_subagent, external_transfer and delete_records need kernel (a Firecracker microVM). Leave sandbox.isolation out and the runtime uses the floor; write it and it may only be stronger. It is not a permission system: nothing is blocked at run time because it is missing from this list. Backends and levels: Architecture.

6. Bound the runLink to this section

yaml
limits:
  max_duration_seconds: 300    # the supervisor kills the agent at five minutes

The timer runs in the host process, not in the agent. When it fires, the run is stopped and the audit log records terminated_by_limit. Omitted or 0 means no limit.

7. Validate, and read every warningLink to this section

shell
constle validate agent.yaml

Validation runs nothing. It prints the isolation level it resolved (and whether it was declared or inferred), and it warns about each control that is declared but will not be enforced. The whole file so far:

agent.yamlyaml
apiVersion: constle.dev/v1alpha1
kind: AgentManifest

identity:
  name: report-writer
  version: "1.0.0"

sandbox:
  image: report-writer:1.0.0
  memory_mb: 512
  network:
    allowed_hosts:
      - api.groq.com

capabilities:
  - external_api

credentials:
  - name: GROQ_API_KEY
  - name: AGENT_TASK

limits:
  max_duration_seconds: 300

On a machine where GROQ_API_KEY and AGENT_TASK are not exported, validate warns that they are unavailable and constle run refuses to start until they are. The quickstart shows that output for an agent very like this one.

Mistakes that look like controlsLink to this section

You wrote What actually happens What validate and run do
egress: none Parsed and ignored; allowed_hosts decides Nothing: it is limitation 5
require_approval_for without enabled: true Nothing is gated Warn: human_gates.enabled is false — NO gate is enforced
A gate entry that provably matches no tool of a declared MCP server That entry gates nothing Warn, naming the entries that run without approval
max_per_run_usd with no priced MCP server Nothing is metered, so nothing is capped Warn: spending limits are declared but NOT enforced
max_per_month_usd Parsed, never enforced Warn: spending.max_per_month_usd is NOT enforced.
max_per_run_usd: "0" Rejected as ambiguous Validation error: omit the field to leave a cap unset
isolation: network beside external_transfer Weaker than the floor Validation error naming the capability
identity.did with no key on this machine No signing key validate warns; run refuses to start

Where to go nextLink to this section

FAQLink to this section

Is the Agentfile read again while the agent runs?Link to this section

No. The runtime reads it once, before the sandbox starts, and nothing inside the sandbox can change it. To change the policy, stop the run, edit the file and start a new run.

Does a field I leave out default to something permissive?Link to this section

The network defaults to nothing: no allowed_hosts means no host. No credentials means no host variables. Human gates default to off, spending caps to unset and max_duration_seconds to no limit, so write the ones you want.

Can I validate an Agentfile in CI without the keys?Link to this section

Yes. constle validate warns about credentials and identities that are not available on the machine, and does not fail on them, because validation is not execution. constle run is where they are required.