Skip to content

Use engine-compatible endpoints for routed models - #66956

Merged
pelikhan merged 7 commits into
mainfrom
copilot/model-routing-fix
Oct 8, 2026
Merged

pelikhan merged 7 commits into
mainfrom
copilot/model-routing-fix

Conversation

Copilot AI commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

AWF may select an endpoint incompatible with Claude, Codex, or pi, causing routed runs to fail before inference. Non-Copilot engines need to verify the selected model’s supported APIs and use their own compatible endpoint.

  • Claude and Codex: On endpoint mismatch, consult complete /reflect routing metadata and use the first compatible engine endpoint. Preserve AWF’s original selection in selected_endpoint; fail closed when metadata is incomplete or there is no compatible endpoint.
  • Pi: Choose the API from Pi or AWF model catalog metadata, then verify its corresponding endpoint against /reflect before writing models.json.
  • Diagnostics and docs: Log the effective endpoint and any differing AWF selection; document runtime checks and the remaining effort-routing limitation.
inference routing: mode=awf-routed model=claude-opus-5 effort=max endpoint=/v1/messages selected_endpoint=/chat/completions

AWF still ranks efforts without engine-specific filtering, so unsupported efforts continue to fail closed pending an upstream AWF capability.

Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix model routing for claude/codex/pi endpoints Use engine-compatible endpoints for routed models Oct 8, 2026
Copilot AI requested a review from SivaKesava1 October 8, 2026 17:44
@SivaKesava1
SivaKesava1 marked this pull request as ready for review October 8, 2026 17:54
Copilot AI balanced review requested due to automatic review settings October 8, 2026 17:55
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.

No ADR enforcement needed for PR #66956: no 'implementation' label (has_implementation_label=false) and 0 new lines in default business logic directories (threshold 100, no custom .design-gate.yml).

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

✅ Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

✅ Ponytail Reviewer completed successfully!

Lean already. Ship.

Generated by Ponytail Reviewer for #66956

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer is reviewing this pull request using Matt Pocock's engineering skills...

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Incorrect AWF reflection metadata paths cause endpoint overrides and routed Pi runs to fail closed.

2 open findings
What changed in this PR

Updates non-Copilot model routing to select engine-compatible endpoints from AWF metadata.

Changes:

  • Adds endpoint override resolution for Claude, Codex, and Pi.
  • Preserves AWF-selected endpoints in diagnostics.
  • Documents endpoint validation and effort-routing limitations.
File Description
docs/​src/​content/​docs/​reference/​model-routing.md Documents routing behavior and diagnostics.
docs/​adr/​66723-extend-model-routing-to-claude-codex-pi.md Updates the routing decision record.
actions/​setup/​js/​awf_model_routing.cjs Resolves engine-compatible endpoints.
actions/​setup/​js/​awf_model_routing.test.cjs Tests shared endpoint resolution.
actions/​setup/​js/​claude_harness.cjs Applies and logs Claude endpoints.
actions/​setup/​js/​claude_harness.test.cjs Tests Claude endpoint overrides.
actions/​setup/​js/​codex_harness.cjs Applies and logs Codex endpoints.
actions/​setup/​js/​codex_harness.test.cjs Tests Codex endpoint overrides.
actions/​setup/​js/​pi_models_json.cjs Resolves and validates Pi APIs.
actions/​setup/​js/​pi_models_json.test.cjs Tests Pi API routing behavior.

🧠 Review effort: Balanced


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread actions/setup/js/awf_model_routing.cjs Outdated
Comment thread actions/setup/js/pi_models_json.cjs Outdated
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Comment Memory

Peek at saved memory (pr-code-quality-reviewer)
reviewed_at: 2026-10-08T18:01:06.016+00:00
review_event: REQUEST_CHANGES
top_themes:
  - endpoint-metadata binding bug in routed Copilot selection verification
files_reviewed:
  - actions/setup/js/awf_model_routing.cjs
  - actions/setup/js/awf_model_routing.test.cjs
  - actions/setup/js/claude_harness.cjs
  - actions/setup/js/claude_harness.test.cjs
  - actions/setup/js/codex_harness.cjs
  - actions/setup/js/codex_harness.test.cjs
  - actions/setup/js/pi_models_json.cjs
  - actions/setup/js/pi_models_json.test.cjs
  - docs/adr/66723-extend-model-routing-to-claude-codex-pi.md
  - docs/src/content/docs/reference/model-routing.md
comment_count: 1

Note

This comment is managed by comment memory.

Expand the saved memory block to view or edit the persistent context for this thread.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 42.1 AIC · ⌖ 5.41 AIC · ⊞ 19.8K · ◷
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict

