5
Vault
Alex Clarke edited this page 2026-06-18 11:53:45 -06:00

The Coyote vault lets users store sensitive secrets and credentials securely so that there's no plaintext secrets anywhere in your configurations.

It's built on the G-Man library, which supports multiple secrets providers: a local encrypted file, AWS Secrets Manager, Google Cloud Secret Manager, Azure Key Vault, gopass, and 1Password. You pick the one that fits your workflow and Coyote handles the rest.

Vault Demo


Usage

The Coyote vault can be used in one of two ways: via the CLI or via the REPL for interactive usage. The same commands work regardless of which provider you've configured.

CLI Usage

The vault is utilized from the CLI with the following flags:

--add-secret <SECRET_NAME>       Add a secret to the Coyote vault
--get-secret <SECRET_NAME>       Decrypt a secret from the Coyote vault and print the plaintext
--update-secret <SECRET_NAME>    Update an existing secret in the Coyote vault
--delete-secret <SECRET_NAME>    Delete a secret from the Coyote vault
--list-secrets                   List all secrets stored in the Coyote vault

(The above is also documented in coyote --help)

Coyote will guide you through manipulating your secrets to make usage easier.

REPL Usage

The vault can be accessed from within the Coyote REPL using the .vault commands:

Coyote Vault REPL Coyote Vault REPL Commands

The manipulation of your vault is guided in the same way as the CLI usage, ensuring ease of use.

Supported Providers

Coyote supports six secrets providers via G-Man. The default is Local (an encrypted file on this machine), but you can switch to any of the others.

Provider Storage What it needs
local (default) Encrypted file at vault.yml in your Coyote config directory A password file you create on first run
aws_secrets_manager AWS Secrets Manager An authenticated AWS CLI (aws sso login or aws configure)
gcp_secret_manager Google Cloud Secret Manager gcloud auth application-default login
azure_key_vault Azure Key Vault az login
gopass The gopass password manager The gopass CLI installed and initialized
one_password 1Password The op CLI installed and signed in (op signin)

If you're not logged into the relevant CLI when Coyote needs to read a secret, you'll get an auth error with the canonical login command. Coyote does not try to log you in automatically.

Configuration

There are two ways to configure your secrets provider in config.yaml:

Shorthand: vault_password_file

If all you want is the default Local provider, just set the path to a password file:

vault_password_file: ~/.coyote_password

This is shorthand for "use the Local provider with this password file". It's the simplest setup if you don't want to use a dedicated secrets provider external to Coyote.

Explicit: secrets_provider

For any non-Local provider (or if you want to be explicit about your Local setup), use the secrets_provider block:

# Local
secrets_provider:
  type: local
  password_file: ~/.coyote_password

# AWS Secrets Manager
secrets_provider:
  type: aws_secrets_manager
  aws_profile: default
  aws_region: us-east-1

# Google Cloud Secret Manager
secrets_provider:
  type: gcp_secret_manager
  gcp_project_id: my-project-id

# Azure Key Vault
secrets_provider:
  type: azure_key_vault
  vault_name: my-vault-name

# gopass
secrets_provider:
  type: gopass
  store: my-store              # Optional; omit to use the default store

# 1Password
secrets_provider:
  type: one_password
  vault: Production            # Optional; omit to use the default vault
  account: my.1password.com    # Optional; omit to use the default account

When secrets_provider is set, the legacy vault_password_file field is ignored.

⚠️ Important: The secrets_provider block itself cannot use {{SECRET_NAME}} interpolation. Coyote needs to initialize the vault before it can resolve any secrets, so the provider's own configuration must be literal values. All other fields in your config (API keys, MCP server env vars, agent variables, etc.) support {{SECRET_NAME}} references as normal.

First-Run Setup

The first time you start Coyote without a config file, a wizard walks you through picking a secrets provider:

  1. Choose a provider from the menu (Local, AWS, GCP, Azure, gopass, 1Password).
  2. Coyote prompts you for the provider-specific config (AWS profile/region, GCP project ID, Azure vault name, etc.).
  3. For non-Local providers, Coyote performs a round-trip validation: it writes a probe secret to the backend, reads it back, then deletes it. If your credentials don't have the right permissions, or if you're not logged in, Coyote bails out before you fill out the rest of the wizard, with a hint pointing to the correct login command.
  4. For the Local provider, Coyote prompts you to create a password file.

