374 lines
13 KiB
YAML
374 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 runtime 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)
|