feat(azure-foundry,bedrock): Entra ID auth modes, agent tools forwarding, and AssumeRole support - #1447
Open
shaileshpadave wants to merge 16 commits into
Open
feat(azure-foundry,bedrock): Entra ID auth modes, agent tools forwarding, and AssumeRole support#1447shaileshpadave wants to merge 16 commits into
shaileshpadave wants to merge 16 commits into
Conversation
shaileshpadave
marked this pull request as draft
July 31, 2026 15:52
shaileshpadave
marked this pull request as ready for review
July 31, 2026 16:36
Azure Foundry and Bedrock now read the endpoint/agent identity from a top-level agentUrl field on ConductorAgentStartRequest, consistent with how A2ACallRequest exposes agentUrl for remote A2A agents. - AzureFoundryAgentClient: reads agentUrl first, falls back to rawConfig.endpoint then AZURE_FOUNDRY_ENDPOINT secret - BedrockAgentClient: parses bedrock://AGENTID/ALIASID[?region=...] URI from agentUrl, falls back to rawConfig.agentId/agentAliasId This lets the UI treat all agent types uniformly via the agentUrl field.
- BedrockAgentClient: agentUrl (bedrock://AGENTID/ALIASID) is now required; removed rawConfig.agentId/rawConfig.agentAliasId fallback and the fake TSTALIASID default alias; throws clearly if agentId or aliasId is missing - AzureFoundryAgentClient: agentUrl is now the only endpoint source (besides the AZURE_FOUNDRY_ENDPOINT system secret); removed rawConfig.endpoint fallback - ConductorAgentStartRequest: converted agentUrl Javadoc to plain-text comment
- Add dual auth: API key (api-key header) or OAuth with ai.azure.com scope,
auto-detected from credentialRef secret fields
- Route to Responses API (POST /openai/responses) for services.ai.azure.com
endpoints; classic Threads/Runs API used for openai.azure.com endpoints
- Auto-detect OAuth scope from endpoint URL (no manual rawConfig.scope needed)
- Fetch agent instructions from GET /agents/{id} when not provided inline
- Remove rawConfig.endpoint fallback — agentUrl top-level field is required
agentUrl now carries the agent/assistant ID directly in the path:
Classic: …/openai/assistants/asst_xxx
Foundry proj: …/api/projects/{proj}/agents/{name}
resolveEndpoint() strips the suffix to get the base URL;
resolveAssistantId() parses it out first, falls back to rawConfig.assistantId
for existing workflow definitions.
Auth (azure-identity replaces hand-rolled OAuth): - API key: secret.apiKey → api-key header - Service Principal: secret.client_id/client_secret/tenant_id → ClientSecretCredential - User-assigned managed identity: secret.clientId only → ManagedIdentityCredential - DefaultAzureCredential: no credentialRef → env vars → workload identity → MI → CLI Agent types (third routing path added): - Azure AI Inference: *.inference.ml.azure.com or .../models → chat/completions - Foundry project agents: services.ai.azure.com/api/projects → Responses API - Classic Assistants: openai.azure.com → Threads/Runs API Scope auto-detected from endpoint URL; overridable via rawConfig.scope.
shaileshpadave
force-pushed
the
feature/agent-url-top-level
branch
from
August 3, 2026 06:55
b749087 to
8f675de
Compare
- Replace resolveInstructions() with fetchAgentDefinition() that fetches
both instructions and tools from the agent's latest version in one call
- Include tools from the agent definition in Responses API request body
so web_search, code_interpreter, and file_search actually execute
- Add toResponsesApiTools() to adapt definition format to Responses API
format (code_interpreter needs container:{type:auto})
Tested: web_search retrieved live Kafka 4.3.0 release notes;
file_search retrieved Orkes Conductor info from uploaded knowledge base
…auth detection 31 tests across 6 nested groups — no Azure credentials or network required: - ExtractAgentIdFromUrl: Foundry agent name, classic assistant ID, trailing slash, null, no marker, last-marker-wins - IsInferenceEndpoint / IsFoundryProjectEndpoint: all 3 URL patterns plus null, mutual-exclusion assertion across all pattern combos - ToResponsesApiTools: code_interpreter gets container injected, web_search and file_search pass through unchanged, all-three mixed, empty array - BuildAuthState: API key → api-key header; client_id/secret/tenant → ClientSecretCredential; camelCase clientId → ManagedIdentityCredential; no credentialRef → DefaultAzureCredential; API key wins over SP creds; incomplete SP falls through to Default; scope auto-detected from endpoint (ml.azure.com, ai.azure.com, cognitiveservices.azure.com) Made static helper methods and AuthState package-private to allow direct access from the same-package test without reflection.
…rovider
Adds a third credential path between static keys and the SDK default chain.
When the credentialRef secret has a roleArn field, the client uses
StsAssumeRoleCredentialsProvider so credentials auto-refresh — no manual
token management needed. Supports optional roleSessionName (default:
conductor-bedrock) and externalId for cross-account role setups.
Secret shape:
{ "roleArn": "arn:aws:iam::123:role/MyRole" } # minimal
{ "roleArn": "...", "roleSessionName": "...",
"externalId": "..." } # full
Covers two live-call paths: default SDK credential chain (env vars) and static accessKeyId+secretAccessKey. Both skip automatically when credentials are absent, so CI stays clean. Static test also skips when session-token (STS) creds are present — AwsBasicCredentials doesn't carry a session token. Uses shailesh-test-agent (KZGTZ8AKK2 / TSTALIASID, us-east-1).
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 changed
1.
agentUrlembeds the agent/assistant IDAgent and assistant IDs are now part of the URL path — no
rawConfigneeded:https://my-resource.services.ai.azure.com/api/projects/{proj}/agents/{name}https://my-resource.openai.azure.com/openai/assistants/asst_xxxbedrock://AGENTID/ALIASID?region=us-east-1The client strips the ID from the URL to get the base endpoint, then re-extracts it when needed.
rawConfig.assistantIdstill works as a fallback.2. Three Azure routing paths (auto-detected from URL)
*.inference.ml.azure.comorservices.ai.azure.com/modelsPOST /chat/completionsservices.ai.azure.com/api/projects/…POST /openai/responses*.openai.azure.com/openai/…3. Four auth modes via Azure Identity SDK (
com.azure:azure-identity:1.15.4)Detection order — first match wins:
{"apiKey": "..."}{"client_id", "client_secret", "tenant_id"}ClientSecretCredential(Service Principal){"clientId": "..."}(camelCase, user-assigned MI)ManagedIdentityCredentialcredentialRefDefaultAzureCredential— env vars → workload identity → MI → Azure CLIThe SDK caches and auto-refreshes tokens. OAuth scope is auto-detected from the endpoint URL.
4. Tools forwarded from agent definition to Responses API
startAgentResponses()fetches the agent's latest version definition (instructions + tools) in one API call and includes the tools in the Responses API request body — soweb_search,code_interpreter, andfile_searchconfigured in the Foundry portal flow through automatically without any workflow changes.code_interpretergetscontainer: {type: auto}injected since the Responses API requires it.Tested end-to-end
Auth modes (all 4 verified):
az cognitiveservices account keys list, workflow withcredentialRefpointing to{"apiKey":"..."}{"client_id","client_secret","tenant_id"}secret, Entra token flowcredentialRefin workflow, SDK picked upaz loginsessionTools (all 3 verified):
web_search— retrieved live Kafka 4.3.1 release notes, USD/EUR exchange ratesfile_search— knowledge base lookup returned Orkes Conductor info from uploaded filecode_interpreter— computed sales averages and formulas; combined with web_search to convert live exchange ratesRouting paths:
openai.azure.com) — Threads/Runs — greeter, summarizer, analyst ✓services.ai.azure.com) — Responses API — greeter, summarizer, analyst ✓