feat(router): provider-flexible /v1/embeddings with Azure Foundry path (A4) - #112
Merged
Merged
Conversation
…refix pin (A4) The /v1/embeddings passthrough now pins LiteLLM provider detection to the OpenAI-compatible Bearer-auth path: a bare EMBEDDING_MODEL is prefixed with openai/ before the litellm.aembedding call. Without the pin, an azure.com EMBEDDING_BASE_URL flips LiteLLM to its AZURE provider (api-key header auth), which Azure AI Foundry's /openai/v1 endpoint rejects with 400 unknown_model. An explicit provider/ prefix is honored unchanged, so classic Azure OpenAI resources (which genuinely want api-key auth) remain reachable. Ported from the upstream private deployment's incident learnings. Callers keep seeing the operator-facing model name; only the LiteLLM call carries the prefix. Tests: prefix-pin unit coverage, mocked Foundry-style end-to-end (pinned model + api_base + key reach litellm), response model field stays unprefixed, plus the existing 503-unconfigured / 400 / 502 fail-loud paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- docs/walkthroughs/azure-foundry-embeddings.md: create the Foundry text-embedding-3-small deployment, configure EMBEDDING_BASE_URL / EMBEDDING_API_KEY / EMBEDDING_MODEL, verify a 1536-dim vector with curl, and troubleshoot 400 unknown_model / 503 / 502 / wrong-dimension cases. - services/model-router/README.md: embeddings provider-config section + /v1/embeddings endpoint row, with the provider-detection pin note. - .env.example + docker-compose.yml: EMBEDDING_* pass-through on the model-router service, off by default (endpoint answers 503 until keyed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 12, 2026
mrobinson2
added a commit
that referenced
this pull request
Jul 12, 2026
…) (#118) Six PRs merged to main since v1.7 (A1-A6: vendored incident-fix defaults, agent-loop canary smoke, vendored-config schema guard, provider-flexible embeddings, canonical user-peer identity, hard cost-envelope enforcement) turn silent failures into loud ones across the vendored-app config surface, the router, and the agent-loop itself. Document them honestly as merged-to- main-but-unreleased in README's What's new/Roadmap and ROADMAP.md's new v1.8 section, and clean up a stale Future-releases item the v1.5/A6 cost governance work already supersedes. Co-authored-by: Michael Robinson <michaelrobinson@Michaels-PC.local> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
mrobinson2
pushed a commit
that referenced
this pull request
Jul 21, 2026
v1.7 hardened the security posture; applying that hardening to a real subscription then broke the paths that install and update the platform. v1.8 collects the repairs and the guards that make the same class of breakage fail loudly next time. Adds docs/releases/v1.8.0.md (fresh-deploy firewall/PG15 fix, the paperclip build-pin drift, the DSN username guard and its six-day outage, the gitleaks allowlists, dependency bumps, upgrade notes), a README section framing it as a repair release rather than a feature one, a ROADMAP "v1.8: shipped" section, and the release badge. The v1.7 tag was cut before the reliability-hardening merges (#112-#117) reached main, so those are documented under v1.7 and contained in this tag; v1.8.0.md covers only what is new since that documentation. Renames the horizon section to post-1.8 and adds the still-open services/paperclip Python 3.14 bump (#124) to it — its smoke job fails, so it is explicitly not in this release. The notes describe the demo feature-flag false positive rather than quoting the string: the allowlist that exempts it is scoped to docs/notes/, so reproducing it here would fail the scan, and widening a security allowlist to accommodate prose is the wrong trade. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mrobinson2
added a commit
that referenced
this pull request
Jul 21, 2026
…131) v1.7 hardened the security posture; applying that hardening to a real subscription then broke the paths that install and update the platform. v1.8 collects the repairs and the guards that make the same class of breakage fail loudly next time. Adds docs/releases/v1.8.0.md (fresh-deploy firewall/PG15 fix, the paperclip build-pin drift, the DSN username guard and its six-day outage, the gitleaks allowlists, dependency bumps, upgrade notes), a README section framing it as a repair release rather than a feature one, a ROADMAP "v1.8: shipped" section, and the release badge. The v1.7 tag was cut before the reliability-hardening merges (#112-#117) reached main, so those are documented under v1.7 and contained in this tag; v1.8.0.md covers only what is new since that documentation. Renames the horizon section to post-1.8 and adds the still-open services/paperclip Python 3.14 bump (#124) to it — its smoke job fails, so it is explicitly not in this release. The notes describe the demo feature-flag false positive rather than quoting the string: the allowlist that exempts it is scoped to docs/notes/, so reproducing it here would fail the scan, and widening a security allowlist to accommodate prose is the wrong trade. Co-authored-by: Michael Robinson <michaelrobinson@Michaels-PC.local> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Kills the memory system's hard OpenAI-billing dependency: the router's
/v1/embeddingspassthrough is now provider-flexible with a documented, end-to-end Azure AI Foundry deployment path — and it bakes in the load-bearing LiteLLM provider-detection pin so forks can't rediscover the400 unknown_modelfailure mode. Ported from the upstream private deployment's incident learnings.Design
openai/LiteLLM prefix pin (_pin_embedding_provider,services/model-router/main.py) — whenEMBEDDING_BASE_URLpoints at an azure.com host and the model string has noprovider/prefix, LiteLLM flips to its AZURE provider and authenticates with anapi-keyheader; Foundry's OpenAI-compatible/openai/v1endpoint rejects that with400 unknown_model. The router now prefixes a bareEMBEDDING_MODELwithopenai/before thelitellm.aembeddingcall, pinning detection to the Bearer-auth OpenAI-compatible path. An explicitprovider/prefix (e.g.azure/<deployment>for a classic Azure OpenAI resource) is honored unchanged._EMBED_MODELstays the reported model name; only_EMBED_LITELLM_MODEL(pinned) goes upstream. Callers never see the routing prefix.503untilEMBEDDING_API_KEY(or theOPENAI_API_KEYfallback) is set,502on upstream failure with the real error logged server-side only. No new required config; a clean fork boots exactly as before.EMBEDDING_API_KEY,EMBEDDING_BASE_URL,EMBEDDING_MODEL(defaulttext-embedding-3-small),EMBEDDING_TIMEOUT_SECONDS,EMBEDDING_MAX_INPUTS— wired throughdocker-compose.ymland.env.example.Test evidence
pytest -q services/model-router/tests(same invocation as CI's model-router step): 200 passed locally on Python 3.13.New/updated coverage in
services/model-router/tests/test_embeddings.py(10 passed):openai/text-embedding-3-small; explicitazure/...andopenai/...honored without stacking; import-time default is pinnedapi_base+ key all reachlitellm.aembeddingmodelfield stays unprefixed when the upstream omits it503unconfigured,400missing/oversized input,502provider errorDocs
docs/walkthroughs/azure-foundry-embeddings.md— end to end: create the Foundrytext-embedding-3-smalldeployment (portal +azCLI), set the three env vars, verify a 1536-dim vector with curl, and a troubleshooting section that explains theunknown_modelmechanism, plus503/502/wrong-dimension cases.services/model-router/README.md— embeddings provider-config section +/v1/embeddingsendpoint row.🤖 Generated with Claude Code