# --- Required: exactly one LLM provider key --- # # Uncomment ONE of the options below. Leave the others commented out: any # non-empty ANTHROPIC_API_KEY — including a leftover placeholder — makes # SWE-AF pick the claude_code runtime, which is exactly what you don't want # on an OpenRouter-only deployment. # Option A (recommended): OpenRouter — 200+ open and proprietary models # (DeepSeek, Qwen, Llama, MiniMax, GLM, Kimi, …). This is the only secret # needed to get started; GH_TOKEN below is optional. # With ONLY an OpenRouter key set (no ANTHROPIC_API_KEY, no SWE_DEFAULT_RUNTIME), # SWE-AF auto-selects the open_code runtime and defaults every role to # openrouter/deepseek/deepseek-v4-flash. Override with SWE_DEFAULT_MODEL. # OPENROUTER_API_KEY=sk-or-v1-... # Option B: Anthropic API key — used by claude-agent-sdk for all coding agents # ANTHROPIC_API_KEY=sk-ant-api03-... # Option C: Claude Code subscription OAuth token (run `claude setup-token` to get it) # Uses your Pro/Max subscription credits instead of API billing # CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-... # --- Optional: additional providers --- # OpenAI API-platform billing for OpenAI models and Codex api_key mode. # OPENAI_API_KEY=sk-... # Codex CLI runtime auth. Values: # auto Use OPENAI_API_KEY when set; otherwise use local Codex login. # chatgpt Use ChatGPT Free/Plus/Pro/Team login. Run `codex login` on the # host, keep OPENAI_API_KEY unset for this process, and Docker will # mount ~/.codex into both swe-planner and swe-fast. # api_key Use OpenAI API-platform billing. Set OPENAI_API_KEY=sk-... # SWE_CODEX_AUTH_MODE=auto # Google Gemini # GOOGLE_API_KEY=... # Z.AI / Zhipu AI (GLM-4.7, GLM-4.5, etc.) — direct access without OpenRouter # Get your key at https://z.ai/manage-apikey/apikey-list # ZHIPU_API_KEY=... # Note: Can reuse ANTHROPIC_API_KEY from above for Claude models via OpenCode # --- Optional: Go node direct-LLM path (QA synthesizer) --- # # The Go port's run_qa_synthesizer reasoner uses the AgentField Go SDK's direct # LLM client (ai.DefaultConfig) instead of the coding harness. That client reads # these env vars; when none supplies a key, the LLM branch is disabled and the # synthesizer falls back to a deterministic decision (so the node still runs). # OPENAI_API_KEY / OPENROUTER_API_KEY (shared with the runtime keys above) — # an OpenRouter key routes to https://openrouter.ai/api/v1, and the short # model aliases below are mapped to anthropic/claude-*-4.5 / -4.1 ids. # AI_BASE_URL points the client at an OpenAI-compatible endpoint # (default https://api.openai.com/v1; OpenRouter is auto-selected from the key). # AI_BASE_URL=https://openrouter.ai/api/v1 # AI_MODEL overrides the default model for the direct-LLM path (default gpt-4o). # The coding loop passes the qa_synthesizer role model (default "haiku"), which # WithModel overrides per call, so AI_MODEL is only the fallback default. # WARNING: AI_MODEL is ALSO the second step of the role-model cascade # (SWE_DEFAULT_MODEL → AI_MODEL → HARNESS_MODEL), so setting it here # repoints every agent role too. To pick a model for the roles, set # SWE_DEFAULT_MODEL instead and leave this one unset. # AI_MODEL=anthropic/claude-haiku-4.5 # --- Optional: Web search (open runtime) --- # # Enables opencode's built-in `websearch` and `webfetch` tools so coding # and review agents can look up external documentation, library APIs, # error messages, and version/deprecation status during a build. # # Both vars must be set. They reach the opencode subprocess via the # parent-env propagation in agentfield's run_cli — no SWE-AF wiring is # needed beyond setting them on the deployment. # # Get an Exa key at https://exa.ai/ # OPENCODE_ENABLE_EXA=1 # EXA_API_KEY=... # --- Optional: GitHub integration --- # GitHub personal access token (repo scope) — for draft PR creation # Optional: builds on local and public repos run without it. Needed to clone # private repos, push branches, and open pull requests. Leave commented out # unless you have a real token — a placeholder value is worse than none, # because git and gh will try to authenticate with it and fail. # GH_TOKEN=ghp_... # --- Optional: Build-time test database --- # An ephemeral Postgres (the `build-db` service in docker-compose.yml) is wired # in by default so target-repo integration tests that *force* a database — e.g. # `REQUIRE_TEST_DB=1 npm run test:integration` — can connect instead of failing # with pg-pool ECONNREFUSED and cascading the build. It ships empty; the target # repo's own integration global-setup migrates it, so the factory stays # repo-agnostic. Override the default DSN or the build-db credentials here: # DATABASE_URL_TEST=postgres://builder:builder@build-db:5432/buildtest # BUILD_DB_USER=builder # BUILD_DB_PASSWORD=builder # BUILD_DB_NAME=buildtest # --- Optional: AgentField server --- # Override the control plane URL (default: http://control-plane:8080 in Docker, # http://localhost:8080 when running bare metal) # Set this to use an already-running control plane instead of Docker's: # AGENTFIELD_SERVER=http://host.docker.internal:8080 # AGENTFIELD_SERVER=http://localhost:8080 # Public URL the control plane uses to call this node back. REQUIRED for any # containerized/remote deploy where the node's listen address isn't directly # reachable by the control plane (k8s, Railway, custom containers) — without # it, calls fail with 504 agent_unreachable. The bundled compose files set it # per service; bare-metal localhost runs don't need it. # AGENT_CALLBACK_URL=http://swe-agent:8003 # Node ID for this agent (default: swe-planner) # NODE_ID=swe-planner # Port the agent listens on (default: 8003) # PORT=8003 # --- Optional: Model configuration --- # Default runtime when callers don't pass a `runtime` in the request config. # Lets the deployer pick the runtime once instead of every caller threading # a config through. Unset = auto: open_code when an OpenRouter key is the # only provider credential, else claude_code. An invalid value is logged as # a warning and ignored. Leave this UNSET on an OpenRouter-only deployment — # auto-select already picks open_code and the deepseek-v4-flash default. # SWE_DEFAULT_RUNTIME=claude_code # or: open_code, codex # Default model when callers don't pass `models` in the request config. # Applies to all 16 agent roles for whichever runtime is active. Caller # config (`models.default` or per-role keys) overrides this. Set this on # the deployment to pin a model without code changes — e.g. swap from # deepseek-v4-flash to a newer release. Empty / unset → use the runtime's # baked-in defaults (openrouter/deepseek/deepseek-v4-flash on open_code). # This is the variable to use for role model selection; AI_MODEL below is # part of the same cascade but is also the direct-LLM fallback, so prefer # this one. # SWE_DEFAULT_MODEL=openrouter/deepseek/deepseek-v4-flash # Per-tier models. Each of the 17 agent roles belongs to one of three tiers: # high = planning-heavy reasoning (pm, architect, tech_lead, replan) # med = coding / review / QA (coder, qa, code_reviewer, sprint_planner, # retry_advisor, issue_writer, issue_advisor, verifier, merger, # integration_tester, ci_fixer) # low = mechanical transformation (qa_synthesizer, git) # Set any subset; a tier var applies to every role in its tier. Precedence: # beats SWE_DEFAULT_MODEL / AI_MODEL / HARNESS_MODEL, loses to caller config # (`models.default` and `models.`). SWE_MODEL_HIGH also becomes the # default for the standalone `plan` pipeline (its reasoners are high-tier). # A model id may carry an optional "#variant" reasoning-effort suffix # (e.g. openrouter/z-ai/glm-5.2#high), passed through to opencode (--variant) # and codex (model_reasoning_effort). # SWE_MODEL_HIGH=openrouter/z-ai/glm-5.2 # SWE_MODEL_MED=openrouter/deepseek/deepseek-v4-pro # SWE_MODEL_LOW=openrouter/deepseek/deepseek-v4-flash # Runtime/model selection is configured via API request config (V2): # { # "runtime": "claude_code" | "open_code" | "codex", # "models": { # "default": "sonnet or provider/model-id", # "coder": "provider/model-id", # "qa": "provider/model-id" # } # } # # Runtime mapping: # claude_code -> Claude backend # open_code -> OpenCode backend # codex -> OpenAI Codex CLI backend # # Legacy keys are removed: ai_provider, preset, model, and all *_model fields. # # Example open runtime request config: # {"runtime": "open_code", "models": {"default": "deepseek/deepseek-chat"}} # # Example Claude runtime request config: # {"runtime": "claude_code", "models": {"default": "sonnet", "coder": "opus"}} # # Example Codex runtime request config: # {"runtime": "codex", "models": {"default": "gpt-5.3-codex"}} # Available open runtime model IDs (format: provider/model-name): # openrouter/deepseek/deepseek-v4-flash # the open_code default # deepseek/deepseek-chat # DeepSeek via OpenRouter # minimax/minimax-m2.5 # MiniMax M2.5 via OpenRouter # qwen/qwen-2.5-72b-instruct # Qwen via OpenRouter # openai/gpt-4o # GPT-4 via OpenAI # anthropic/claude-sonnet-4 # Claude via Anthropic # zhipuai-coding-plan/glm-4.7 # GLM-4.7 via Z.AI direct (set ZHIPU_API_KEY) # openrouter/z-ai/glm-5 # GLM-5 via OpenRouter (set OPENROUTER_API_KEY) # --- High-performance coding engine, beta (Go node) --- # # The Go node ships prebuilt coding engines — one per supported platform, at # go/bin/swe-pro-darwin-arm64 and go/bin/swe-pro-linux-amd64 — that take over # per-issue coding work: the engine registers as its own node on the control # plane and builds route their coding through it. # # Whether it runs depends on how the node was started: # * `af install` / AgentField Desktop — ON for you already (the manifest # defaults SWE_PRO_ENGINE to 1). Set it to 0 for the classic coding loop. # * this file's audience (a clone, a fork, the compose stacks, a bare # binary) — OFF. Uncomment the line below to opt in. # If the binary is missing, the node logs a warning and keeps using the # classic loop. # SWE_PRO_ENGINE=1 # Engine sidecar identity and reachability. In containers, set the public URL # so the control plane can reach the engine's callback (mirrors # AGENT_CALLBACK_URL on the SWE-AF nodes); the engine otherwise advertises # http://localhost:8801, which a control-plane container cannot reach. # SWE_PRO_NODE_ID=swe-pro # SWE_PRO_PORT=8801 # SWE_PRO_PUBLIC_URL=http://swe-agent-go:8801 # Only needed to point at an engine build outside the shipped layout: the node # already finds /usr/local/bin/swe-pro (Docker) or the swe-pro-- # binary next to itself (an `af install` checkout). # SWE_PRO_BIN=/usr/local/bin/swe-pro # Engine model pools and reasoning effort. Unset keeps the engine's own # defaults (all OpenRouter ids, so an OpenRouter key is all it needs). # SWE_PRO_MODELS_HIGH=openrouter/deepseek/deepseek-v4-pro # SWE_PRO_MODELS_LOW=openrouter/deepseek/deepseek-v4-flash # SWE_PRO_VARIANT=low # Per-run USD ceiling. Unset = no per-run cap; set this on shared or # unattended deployments so a wide issue DAG cannot run away. # SWE_PRO_MAX_COST=5