Manual contents

Manage resources as YAML

Once you have more than a few agents, environments and vaults, keep them in YAML under source control and reconcile them with managoat apply. This page covers the manifest format and the secret references that let you commit a manifest with no plaintext in it. The flags themselves are in the CLI guide.

Start from the example

The repository holds the smallest useful manifest, one Environment and one Agent. It needs the CLI, signed in, and an Anthropic credential under Account, then Inference keys. Download it, apply it, and call the agent by name.

curl -fsSLo managoat.yml \
https://raw.githubusercontent.com/managoat/managoat/main/examples/quickstart/managoat.yml
managoat apply -f managoat.yml
managoat run fountain-reader -p \
"Find the code that reclaims an idle sandbox. Explain when it runs and name the files you read."

A checkout already contains the manifest. If you run your own server from the checkout, skip the download. Apply examples/quickstart/managoat.yml from the repository root, so the manifest matches the code you deployed.

apply creates two reusable rows. The Environment says which repository the sandbox receives. The Agent says which runtime and model work in it.

run creates the Conversation. Managoat starts the sandbox, clones the repository, starts Claude, and streams the work and final answer. The command prints the conversation id first. Use it for a follow-up.

managoat conv prompt <conversation-id> -p \
"Now trace the call one level deeper. What stops two reclaimers from racing?"

The follow-up lands on the same sandbox. The checkout and the agent session are still there.

The example has no Vault because it reads a public repository. Add a Vault when a run needs a credential that changes independently from the machine or the Agent. The guided tour adds a GitHub token, changes a repository, and opens a pull request.

The example uses Claude because it is Managoat's most exercised runtime. To use Codex or Gemini CLI, change runtime and model in the manifest and add that provider's inference credential. The runtime catalog lists the accepted shapes.

The format

A manifest is a YAML file of one or more documents. Each document is one resource.

apiVersion: managoat/v1
kind: Environment # or Vault, or Agent
metadata:
name: my-project # the upsert key
spec:
# the fields of that kind, as the API names them

metadata.name is the key for every kind. A resource with that name is updated; with no such resource, apply creates one. The spec fields are the API's fields for the kind; see About environments, About vaults, About agents and the generated reference at /api/docs. An absent spec key leaves that field as it is, and an unknown one is refused for that document.

An example with one of each:

---
apiVersion: managoat/v1
kind: Environment
metadata:
name: my-project
spec:
packages:
apt: [jq, ripgrep]
setup_script: cd /workspace && uv sync
---
apiVersion: managoat/v1
kind: Vault
metadata:
name: alice
spec:
description: Alice's credentials
secrets:
GITHUB_TOKEN: op://Personal/GitHub/token
---
apiVersion: managoat/v1
kind: Agent
metadata:
name: researcher
spec:
runtime: claude
model: anthropic/claude-sonnet-5
environment: my-project # resolved to an environment by name
system: You are a research assistant.
mcp_servers:
everything:
command: npx
args: ["-y", "@modelcontextprotocol/server-everything"]

A file or a directory

managoat apply -f managoat.yml
managoat apply -f ./fountain-specs/

Given a directory, the CLI walks it recursively and reads every .yml and .yaml file, in alphabetical order. A document that does not carry both apiVersion and kind is skipped without a word, so an unrelated YAML file, such as a CI workflow, can share the tree. A document whose kind is not one of the three stops the run before anything is sent.

The file order does not matter. The server reconciles every environment first, then every vault, then every agent, so an agent can name an environment defined later in the file. The name resolves against the manifest first and then against the environments your account already holds. A name that matches neither fails that agent's document, and no other.

What apply prints

One line per resource: + for a create, ~ for an update, = for a resource that already matched, ! for a failure. Inline secrets get a line of their own under their resource.

env + my-project
vault + alice
secret ~ alice/GITHUB_TOKEN
agent = researcher

A failure on one resource goes to stderr and does not stop the others; the CLI exits nonzero at the end. Re-applying the same manifest prints = on every resource, because nothing was written. Inline secrets are the exception: Managoat cannot compare stored ciphertext with the value you gave, so it encrypts them again on each apply and they keep printing ~.