The new endpoint-override path is still not safe when the routed model is advertised by more than one configured Copilot endpoint.

Blocking theme
  • Endpoint compatibility is now verified via a helper that picks the first matching routing_models entry for the selected model, not the specific reflected endpoint that produced the routing decision. That makes the override logic nondeterministic across multi-endpoint Copilot configurations and can turn a valid route into either a false failure or a misrouted request.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 42.1 AIC · ⌖ 5.41 AIC · ⊞ 19.8K
Comment /review to run again

Comment thread actions/setup/js/awf_model_routing.cjs
@github-actions github-actions Bot mentioned this pull request Oct 8, 2026
@SivaKesava1

Copy link
Copy Markdown
Collaborator

@copilot Tested this PR at head f2eb699d77 in a private sandbox (pi engine, engine.model-routing, default AWF v0.28.44). Both routed runs now fail closed before inference, including a GPT pick that succeeds on main:

selection: github-copilot/claude-opus-5 effort=max endpoint=/chat/completions
[gh-aw/pi-models-json] resolved model API=anthropic-messages (provider=github, model=claude-opus-5, source=Pi model catalog)
[gh-aw/pi-models-json] fatal: AWF /reflect cannot verify endpoints for Pi model claude-opus-5; candidate metadata is incomplete; refusing to start Pi

selection: github-copilot/gpt-5.6-luna effort=high endpoint=/responses
[gh-aw/pi-models-json] resolved model API=openai-responses (provider=github, model=gpt-5.6-luna, source=Pi model catalog)
[gh-aw/pi-models-json] fatal: AWF /reflect cannot verify endpoints for Pi model gpt-5.6-luna; candidate metadata is incomplete; refusing to start Pi

Cause: candidate_metadata_complete is a field of each routing_models entry, not of the top-level /reflect payload. See containers/api-proxy/management.js and the routing_models description in docs/api-proxy-sidecar.md in gh-aw-firewall. resolveAWFModelRoutingSelection (awf_model_routing.cjs) and resolvePiRoutingEndpoint (pi_models_json.cjs) both check reflectData.candidate_metadata_complete, which is always undefined, so every pi selection fails. Every Claude selection would fail too, because the override path always runs there. The unit tests pass only because their fixtures put the field at the top level.

This is the actual /reflect payload from the run (copilot endpoint, trimmed):

{
  "models_fetch_complete": true,
  "endpoints": [{
    "provider": "copilot", "configured": true,
    "routing_models": [
      {"model_id": "claude-opus-5", "source": "provider", "supported_endpoints": ["/v1/messages", "/chat/completions"], "supported_reasoning_efforts": ["low","medium","high","xhigh","max"], "context_window_tokens": 1000000, "candidate_metadata_complete": true},
      {"model_id": "claude-haiku-4.5", "source": "provider", "supported_endpoints": ["/chat/completions", "/v1/messages"], "supported_reasoning_efforts": [], "context_window_tokens": 200000, "candidate_metadata_complete": true}
    ]
  }],
  "routing": {"status": "selected", "selection": {"…": "…"}}
}

Please read candidate_metadata_complete from the matched routing_models entry, and update the test fixtures to this shape. A fixture built from the payload above would catch the regression: the GPT selection on /responses should pass unchanged, and the Claude selection on /chat/completions should resolve to /v1/messages for pi and Claude. I'll rerun both tasks once it's updated.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Impeccable Review — harden + audit (bug_fix: endpoint-routing correctness)

Traced the new endpoint-compatibility logic end to end (awf_model_routing.cjs, claude_harness.cjs, codex_harness.cjs, pi_models_json.cjs) and smoke-tested resolveAWFModelRoutingSelection, getAWFRoutingModel, resolvePiApiForModel, and resolvePiRoutingEndpoint directly in Node against the scenarios the PR's new tests cover (compatible-endpoint override, incomplete metadata, no-compatible-endpoint, Pi catalog-vs-reflect wire_api fallback).

Findings:

  • Fail-closed behavior is correct in all paths: incomplete candidate_metadata_complete/supported_endpoints and no-compatible-endpoint cases both return explicit errors instead of silently picking an endpoint.
  • selected_endpoint vs endpoint is threaded consistently through Claude, Codex, and Pi logging, matching the documented log-line examples in docs/src/content/docs/reference/model-routing.md.
  • ADR and reference docs were updated to reflect the new "AWF selection is advisory for non-Copilot engines" model, and the new troubleshooting table rows match the actual thrown error strings (advertises endpoints, candidate metadata is incomplete).
  • Test coverage (awf_model_routing.test.cjs, claude_harness.test.cjs, codex_harness.test.cjs, pi_models_json.test.cjs) exercises both the happy-path override and all fail-closed branches added in pi_models_json.cjs/awf_model_routing.cjs.

