You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue was opened by GitHub Copilot CLI, acting on behalf of @lecoursen. The investigation and artifact analysis below were done by the agent.
Summary
models.default-ai-credits-pricing is documented as the escape hatch for models that are missing from AWF's built-in pricing table. It does not work. gh-aw compiles it into awf-config.json correctly, but AWF drops it during config resolution and never sets AWF_DEFAULT_AI_CREDITS_PRICING on the API proxy container, so the guard never sees a fallback and rejects every request with HTTP 400.
This makes the documented remedy for unknown_model_ai_credits a no-op.
Versions
gh-aw v0.83.4
AWF v0.27.42 (both the installed binary and the pinned container images)
Engine: copilot, model resolved to claude-opus-5
Symptom
400 Model "claude-opus-5" has no AI credits pricing and no default pricing is configured.
Set apiProxy.defaultAiCreditsPricing in the AWF config (e.g. {"input": 3.0, "output": 15.0})
to provide a fallback rate, or add the model to ...
All four copilot-harness attempts fail identically, so it is deterministic rather than transient.
Compile with gh-aw v0.83.4 and run. The opus alias resolves to claude-opus-5, which has no catalog pricing, and the run fails despite the fallback being configured.
Evidence from the run artifacts
1. gh-aw compiles the field correctly.agent/awf-config.json:
2. AWF does not propagate it to the container. In sandbox/firewall/audit/docker-compose.redacted.yml, every sibling apiProxy.* field arrives as an env var on the api-proxy service:
3. The resolved config confirms the drop.sandbox/firewall/audit/awf-resolved-config.json has top-level keys including maxAiCredits, maxCacheMisses, maxRuns, modelAliases, and rateLimitConfig, but no defaultAiCreditsPricing key at all. So the loss happens during config resolution, before the env-mapping step.
4. The container-side code is fine. At tag v0.27.42, containers/api-proxy/guards/ai-credits-guard.js:
functioncheckUnknownModelRejection(model,provider=undefined){constconfig=getAiCreditsConfig();if(!config.max)returnnull;if(!model)returnnull;if(config.defaultPricing)returnnull;// has fallback, don't reject
...
}
and getAiCreditsConfig() reads process.env.AWF_DEFAULT_AI_CREDITS_PRICING. Since that env var is never set, config.defaultPricing is null and the short-circuit never fires.
Why this looks like a resolution-layer bug
At v0.27.42 all the supporting pieces are present:
src/config-mapper.ts has defaultAiCreditsPricing: config.apiProxy?.defaultAiCreditsPricing
src/services/api-proxy-env-config.ts has ...(config.defaultAiCreditsPricing && { AWF_DEFAULT_AI_CREDITS_PRICING: JSON.stringify(config.defaultAiCreditsPricing) })
So the plumbing exists end to end, yet the value does not survive into the resolved config. Note that maxAiCredits reaches the container even though it is also set via CLI flag, which suggests the working fields may be arriving through the flag path rather than the config-file path, and that the config-file path is what is broken.
Impact
Any workflow pinned to, or resolving via alias to, a model newer than AWF's pricing catalog will fail with no working remedy. This is especially likely for alias users, because aliases like opus and sonnet deliberately resolve to the newest matching model, which is precisely the model most likely to be missing pricing. We hit it on a scheduled monthly workflow in github/docs-content and had to abandon the alias and pin an older model.
Suggested fixes
Ensure apiProxy.defaultAiCreditsPricing survives config resolution and reaches AWF_DEFAULT_AI_CREDITS_PRICING, matching the documented behavior.
Consider a CLI flag equivalent, mirroring how maxAiCredits is passed, so gh-aw has a path that is known to work.
Separately, it would help a lot if new models inherited a sane default price rather than hard-failing, so that a newly released model does not break scheduled workflows on the day it ships.
Note
This issue was opened by GitHub Copilot CLI, acting on behalf of @lecoursen. The investigation and artifact analysis below were done by the agent.
Summary
models.default-ai-credits-pricingis documented as the escape hatch for models that are missing from AWF's built-in pricing table. It does not work. gh-aw compiles it intoawf-config.jsoncorrectly, but AWF drops it during config resolution and never setsAWF_DEFAULT_AI_CREDITS_PRICINGon the API proxy container, so the guard never sees a fallback and rejects every request with HTTP 400.This makes the documented remedy for
unknown_model_ai_creditsa no-op.Versions
v0.83.4v0.27.42(both the installed binary and the pinned container images)copilot, model resolved toclaude-opus-5Symptom
All four copilot-harness attempts fail identically, so it is deterministic rather than transient.
Reproduction
Workflow frontmatter:
Compile with gh-aw v0.83.4 and run. The
opusalias resolves toclaude-opus-5, which has no catalog pricing, and the run fails despite the fallback being configured.Evidence from the run artifacts
1. gh-aw compiles the field correctly.
agent/awf-config.json:2. AWF does not propagate it to the container. In
sandbox/firewall/audit/docker-compose.redacted.yml, every siblingapiProxy.*field arrives as an env var on the api-proxy service:AWF_DEFAULT_AI_CREDITS_PRICINGis absent.3. The resolved config confirms the drop.
sandbox/firewall/audit/awf-resolved-config.jsonhas top-level keys includingmaxAiCredits,maxCacheMisses,maxRuns,modelAliases, andrateLimitConfig, but nodefaultAiCreditsPricingkey at all. So the loss happens during config resolution, before the env-mapping step.4. The container-side code is fine. At tag
v0.27.42,containers/api-proxy/guards/ai-credits-guard.js:and
getAiCreditsConfig()readsprocess.env.AWF_DEFAULT_AI_CREDITS_PRICING. Since that env var is never set,config.defaultPricingis null and the short-circuit never fires.Why this looks like a resolution-layer bug
At
v0.27.42all the supporting pieces are present:src/awf-config-schema.jsondefinesdefaultAiCreditsPricingsrc/config-mapper.tshasdefaultAiCreditsPricing: config.apiProxy?.defaultAiCreditsPricingsrc/services/api-proxy-env-config.tshas...(config.defaultAiCreditsPricing && { AWF_DEFAULT_AI_CREDITS_PRICING: JSON.stringify(config.defaultAiCreditsPricing) })So the plumbing exists end to end, yet the value does not survive into the resolved config. Note that
maxAiCreditsreaches the container even though it is also set via CLI flag, which suggests the working fields may be arriving through the flag path rather than the config-file path, and that the config-file path is what is broken.Impact
Any workflow pinned to, or resolving via alias to, a model newer than AWF's pricing catalog will fail with no working remedy. This is especially likely for alias users, because aliases like
opusandsonnetdeliberately resolve to the newest matching model, which is precisely the model most likely to be missing pricing. We hit it on a scheduled monthly workflow in github/docs-content and had to abandon the alias and pin an older model.Suggested fixes
apiProxy.defaultAiCreditsPricingsurvives config resolution and reachesAWF_DEFAULT_AI_CREDITS_PRICING, matching the documented behavior.maxAiCreditsis passed, so gh-aw has a path that is known to work.Related
docs/adr/47687-models-default-ai-credits-pricing-for-byok-models.mddocs/adr/48746-propagate-imported-default-ai-credits-pricing.md