Once the provider is set up, the wizard continues with your LLM/API provider selection and writes your config.yaml.

If you set up Coyote with one provider and later want to switch, just edit your config.yaml to change (or add) the secrets_provider block.

Vault in Sandboxes

If you run Coyote inside a Docker Sandbox, your vault provider determines what (if anything) you need to do to make it usable in the sandbox.

Local provider

Nothing is required. Coyote auto-copies your vault password file into the sandbox at the matching location during coyote --sandbox. Your existing config and encrypted vault.yml come along for the ride. See Sandboxes — Vault Behavior for the exact path-rewriting rules.

If your vault_password_file (or secrets_provider.password_file) is set to a path under your host's home directory (e.g. /home/atusa/.config/coyote/.password, /Users/atusa/... on macOS, or C:\Users\atusa\... on Windows), Coyote inside the sandbox automatically retranslates that path to the corresponding /home/agent/... location at vault initialization time. So your existing config doesn't need to be edited, and a coyote --info inside the sandbox will still show the original path you configured. You'll see an INFO-level log line noting the translation if it happens. This means custom password-file locations work transparently in the sandbox.

Windows-host limitation

On Windows hosts, the password file must live under %USERPROFILE% (i.e. C:\Users\<you>\...). If your configured vault_password_file points anywhere outside the user profile (e.g. C:\Program Files\Coyote\vault.txt), coyote --sandbox will refuse to start with a clear error directing you to move the file. The Linux sandbox has no way to faithfully represent paths under C:\Program Files\ or other Windows-only locations, so the file copy can't proceed.

Linux and macOS hosts have no such restriction. Vault files outside the home directory are copied verbatim into the sandbox at the same absolute path (e.g. /etc/coyote/.password/etc/coyote/.password inside the sandbox).

Non-Local providers (one-time re-authentication needed)

For every other provider, Coyote auto-applies a built-in sbx mixin that installs the corresponding CLI inside the sandbox. The mixin does not log you in! You must re-authenticate once per sandbox lifetime:

Provider First-time sandbox auth
local Nothing (password file auto-copied)
one_password sbx exec <sandbox-name> op signin
azure_key_vault sbx exec <sandbox-name> az login
gopass sbx exec <sandbox-name> gopass clone <your-git-remote> (or gopass setup)
aws_secrets_manager sbx exec <sandbox-name> aws configure sso (or aws sso login --profile <profile>)
gcp_secret_manager sbx exec <sandbox-name> gcloud auth application-default login

Replace <sandbox-name> with whatever you passed to coyote --sandbox <name> (or the basename of your project directory if you used the no-argument form).

From inside the running Coyote REPL (alternative)

When coyote --sandbox is already running and you're at the REPL prompt inside the sandbox, you can run the auth command directly with the !<command> shell pass-through without opening a second terminal:

> !op signin
> !az login
> !gopass clone <your-git-remote>
> !aws configure sso
> !gcloud auth application-default login

The output streams to your REPL, Ctrl-C cancels, and you stay in the conversation. This is usually quicker than exiting Coyote to run sbx exec <sandbox-name> <command> from your host shell. Use sbx exec when you're not already inside the REPL, or when you want to launch an interactive sub-shell to step through a complex login flow.

