Accept project-scoped AI Foundry endpoints#23
Open
TheovanKraay wants to merge 1 commit into
Open
Conversation
Normalize ai_foundry_endpoint so a project-scoped Foundry URL (.../api/projects/<name>) is stripped to the inference base the OpenAI SDK expects. Lets callers paste whichever endpoint form the Foundry portal shows them. Adds unit tests, CHANGELOG, and .env.template guidance.
There was a problem hiding this comment.
Pull request overview
This PR updates the toolkit’s handling of ai_foundry_endpoint so users can provide Azure AI Foundry project-scoped URLs (as commonly copied from the Foundry portal) and have them automatically normalized to the account-level inference base URL required by the OpenAI SDK.
Changes:
- Added
normalize_ai_foundry_endpoint()to strip/api/projects/<name>[/…], trim whitespace, and remove trailing slashes. - Applied normalization at the shared configuration chokepoint (
_BaseMemoryClient._init_base_config). - Added unit tests plus documentation updates (
.env.template,CHANGELOG.md).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
azure/cosmos/agent_memory/_utils.py |
Adds endpoint normalization helper for Foundry project-scoped URLs. |
azure/cosmos/agent_memory/_base/base_client.py |
Applies normalization when initializing shared client config. |
tests/unit/test_utils.py |
Adds unit coverage for the new normalization helper. |
tests/unit/_base/test_base_client.py |
Verifies normalization is applied during base client initialization. |
.env.template |
Documents accepted endpoint forms (including project-scoped URLs). |
CHANGELOG.md |
Notes new behavior for ai_foundry_endpoint in Unreleased. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+204
to
+208
| if not endpoint: | ||
| return endpoint | ||
| trimmed = endpoint.strip() | ||
| trimmed = _AI_FOUNDRY_PROJECT_PATH_RE.sub("", trimmed) | ||
| return trimmed.rstrip("/") |
aayush3011
approved these changes
Jun 24, 2026
aayush3011
left a comment
Contributor
There was a problem hiding this comment.
LGTM, other than the copilot comment and the lint builds failing
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.
Accept project-scoped AI Foundry endpoints
Why
ai_foundry_endpointonly accepts the account-level inference endpoint today (https://<resource>.services.ai.azure.comor.openai.azure.com), because the toolkit talks to the model APIs through the OpenAI SDK (AzureOpenAI(azure_endpoint=...)). But the Azure AI Foundry portal commonly hands users a project-scoped URL instead:Pasting that into
AI_FOUNDRY_ENDPOINTyields opaque404/routing errors. The parameter name promises "a Foundry endpoint" but the implementation silently demands an Azure OpenAI one.This surfaced while integrating the toolkit into the Microsoft Agent Framework as a
CosmosMemoryContextProvider(newagent-framework-azure-cosmos-memorypackage). The goal there is a single-endpoint experience: one AI Foundry endpoint drives both the memory pipeline (this toolkit) and the chat agent (the framework'sFoundryChatClient). The catch — the framework's client accepts the project URL natively, but the toolkit rejects the exact same value unless the user manually strips/api/projects/<name>.Why fix it here (and not in the Agent Framework integration)
ai_foundry_endpointis the toolkit's own public contract, so the toolkit should own what's valid for it. Fixing it here benefits every consumer (direct users, the Agent Framework provider, future integrations), not just one wrapper. Pushing normalization into the integration layer would paper over the leaky abstraction and leave the next caller to rediscover the same papercut. Since, for*.services.ai.azure.comresources, the project path is just a suffix on the same host that serves inference, the safe, canonical fix lives right where the endpoint is consumed.What changed
normalize_ai_foundry_endpoint()in_utils.py: strips atrailing
/api/projects/<name>[/...](case-insensitive), trims whitespace andtrailing slash, passes
None/empty through, and leaves non-project endpointsunchanged.
_BaseMemoryClient._init_base_config— the single configchokepoint shared by the sync and async clients.
.env.templatedocuments the accepted forms;CHANGELOG.mdupdated.Behavior (non-breaking)
https://r.services.ai.azure.com/api/projects/phttps://r.services.ai.azure.comhttps://r.services.ai.azure.com/https://r.openai.azure.comhttps://r.services.ai.azure.com/https://r.services.ai.azure.comNone/""Tests
10 new tests (8 for the helper, 2 on the base client). Full unit suite green except 5 pre-existing
duration_ms > 0.0reconcile-telemetry timing flakes (confirmed failing onmain; unrelated).Scope
Covers the modern
*.services.ai.azure.comcase via pure string normalization (no new deps). Legacy hub/project endpoints on a different host than the linked Azure OpenAI resource would needAIProjectClientlookup — left as a follow-up.