Skip to content

API proxy rejects BYOK models that don't match configured model routing patterns #2698

@lpcox

Description

@lpcox

Problem

When using BYOK (Bring Your Own Key) with a provider like OpenRouter, the AWF API proxy rejects requests with HTTP 400 if the model name does not match any of the configured apiProxy.models glob patterns. The Copilot CLI reports this as transient_bad_request and retries until all attempts are exhausted.

Reproduction

Workflow configuration:

engine: copilot
engine.env:
  COPILOT_PROVIDER_BASE_URL: https://openrouter.ai/api/v1
  COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
  COPILOT_MODEL: minimax/minimax-m2.5:free

What happens:

  1. The API proxy intercepts the request on port 10002 (Copilot proxy)
  2. The model minimax/minimax-m2.5:free does not match any pattern in apiProxy.models
  3. The proxy returns HTTP 400
  4. Copilot CLI logs: ● Request failed (transient_bad_request). Retrying...
  5. All 4 harness attempts fail with exit code 1
  6. awf-reflect: models fetch returned 400 for http://api-proxy:10002/models

Evidence from logs:

COPILOT_MODEL: minimax/minimax-m2.5:free
COPILOT_PROVIDER_BASE_URL: https://openrouter.ai/api/v1
[health-check] COPILOT_PROVIDER_BASE_URL=http://172.30.0.30:10002 (offline+BYOK mode)

● Request failed (transient_bad_request). Retrying...
● Request failed (transient_bad_request). Retrying...
attempt 1 failed: exitCode=1 isCAPIError400=false

AWF config model patterns (none match minimax/*):

"models": {
  "sonnet": ["copilot/*sonnet*", "anthropic/*sonnet*"],
  "opus": ["copilot/*opus*", "anthropic/*opus*"],
  "haiku": ["copilot/*haiku*", "anthropic/*haiku*"],
  "gpt-5": ["copilot/gpt-5*", "openai/gpt-5*"],
  ...
}

Expected Behavior

BYOK mode should allow arbitrary model names to pass through the API proxy to the configured provider. The proxy should either:

  1. Pass-through unmatched models in BYOK mode — if a model doesn't match any pattern, forward the request to the provider as-is rather than returning 400
  2. Add a wildcard/catch-all pattern — e.g. "byok": ["*"] that matches any model when BYOK is configured
  3. Skip model routing for BYOK — when COPILOT_PROVIDER_BASE_URL is set, disable model-based routing entirely and proxy all requests directly

Impact

This blocks all BYOK use cases with providers/models outside the pre-configured copilot/anthropic/openai/google patterns (e.g., OpenRouter with minimax, mistral, deepseek, etc.).

References

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions