{"repo": "agentcyberrange/cage", "files": {"config/models.example.yml": {"bf246dda34ef8ffe5481aad66bd90b489377af5d": {"t": 1786068431.711207, "n": 10960, "h": "0892644d64a73f0b", "c": "models:\n # ======================================================================\n # CAGE model registry — example / template\n # ======================================================================\n # Copy this file to `config/models.yml`, then fill in your endpoints:\n #\n # cp config/models.example.yml config/models.yml\n #\n # `config/models.yml` is gitignored — keep real keys there, never here.\n # Secrets are written as `${ENV_VAR}` refs and expanded at load time, so\n # the literal key never lives in any file on disk.\n #\n # Each top-level key below is a model *id* — the name you pass to\n # `--model ` or list under `agents:` in project.yml. An id maps to ONE\n # upstream endpoint; CAGE routes every LLM call through its in-container\n # proxy to that endpoint, translating the wire protocol when the agent and\n # the endpoint disagree.\n #\n # ----------------------------------------------------------------------\n # FIELDS\n # ----------------------------------------------------------------------\n # Required\n # provider Wire-protocol family. Decides how CAGE talks to the endpoint:\n # openai | vllm | sglang -> OpenAI Chat Completions protocol\n # gemini | google -> Google Generative Language API\n # (generateContent; for the\n # gemini_cli agent)\n # anthropic (or any other) -> Anthropic Messages protocol\n # `vllm`/`sglang` additionally mark the endpoint as *self-hosted*\n # — the only kind eligible for `--wait-for-model` startup polling\n # (SaaS providers are assumed always up).\n # model The model string sent upstream, i.e. the provider's own name.\n #\n # Auth — pick the ONE style that fits the endpoint\n # api_key A single key, normally an env ref e.g. ${OPENAI_API_KEY}.\n # This is the common case.\n # api_keys A *pool* of keys for the same endpoint — several accounts /\n # quotas. When non-empty it OVERRIDES api_key, and CAGE rotates\n # across the pool to load-balance concurrent trials. Use this\n # INSTEAD of api_key only when you want to spread load over\n # multiple accounts. (Internally: pool = api_keys if set, else\n # [api_key].)\n # auth_source ONLY for subscription / OAuth agents logged in with an\n # account instead of an API key: Claude Code (Max/Pro) or Codex\n # (\"Sign in with ChatGPT\"). Points at a host directory holding\n # the agent's OAuth credential file (`.credentials.json` for\n # Claude Code, `.codex/auth.json` for Codex), which CAGE\n # bind-mounts into the agent container. In this mode base_url and\n # api_key are left empty. Almost no endpoint needs this — leave\n # it out entirely unless you actually run subscription mode.\n #\n # Optional (have sensible defaults — omit unless you need to override)\n # base_url Endpoint URL. Required for normal API / self-hosted\n # endpoints; empty only in subscription (auth_source) mode.\n # agent_model_names Per-agent override of `model`, for when a specific\n # agent CLI expects a different launch name, e.g.\n # agent_model_names: {claude_code: claude-opus-4-7[1m]}\n # timeout Per-request timeout in seconds. Default: 360.\n # max_retries Upstream retry attempts. Default: 2.\n # input_cost_per_1m USD per 1M input tokens — for cost accounting only.\n # output_cost_per_1m USD per 1M output tokens. (Both unset => not tracked.)\n # extra_headers Extra HTTP headers sent upstream, e.g. {X-Title: cage}.\n # max_context_size The endpoint's REAL context window, in tokens. A model\n # capability (not a per-run knob), so it lives here.\n # Agents whose CLI can be told a window honour it —\n # kimi_code and qwen_code (alias: context_window_size).\n # Omit it and the agent CLI keeps its OWN default; CAGE\n # never invents a number. NOTE: the Claude Code CLI has\n # no knob for a custom window (it infers ~200k from the\n # model id), so claude_code CANNOT honour this — a\n # long-context model still caps ~200k under claude_code.\n # reserved_context_size Tokens of output headroom an agent keeps free below\n # max_context_size before it auto-compacts. kimi_code only.\n # context_window_size Accepted alias for max_context_size (qwen naming).\n # rl_reward_sink RL training integration. Set this to the URL of an\n # external trainer's reward sink to put the model in\n # \"RL mode\": every LLM call it drives carries an\n # `X-Trial-Id` header (so the trainer can group one\n # trajectory's calls), and each finished trial's reward\n # is POSTed here as JSON `{trial_id, reward, success,\n # sample_id, metrics}`. The reward number comes from the\n # benchmark (`Benchmark.reward`, default = its score).\n # Omit ⇒ an ordinary model, behaviour identical. This is\n # the ONLY switch — the whole feature toggles from here.\n # ======================================================================\n\n # --- OpenAI-protocol SaaS, single key --------------------------------\n gpt-5.5:\n provider: openai\n model: gpt-5.5\n base_url: https://api.openai.com/v1\n api_key: ${OPENAI_API_KEY}\n timeout: 3600\n # Cost accounting is optional; set real numbers to track $ per run:\n # input_cost_per_1m: 1.25\n # output_cost_per_1m: 10.0\n\n # --- Multi-account key POOL (use api_keys, not api_key) ---------------\n # CAGE rotates trials across these keys to spread quota/load.\n openai-example:\n provider: openai\n model: gpt-5.5\n base_url: https://api.openai.com/v1\n api_keys:\n - ${OPENAI_API_KEY}\n - ${OPENAI_API_KEY_2}\n\n # --- Self-hosted vLLM (OpenAI protocol, --wait-for-model eligible) ----\n vllm-example:\n provider: vllm\n model: local-model\n base_url: http://127.0.0.1:8000/v1\n api_key: ${VLLM_API_KEY} # self-hosted servers often accept any/empty key\n # Declare the model's real context window so kimi_code / qwen_code size their\n # auto-compaction to it instead of a CLI default. Omit ⇒ the CLI default\n # stands; CAGE will not invent one. (claude_code can't use this — see the\n # FIELDS note above: the Claude Code CLI has no custom-window knob.)\n # max_context_size: 262144\n # reserved_context_size: 20000 # output headroom kept free (kimi_code)\n\n # --- RL training policy (verl etc.) — OpenAI endpoint + reward sink ----\n # The trainer serves the in-training policy as an OpenAI-compatible\n # endpoint; CAGE drives it like any OpenAI model. Adding `rl_reward_sink`\n # is the whole switch: trial ids ride on every call and rewards are\n # reported back. Drop that one line and this is a plain model again.\n rl-policy:\n provider: openai\n model: rl-policy\n base_url: ${RL_ENDPOINT} # trainer's OpenAI-compatible policy server\n api_key: dummy # trainer usually ignores the key\n rl_reward_sink: ${RL_REWARD_SINK} # where per-trial rewards are POSTed\n\n # --- Anthropic SaaS, single key --------------------------------------\n claude-opus:\n provider: anthropic\n model: claude-opus-4-7\n base_url: https://api.anthropic.com\n api_key: ${ANTHROPIC_API_KEY}\n timeout: 3600\n\n # --- Subscription / OAuth (auth_source) — Claude Code & Codex ---------\n # No base_url / api_key: the agent logs in with a subscription account\n # and CAGE bind-mounts the host credentials into the container, keeping\n # the on-disk OAuth token fresh via a host-side refresher for the run.\n claude-opus-sub:\n provider: anthropic\n model: claude-opus-4-7\n agent_model_names:\n claude_code: claude-opus-4-7[1m] # decorated launch name (e.g. [1m] = 1M context)\n auth_source: ${CAGE_CLAUDE_AUTH_SOURCE} # host dir with .credentials.json\n\n # --- Codex \"Sign in with ChatGPT\" (OAuth). Run `codex login` on the host\n # first so ~/.codex/auth.json holds the ChatGPT OAuth tokens; point\n # auth_source at that dir (or the file). No base_url / api_key — the proxy\n # forwards the OAuth Bearer to the ChatGPT Codex backend. Use with\n # `--agent codex`.\n codex-chatgpt:\n provider: openai\n model: gpt-5-codex\n auth_source: ${CAGE_CODEX_AUTH_SOURCE} # host dir with .codex/auth.json (e.g. ~/.codex)\n\n # --- Anthropic-compatible 3rd party (custom base_url + agent name) ----\n deepseek-v4-pro:\n provider: anthropic\n model: deepseek-v4-pro\n agent_model_names:\n claude_code: deepseek-v4-pro[1m]\n base_url: https://api.deepseek.com/anthropic\n api_key: ${DEEPSEEK_API_KEY}\n timeout: 3600\n\n # --- Self-hosted OpenAI-compatible server -----------------------------\n local-openai-compatible:\n provider: openai\n model: local-model\n base_url: http://127.0.0.1:8000/v1\n api_key: ${LOCAL_MODEL_API_KEY}\n timeout: 3600\n\n glm-5.1:\n provider: openai\n model: GLM-5.1\n base_url: https://open.bigmodel.cn/api/paas/v4\n api_key: ${GLM_API_KEY}\n timeout: 3600\n\n qwen3.5-397b-w8a8:\n provider: vllm\n model: qwen3.5-397b-w8a8\n base_url: http://127.0.0.1:8000/v1\n api_key: ${SII_API_KEY}\n timeout: 3600\n\n qwen3.6-max-preview:\n provider: openai\n model: qwen3.6-max-preview\n base_url: https://dashscope.aliyuncs.com/compatible-mode/v1\n api_key: ${QWEN_API_KEY}\n timeout: 3600\n\n qwen3.7-max:\n provider: openai\n model: qwen3.7-max\n base_url: https://dashscope.aliyuncs.com/compatible-mode/v1\n api_key: ${QWEN_API_KEY}\n timeout: 3600\n\n kimi-k2.6-cli:\n provider: openai\n model: kimi-k2.6\n base_url: https://api.moonshot.cn/v1\n api_key: ${KIMI_API_KEY}\n timeout: 3600\n\n # Google Gemini, driven by the `gemini_cli` agent. `provider: gemini` routes\n # the agent's native generateContent traffic through the proxy to Google\n # (the proxy forwards byte-for-byte and records an OpenAI-shaped projection\n # so the inspector parses it). `base_url` is the API origin only — gemini-cli\n # appends the `/v1beta/...` path itself. The key authenticates via the\n # `x-goog-api-key` header.\n gemini-2.5-pro:\n provider: gemini\n model: gemini-2.5-pro\n base_url: https://generativelanguage.googleapis.com\n api_key: ${GEMINI_API_KEY}\n timeout: 3600\n"}}}}