No blocking issues found. Sandbox network restrictions prevented running npm ci/vitest directly, so correctness was verified by isolated Node smoke tests of the exported functions against the PR's own fixtures — results matched the new test expectations in the diff.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet50 · 76.5 AIC · ⌖ 13.2 AIC · ⊞ 8.1K

Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>

Copilot AI commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Tested this PR at head f2eb699d77 in a private sandbox (pi engine, engine.model-routing, default AWF v0.28.44). Both routed runs now fail closed before inference, including a GPT pick tha...

Fixed in 47f922a2. Both resolvers now read candidate_metadata_complete from the matched routing_models entry. Fixtures use the production per-model shape, including the supplied Claude metadata. Tests verify Claude/Pi resolve to /v1/messages, GPT stays on /responses, and missing/false selected-model completeness fails closed. All 415 affected tests and the final repository validation gate passed.

@SivaKesava1

Copy link
Copy Markdown
Collaborator

@copilot Verified 47f922a2 in the private sandbox (pi engine, engine.model-routing, AWF v0.28.44). Both runs now work:

Task AWF selection pi Result
t01 gpt-5.6-luna high, /responses openai-responses on /responses ✅ 5/5 requests 200
t10 claude-opus-5 max, /chat/completions anthropic-messages on /v1/messages (selected_endpoint=/chat/completions logged) ✅ 18/18 requests 200 on /v1/messages; thinkingLevel: max on every message, so Copilot accepts max over the Messages API; all 18 routing records as_selected with deviations: ["endpoint"]

I couldn't test the Claude engine end to end yet. It still fails AWF's pre-flight on host.docker.internal:10002 (#66788 / #66957), so the /v1/messages override on claude_harness.cjs is covered only by your unit tests for now. I'll rerun it once #66957 lands.

@SivaKesava1

Copy link
Copy Markdown
Collaborator

@copilot Please address the open review thread on getAWFRoutingModel (#66956 (comment)). Ambiguity can't happen with today's AWF, which has one /reflect endpoint per adapter and only copilot is a GitHub alias, but add the cheap guard anyway:

  • In getAWFRoutingModel, find every configured GitHub-alias endpoint whose routing_models lists wire_model. If there's more than one, return no match, so resolveAWFModelRoutingSelection and resolvePiRoutingEndpoint fail closed with an error naming the model and the endpoints. Never pick the first one.
  • Add a unit test with two configured GitHub-alias endpoints (for example copilot and github) that both list the model, and assert that it fails closed. Leave the single-endpoint tests unchanged.
  • Reply on that review thread when done.

@SivaKesava1

Copy link
Copy Markdown
Collaborator

@copilot /pr-finisher

For the unresolved github-actions thread on getAWFRoutingModel, follow my reply in that thread: fail closed (no match) when more than one configured GitHub-alias endpoint lists the routed wire_model, add a unit test for it, then reply and resolve. The sandbox verification above (pi t01 and t10 at 47f922a2) covers runtime behaviour; please keep that behaviour unchanged.

Co-authored-by: SivaKesava1 <11771739+SivaKesava1@users.noreply.github.com>

Copilot AI commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

@copilot /pr-finisher

For the unresolved github-actions thread on getAWFRoutingModel, follow my reply in that thread: fail closed (no match) when more than one configured GitHub-alias endpoint li...

The ambiguity guard and regression tests are on 778f40ae, and the original review thread already has my substantive reply. I couldn't mark it resolved: the available GitHub MCP tools are read-only for thread state, and gh has no GH_TOKEN in this environment. Please resolve the thread manually; I have not claimed it is resolved.

@SivaKesava1
SivaKesava1 requested a review from pelikhan October 8, 2026 19:23
@SivaKesava1

Copy link
Copy Markdown
Collaborator

Ready for review. Verified in the private sandbox (pi engine, routing, AWF v0.28.44):

  • t01, gpt-5.6-luna high on /responses: works at 47f922a2 and again at 778f40ae (after the ambiguity guard).
  • t10, claude-opus-5 max: AWF selected /chat/completions, and pi now runs it on /v1/messages. 18/18 requests returned 200, max effort was accepted, and the routing records are as_selected with deviations: ["endpoint"].

All review threads are resolved; I resolved the last one after the guard landed in 778f40ae. The Claude engine can't be checked end to end until #66788 / #66957 lands, so the claude_harness.cjs path is covered only by unit tests. Effort filtering (part C of #66787) is still pending an AWF capability. CI on 778f40ae needs a re-trigger.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.91.7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Model routing on claude/codex/pi fails closed: AWF selection endpoint and effort are chosen for Copilot CLI, not the engine

4 participants