# Docker sbx agent kit for Coyote # # Setup (paths use $HOME so commands work in bash/zsh/PowerShell/Git Bash): # sbx create --kit ./sbx-kit/ coyote --name testing . # sbx cp $HOME/.config/coyote/ testing:/home/agent/.config/ # sbx run testing --kit ./sbx-kit/ schemaVersion: '2' kind: sandbox name: coyote displayName: Coyote description: > The batteries-included runtime for LLMs, featuring Shell Assistant, CLI & REPL mode, RAG, AI tools & agents, MCP servers, skills, and macros. sandbox: image: 'darkalex17/coyote:v0.10.0' entrypoint: ['bash', '-lc', 'exec /home/agent/.cargo/bin/coyote'] permissions: network: allow: # Coyote release + self-update + model-registry sync - 'github.com' - 'api.github.com' - 'raw.githubusercontent.com' - 'objects.githubusercontent.com' - '*.githubusercontent.com' # Package managers and developer tools (cargo, uv, pip — useful at runtime for user installs) - 'crates.io' - 'static.crates.io' - 'pypi.org' - 'files.pythonhosted.org' - 'astral.sh' - 'sh.rustup.rs' - 'static.rust-lang.org' # LLM model OAuth + API endpoints - 'claude.ai' - 'console.anthropic.com' - 'accounts.google.com' # *.googleapis.com covers oauth2 + userinfo + VertexAI regional endpoints # (*-aiplatform.googleapis.com). Do not narrow without re-checking VertexAI. - '*.googleapis.com' # Bedrock and GitHub Models use signed / GitHub-PAT auth that the proxy # cannot rewrite; credentials must be injected separately (see README # "Extending"). NOTE: '*.amazonaws.com' matches exactly ONE label, so # two-label regional Bedrock hosts must be enumerated explicitly # ('**.' is declared but not yet enforced by sbx). Add your region # via a mixin if it's missing below. - '*.amazonaws.com' - 'bedrock-runtime.us-east-1.amazonaws.com' - 'bedrock-runtime.us-east-2.amazonaws.com' - 'bedrock-runtime.us-west-2.amazonaws.com' - 'bedrock-runtime.eu-west-1.amazonaws.com' - 'bedrock-runtime.eu-central-1.amazonaws.com' - 'bedrock-runtime.ap-southeast-2.amazonaws.com' - 'bedrock-runtime.ap-northeast-1.amazonaws.com' - 'models.inference.ai.azure.com' # Proxy-managed LLM provider APIs. Every credentials[].apiKey.inject # domain below MUST also appear here. sbx does not derive allow entries # from inject rules. - 'api.openai.com' - 'api.anthropic.com' - 'generativelanguage.googleapis.com' - 'api.cohere.ai' - 'api.groq.com' - 'openrouter.ai' - 'api.ai21.com' - 'api.cloudflare.com' - 'api.deepinfra.com' - 'api.deepseek.com' - 'api.mistral.ai' - 'api.perplexity.ai' - 'api.voyageai.com' - 'api.x.ai' - 'api.jina.ai' - 'r.jina.ai' - 'qianfan.baidubce.com' - 'api.hunyuan.cloud.tencent.com' - 'api.minimax.chat' - 'api.moonshot.cn' - 'dashscope.aliyuncs.com' - 'open.bigmodel.cn' # Proxy-managed LLM providers: inside the sandbox each apiKey env var holds # the `proxy-managed` sentinel; the proxy injects the real value into the # request header per the inject rules at request time. Values are bound by # the user via credential bindings (`sbx secret set `); Coyote # pre-seeds them from its vault at launch. Multiple domains may map to one # service (e.g. jina) so they share a single credential. credentials: - service: openai description: OpenAI API key, injected on api.openai.com apiKey: name: OPENAI_API_KEY proxyManaged: true inject: - domain: api.openai.com scheme: bearer - service: anthropic description: Anthropic API key, injected as x-api-key on api.anthropic.com apiKey: name: ANTHROPIC_API_KEY proxyManaged: true inject: - domain: api.anthropic.com header: x-api-key format: '%s' - service: gemini description: Google Gemini API key, injected as x-goog-api-key on generativelanguage.googleapis.com apiKey: name: GEMINI_API_KEY proxyManaged: true inject: - domain: generativelanguage.googleapis.com header: x-goog-api-key format: '%s' - service: cohere description: Cohere API key, injected on api.cohere.ai apiKey: name: COHERE_API_KEY proxyManaged: true inject: - domain: api.cohere.ai scheme: bearer - service: groq description: Groq API key, injected on api.groq.com apiKey: name: GROQ_API_KEY proxyManaged: true inject: - domain: api.groq.com scheme: bearer - service: openrouter description: OpenRouter API key, injected on openrouter.ai apiKey: name: OPENROUTER_API_KEY proxyManaged: true inject: - domain: openrouter.ai scheme: bearer - service: ai21 description: AI21 Labs API key, injected on api.ai21.com apiKey: name: AI21_API_KEY proxyManaged: true inject: - domain: api.ai21.com scheme: bearer - service: cloudflare description: Cloudflare Workers AI API key, injected on api.cloudflare.com apiKey: name: CLOUDFLARE_API_KEY proxyManaged: true inject: - domain: api.cloudflare.com scheme: bearer - service: deepinfra description: DeepInfra API key, injected on api.deepinfra.com apiKey: name: DEEPINFRA_API_KEY proxyManaged: true inject: - domain: api.deepinfra.com scheme: bearer - service: deepseek description: DeepSeek API key, injected on api.deepseek.com apiKey: name: DEEPSEEK_API_KEY proxyManaged: true inject: - domain: api.deepseek.com scheme: bearer - service: mistral description: Mistral API key, injected on api.mistral.ai apiKey: name: MISTRAL_API_KEY proxyManaged: true inject: - domain: api.mistral.ai scheme: bearer - service: perplexity description: Perplexity API key, injected on api.perplexity.ai apiKey: name: PERPLEXITY_API_KEY proxyManaged: true inject: - domain: api.perplexity.ai scheme: bearer - service: voyageai description: Voyage AI API key, injected on api.voyageai.com apiKey: name: VOYAGE_API_KEY proxyManaged: true inject: - domain: api.voyageai.com scheme: bearer - service: xai description: xAI (Grok) API key, injected on api.x.ai apiKey: name: XAI_API_KEY proxyManaged: true inject: - domain: api.x.ai scheme: bearer - service: jina description: Jina API key, injected on api.jina.ai and r.jina.ai apiKey: name: JINA_API_KEY proxyManaged: true inject: - domain: api.jina.ai scheme: bearer - domain: r.jina.ai scheme: bearer - service: ernie description: Baidu ERNIE API key, injected on qianfan.baidubce.com apiKey: name: ERNIE_API_KEY proxyManaged: true inject: - domain: qianfan.baidubce.com scheme: bearer - service: hunyuan description: Tencent Hunyuan API key, injected on api.hunyuan.cloud.tencent.com apiKey: name: HUNYUAN_API_KEY proxyManaged: true inject: - domain: api.hunyuan.cloud.tencent.com scheme: bearer - service: minimax description: MiniMax API key, injected on api.minimax.chat apiKey: name: MINIMAX_API_KEY proxyManaged: true inject: - domain: api.minimax.chat scheme: bearer - service: moonshot description: Moonshot AI API key, injected on api.moonshot.cn apiKey: name: MOONSHOT_API_KEY proxyManaged: true inject: - domain: api.moonshot.cn scheme: bearer - service: qianwen description: Alibaba Qianwen (DashScope) API key, injected on dashscope.aliyuncs.com apiKey: name: DASHSCOPE_API_KEY proxyManaged: true inject: - domain: dashscope.aliyuncs.com scheme: bearer - service: zhipuai description: Zhipu AI (GLM) API key, injected on open.bigmodel.cn apiKey: name: ZHIPUAI_API_KEY proxyManaged: true inject: - domain: open.bigmodel.cn scheme: bearer environment: variables: IS_SANDBOX: '1' COYOTE_LOG_LEVEL: INFO COYOTE_CONFIG_DIR: /home/agent/.config/coyote EDITOR: nano # Alias for the gemini credential: v2 apiKey supports a single env name # (GEMINI_API_KEY above). Coyote also recognizes GOOGLE_API_KEY, so keep # it set to the sentinel. Header injection happens per-domain regardless # of which env var the app reads. GOOGLE_API_KEY: proxy-managed setup: files: - path: /home/agent/.config/git/ssh-signing-key-command mode: '0755' description: Resolve the forwarded SSH agent key for Git SSH signing content: | #!/bin/sh set -e if [ -z "$SSH_AUTH_SOCK" ]; then echo "WARNING: [git-ssh-sign] no SSH agent - cannot sign commits" >&2 fi key=$(ssh-add -L 2>/dev/null | head -n 1) if [ -z "$key" ]; then echo "WARNING: [git-ssh-sign] no keys in SSH agent - cannot sign commits" >&2 fi config_dir="$GIT_SSH_SIGN_CONFIG_DIR" if [ -z "$config_dir" ]; then config_dir="/home/agent/.config/git" fi mkdir -p "$config_dir" email=$(git config user.email 2>/dev/null || printf '%s' "agent@sandbox.local") printf '%s %s\n' "$email" "$key" > "$config_dir/allowed_signers" printf 'key::%s\n' "$key" install: - command: | git config --system gpg.format ssh git config --system --unset-all user.signingKey || true git config --system commit.gpgSign true git config --system tag.gpgSign true git config --system gpg.ssh.defaultKeyCommand /home/agent/.config/git/ssh-signing-key-command git config --system gpg.ssh.allowedSignersFile /home/agent/.config/git/allowed_signers if [ "$(git config --system --get core.hooksPath || true)" = "/home/agent/.config/git/hooks" ]; then git config --system --unset-all core.hooksPath fi user: '0' description: Configure SSH commit signing with a dynamic key command startup: - command: [ 'sh', '-c', 'test -f "$HOME/.config/coyote/config.yaml" || coyote --info >/dev/null 2>&1 || true', ] user: '1000' background: false description: Bootstrap Coyote config directory on first sandbox start agentInstructions: filename: COYOTE.md content: | ## Sandbox environment You are running inside a Docker sandbox launched via `sbx run coyote`. The user's project workspace is mounted at its absolute host path and is the current working directory. `sudo` is passwordless; use it for system package installs. Coyote's configuration lives at `~/.config/coyote/` and logs at `~/.cache/coyote/coyote.log`. Persistence is enabled, so config, sessions, vault state, OAuth tokens, and installed tools survive sandbox restarts. LLM provider credentials are forwarded by the sandbox HTTP proxy via credential bindings. Coyote pre-seeds them from its vault at launch (`sbx secret set `); users can also bind values manually on the host with `sbx secret set ` or `sbx secret import`. Recognized services: openai, anthropic, gemini, cohere, groq, openrouter, ai21, cloudflare, deepinfra, deepseek, mistral, perplexity, voyageai, xai, jina, ernie, hunyuan, minimax, moonshot, qianwen, zhipuai Inside the sandbox the corresponding env vars (OPENAI_API_KEY, etc.) hold the placeholder string `proxy-managed`; the proxy substitutes the real value at request time. OAuth flows for Claude Pro/Max and Gemini are also allow-listed. Bedrock (AWS) and VertexAI (Google Cloud) use signed/OAuth-token requests that the proxy cannot rewrite, so you must inject credentials yourself via `sbx run --env AWS_ACCESS_KEY_ID=...` or a mixin kit that mounts a service-account JSON. VertexAI regional endpoints are allow-listed via `*.googleapis.com`. Bedrock runtime endpoints are allow-listed for us-east-1/2, us-west-2, eu-west-1, eu-central-1, ap-southeast-2, and ap-northeast-1 only; other regions need a mixin allow entry (`bedrock-runtime..amazonaws.com`). Useful first-run commands: - `coyote --info` # show config paths and resolved settings - `coyote --list-secrets` # initialise the local vault - `coyote --authenticate ` # OAuth flow (Claude Pro/Max, Gemini)