Each create or update writes the same audit event as the matching API call, with the actor and address of the request that ran the apply, and secret writes are marked via: apply. An unchanged resource writes none.

Apply never deletes. A document you remove from the manifest leaves its record in place; delete the record with managoat agent delete, managoat env delete or managoat vault delete, or through the API.

Secret references

Any value under spec.secrets of an Environment or a Vault can be a reference instead of the secret itself. The CLI resolves it on your machine, at apply time, before it sends the manifest. Managoat never sees your secret manager's credentials, only the value it returns.

Reference Resolved from
${VAR} Your shell environment, or --var VAR=value. A flag wins over the environment.
op://<vault>/<item>/<field> 1Password, with op read
bws://<secret-uuid> Bitwarden Secrets Manager, with bws secret get
infisical://<project?>/<env>/<path?>/<name> Infisical, with infisical secrets get
kind: Environment
metadata: { name: my-project }
spec:
secrets:
GITHUB_TOKEN: ${GH_PAT}
POSTHOG_API_KEY: op://Work/PostHog/api_key
NPM_TOKEN: bws://11111111-1111-1111-1111-111111111111
DATABASE_URL: infisical://abc123/prod/api/DATABASE_URL
REDIS_URL: infisical:///prod/REDIS_URL
ANTHROPIC_API_KEY: op://${OP_VAULT}/Anthropic/key
GH_PAT=ghp_... OP_VAULT=Work managoat apply -f managoat.yml
managoat apply -f managoat.yml --var GH_PAT=ghp_... --var OP_VAULT=Work

Substitution runs first and the managers second, so a reference can be built from a variable, as op://${OP_VAULT}/... is above. Write $${VAR} to store a literal ${VAR}, and $$ for a literal $.

Every failure at once

Each phase collects its failures across the whole manifest, and the CLI stops before it sends anything, so one run lists everything to fix.

apply-time substitution failed — set these in the env or pass --var KEY=VAL:
my-project: GH_PAT
apply-time secret resolution failed:
my-project:
POSTHOG_API_KEY (op://Work/PostHog/api_key): [ERROR] ... session expired
NPM_TOKEN (bws://11111111-...): Error: invalid access token

An empty value counts as a failure, because it nearly always means the manager found no secret. If a manager's CLI is not on PATH, the message says where to install it.

Only spec.secrets

Apply-time resolution touches spec.secrets and nothing else. A ${VAR} elsewhere in a manifest, such as in an agent's mcp_servers, goes to the server as written. Managoat resolves that one when a conversation starts, against the merged environment and vault secrets. Read Hop 4. The syntax is the same; the time and the source differ.

Set up each manager

Each manager's own CLI does the authenticating. Install it and sign in before you run managoat apply.

1Password

Install the 1Password CLI. Run op signin for an interactive session; for CI, export a service account token as OP_SERVICE_ACCOUNT_TOKEN.

Segment Is
vault A vault name or ID, such as Work
item An item name or ID, such as PostHog
field A field label or ID, such as api_key

op item get <item> --vault <vault> shows an item's fields. An expired session fails with op's own message; sign in again and re-apply.

Bitwarden Secrets Manager

This is the Secrets Manager CLI, bws, and not the password manager's bw. Install it from the Secrets Manager CLI page. Create a machine account with read access to the secrets you need, and export its access token as BWS_ACCESS_TOKEN.

A reference is the secret's UUID, with no hierarchy. bws secret list shows each secret's id. invalid access token means the token is missing or expired; resource not found means the UUID is wrong or the machine account cannot read it.

Infisical

Install the Infisical CLI. Either run infisical login and infisical init in the directory you apply from, or export INFISICAL_TOKEN for CI.

infisical://<project-id>/<env>/<name>
infisical://<project-id>/<env>/<folder>/<name>
infisical://<project-id>/<env>/<a>/<b>/<name> # folder /a/b
infisical:///<env>/<name> # project from .infisical.json or INFISICAL_PROJECT_ID

The last segment is always the secret's name, and the segments between the environment slug and the name are the folder path. A reference needs at least an environment and a name. Paths are case-sensitive.

Where to go next