Files
coyote/assets/sbx-kit/spec.yaml
T
Dark-Alex-17 91dbaf5533
CI / All (ubuntu-latest) (push) Failing after 25s
CI / All (macos-latest) (push) Has been cancelled
CI / All (windows-latest) (push) Has been cancelled
feat: upgraded to sbx kit v2 spec for improved integration
2026-08-10 15:26:16 -06:00

373 lines
13 KiB
YAML

# 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: >
An all-in-one, batteries-included LLM CLI tool featuring Shell Assistant,
CLI & REPL mode, RAG, AI tools & agents, MCP servers, skills, and macros.
sandbox:
image: 'darkalex17/coyote:v0.8.3'
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 <service>`); 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 <service>`); users can also bind values manually on the
host with `sbx secret set <service>` 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.<region>.amazonaws.com`).
Useful first-run commands:
- `coyote --info` # show config paths and resolved settings
- `coyote --list-secrets` # initialise the local vault
- `coyote --authenticate <client>` # OAuth flow (Claude Pro/Max, Gemini)