Skip to content

feat(azure-foundry,bedrock): Entra ID auth modes, agent tools forwarding, and AssumeRole support - #1447

Open
shaileshpadave wants to merge 16 commits into
mainfrom
feature/agent-url-top-level
Open

feat(azure-foundry,bedrock): Entra ID auth modes, agent tools forwarding, and AssumeRole support#1447
shaileshpadave wants to merge 16 commits into
mainfrom
feature/agent-url-top-level

Conversation

@shaileshpadave

@shaileshpadave shaileshpadave commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

What changed

1. agentUrl embeds the agent/assistant ID

Agent and assistant IDs are now part of the URL path — no rawConfig needed:

  • Foundry project agent: https://my-resource.services.ai.azure.com/api/projects/{proj}/agents/{name}
  • Classic assistant: https://my-resource.openai.azure.com/openai/assistants/asst_xxx
  • Bedrock: bedrock://AGENTID/ALIASID?region=us-east-1

The client strips the ID from the URL to get the base endpoint, then re-extracts it when needed. rawConfig.assistantId still works as a fallback.

2. Three Azure routing paths (auto-detected from URL)

Endpoint pattern API used
*.inference.ml.azure.com or services.ai.azure.com/models Azure AI Inference — POST /chat/completions
services.ai.azure.com/api/projects/… Foundry project agents — POST /openai/responses
*.openai.azure.com/openai/… Classic Assistants — Threads/Runs

3. Four auth modes via Azure Identity SDK (com.azure:azure-identity:1.15.4)

Detection order — first match wins:

Secret shape Mode
{"apiKey": "..."} API key header — no SDK
{"client_id", "client_secret", "tenant_id"} ClientSecretCredential (Service Principal)
{"clientId": "..."} (camelCase, user-assigned MI) ManagedIdentityCredential
no credentialRef DefaultAzureCredential — env vars → workload identity → MI → Azure CLI

The 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 — so web_search, code_interpreter, and file_search configured in the Foundry portal flow through automatically without any workflow changes.

code_interpreter gets container: {type: auto} injected since the Responses API requires it.

Tested end-to-end

Auth modes (all 4 verified):

  • API key — key from az cognitiveservices account keys list, workflow with credentialRef pointing to {"apiKey":"..."}
  • Service Principal — {"client_id","client_secret","tenant_id"} secret, Entra token flow
  • User-assigned Managed Identity — created UAMI, attached to Azure Container Instance, confirmed IMDS token → Foundry API call succeeds
  • DefaultAzureCredential — no credentialRef in workflow, SDK picked up az login session

Tools (all 3 verified):

  • web_search — retrieved live Kafka 4.3.1 release notes, USD/EUR exchange rates
  • file_search — knowledge base lookup returned Orkes Conductor info from uploaded file
  • code_interpreter — computed sales averages and formulas; combined with web_search to convert live exchange rates

Routing paths:

  • Classic Assistants (openai.azure.com) — Threads/Runs — greeter, summarizer, analyst ✓
  • Foundry project agents (services.ai.azure.com) — Responses API — greeter, summarizer, analyst ✓
  • Guardrails (Azure RAI policy) — harmful prompt blocked cleanly on new agent version ✓

@shaileshpadave
shaileshpadave marked this pull request as draft July 31, 2026 15:52
@shaileshpadave
shaileshpadave marked this pull request as ready for review July 31, 2026 16:36
shaileshpadave and others added 8 commits August 3, 2026 12:25
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
shaileshpadave force-pushed the feature/agent-url-top-level branch from b749087 to 8f675de Compare August 3, 2026 06:55
- 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.
@shaileshpadave shaileshpadave changed the title feat: add agentUrl top-level field for Azure Foundry and Bedrock feat(azure-foundry): Entra ID auth, agent tools forwarding, and three-path routing Aug 3, 2026
…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
@shaileshpadave shaileshpadave changed the title feat(azure-foundry): Entra ID auth, agent tools forwarding, and three-path routing feat(azure-foundry,bedrock): Entra ID auth modes, agent tools forwarding, and AssumeRole support Aug 3, 2026
shaileshpadave and others added 4 commits August 3, 2026 20:14
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).
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.

2 participants