Things to know

  • Re-auth is per-sandbox, not per-Coyote-launch. Once you authenticate, credentials persist inside the sandbox filesystem until you sbx rm <sandbox-name>. Reopening the sandbox later does not re-prompt.
  • sbx rm <sandbox-name> wipes all cached credentials. The next coyote --sandbox <sandbox-name> creates a fresh sandbox that requires re-auth.
  • The built-in mixin installs the CLI but does not pre-configure it. Users with multiple AWS profiles, Azure subscriptions, GCP projects, or 1Password accounts must run the same aws configure / az account set / gcloud config set / op account add they would on a fresh host.
  • gopass with self-hosted git remotes: the built-in mixin only allows github.com and gitlab.com for cloning your store. If you host the store elsewhere (Bitbucket, self-hosted GitLab, etc.), add the relevant host to your own top-level ~/.config/coyote/sbx-mixin.yaml under network.allowedDomains. Without this, gopass clone will fail with a network error.
  • Manual credential transfer is supported as an alternative. If you'd rather not re-authenticate inside the sandbox, you can sbx cp ~/.aws <sandbox-name>:/home/agent/.aws (or equivalent) before starting Coyote. Coyote intentionally does not do this automatically. Re-auth inside the sandbox keeps host state out of the sandbox by default. The choice is yours.

Motivation

Coyote is intended to be highly configurable and adaptable to many different use cases. This means that users of Coyote should be able to share configurations for agents, tools, roles, etc. with other users or even entire teams.

My objective is to encourage this, and to make it so that users can easily version their configurations using version control. Good VCS hygiene dictates that one never commits secrets or sensitive information to a repository.

Since a number of files and configurations in Coyote may contain sensitive information, the vault exists to solve this problem. How you share secrets across a team depends on your provider:

  • Local: Either share the vault password with the team (one config + one shared password file) or have each user maintain their own password and substitute their own secret values.
  • AWS / GCP / Azure / gopass / 1Password: Each team member uses their own credentials against the shared backend. The vault becomes a natural single source of truth. Rotating a secret in one place propagates to everyone using that config.

Referencing Secrets

Secrets are referenced in Coyote configurations using the same variable templating as the Jinja templating engine:

{{some_variable}}

So whenever you want Coyote to use a secret from the vault, you simply specify the secret name in this format in the applicable file. The same syntax works regardless of which provider stores the secret.

Example: Suppose my vault has a secret called GITHUB_TOKEN in it, and I want to use that in the MCP configuration. Then, I simply replace the expected value in my mcp.json with the templated secret:

{
  "mcpServers": {
    "atlassian": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.atlassian.com/v1/sse"]
    },
    "github": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "{{GITHUB_TOKEN}}"
      }
    }
  }
}

At runtime, Coyote will detect the templated secret and replace it with the decrypted value from the vault before executing.

Supported Files

At the time of writing, the following files support Coyote secret injection:

File Type Description Limitations
config.yaml The main Coyote configuration file Cannot use secret injection on the vault_password_file field or anywhere inside the secrets_provider block
functions/mcp.json The MCP server configuration file
<agent>/tools.<py/sh> Tool files for agents Specific configuration and only supported for Agents, not all global tools (see below)

Note that all paths are relative to the Coyote configuration directory. The directory varies by system, so you can find yours by running

coyote --info | grep config_dir | awk '{print $2}'

Environment Variable Secret Injection in Agents

Secrets from the Coyote vault can be injected into agent tools.sh/tools.py as environment variables. This is done as follows:

  1. Ensure a secret named MY_USERNAME is in your Coyote vault.
  2. Set the name of the secret as the default value for a variable <agent>/config.yaml
    name: Username
    description: An AI agent that demonstrates agent capabilities
    instructions: |
      You are a AI agent designed to demonstrate agent capabilities.
    variables:
      - name: username
        description: Your user name
        # Configure the secret you want to inject using the same templating mentioned above; i.e. wrap the 
        # case-sensitive name in '{{}}'
        default: '{{MY_USERNAME}}'
    
  3. Reference the variable in your <agent>/tools.<py/sh> file using the familiar variable injection name; that is, since the name of the variable is username, the environment variable that will be provided to the tool call will be named LLM_AGENT_VAR_USERNAME tools.sh
    #!/usr/bin/env bash
    # @env LLM_OUTPUT=/dev/stdout The output path
    
    # @cmd Get my username
    get_my_username() {
       echo "$LLM_AGENT_VAR_USERNAME" >> "$LLM_OUTPUT"        
    }
    

For more information about variable usage within agents, refer to the Variables section of the Agents documentation