Skip to content

feat(azure-foundry): add Microsoft Entra ID auth#27509

Closed
glennc wants to merge 1 commit into
NousResearch:mainfrom
glennc:feat/azure-entra-auth
Closed

feat(azure-foundry): add Microsoft Entra ID auth#27509
glennc wants to merge 1 commit into
NousResearch:mainfrom
glennc:feat/azure-entra-auth

Conversation

@glennc

@glennc glennc commented May 17, 2026

Copy link
Copy Markdown
Contributor

Use azure-identity DefaultAzureCredential for keyless Foundry auth.

Preserve refreshable callable credentials through OpenAI and Anthropic client paths. Add setup, doctor, auth status, docs, and tests for Entra auth.

One design question: I tried to not impact Hermes as much as I could, but it does introduces the idea that api_key could be a string or callable depending on your provider. We should perhaps make it only a callable everywhere and have the paths that use an api_key return the str from that callable. I didn't do it because it wasn't completely obvious that was better, or that there wasn't a more minimal approach we could take. Looking for feedback on that.

What does this PR do?

Implements foundry bearer auth using DefaultAzureCredential, which is a chained credential that looks at many locations but most importantly for this use case looks at your local az login creds for local use and the agent id that is assigned to an agent when it is running on foundry itself. It takes into account token refresh, token caching, and attempts to do this changing as little of the rest of Hermes as it can.

Token auth is preferred over API keys because it uses short-lived bearer tokens derived from the local or managed identity environment, reducing the risk and impact of leaked long-lived API keys. Many corporate environments do not allow api key to be enabled on Foundry when creating projects meaning without this they cannot use Hermes with Foundry models at all.

Related Issue

Fixes #25162

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • Added Azure Entra ID bearer-token support via agent/azure_identity_adapter.py.
  • Wired Azure Foundry runtime resolution for auth_mode: entra_id in hermes_cli/runtime_provider.py, agent/agent_init.py, and related agent runtime paths.
  • Preserved callable API keys through OpenAI-compatible, Anthropic-compatible, auxiliary, compression, batch, ACP, CLI, and TUI gateway flows.
  • Added Azure Foundry setup/detection/auth status support in hermes_cli/auth.py, hermes_cli/auth_commands.py, hermes_cli/azure_detect.py, hermes_cli/doctor.py, and hermes_cli/main.py.
  • Added lazy dependency/install support for azure-identity in pyproject.toml, uv.lock, and tools/lazy_deps.py.
  • Updated Azure Foundry provider metadata in plugins/model-providers/azure-foundry/.
  • Added tests for Entra auth detection, callable credentials, Azure identity behavior, auxiliary clients, Anthropic adapter compatibility, and CLI setup flows.
  • Updated Azure Foundry and environment variable documentation.

How to Test

  1. Run targeted tests:
    scripts/run_tests.sh \
      tests/agent/test_azure_identity_adapter.py \
      tests/agent/test_auxiliary_client_azure_foundry.py \
      tests/agent/test_anthropic_adapter.py \
      tests/acp_adapter/test_detect_provider_entra.py \
      tests/hermes_cli/test_azure_foundry_entra.py \
      tests/hermes_cli/test_azure_detect.py \
      tests/run_agent/test_callable_api_key.py \
      -q
    
  2. Manually configure Azure Foundry with Entra auth, then authenticate locally: az login
    hermes model
  3. Select/configure Azure Foundry with Entra ID auth and verify Hermes can make a request without AZURE_FOUNDRY_API_KEY.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Ubuntu 24.04

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A

Screenshots / Logs

image

as a follow up PR we can probably improve this model list selection when logged in with az, as the user could call apis that you cannot with just an api key and fetch actually deployed models in the project rather than all possible models.

Use azure-identity DefaultAzureCredential for keyless Foundry auth.

Preserve refreshable callable credentials through OpenAI and Anthropic client paths.

Add setup, doctor, auth status, docs, and tests for Entra auth.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@glennc glennc requested a review from a team May 17, 2026 17:05
@alt-glitch alt-glitch added type/feature New feature or request comp/agent Core agent loop, run_agent.py, prompt builder comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins area/auth Authentication, OAuth, credential pools P3 Low — cosmetic, nice to have labels May 17, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Merged via PR #28101. Your commit was cherry-picked onto current main with your authorship preserved in git log (commit 9df9816 — "feat(azure-foundry): add Microsoft Entra ID auth").

Two small things on top:

  1. Conflict resolution in agent/anthropic_adapter.py: yesterday's salvage of fix(auth): send Bearer auth for Azure Foundry anthropic_messages endpoints #27022 landed a _is_minimax_anthropic_endpoint predicate, so both predicates now coexist. I also broadened your _is_azure_anthropic_endpoint to match *.openai.azure.com in addition to *.services.ai.azure.* — keeps legacy Azure-OpenAI-on-Anthropic hosts on the api-version query-param plumbing.

  2. AUTHOR_MAP entry added for glennc@microsoft.com (commit 65e0c49) so CI doesn't block future PRs.

On your design question ("api_key as str | callable everywhere vs only callable"): the per-site callable(api_key) checks you used are fine for now. The callable variant is rare enough (Entra-only) that pushing it through every consumer as the canonical shape would be churn for no win. If a second callable-credential provider shows up later (e.g. STS / OIDC federation), revisit then.

Thanks for the contribution — keyless Foundry was a real gap. Will ship in the next release.

Closes #25162.

@glennc glennc deleted the feat/azure-entra-auth branch May 18, 2026 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools comp/agent Core agent loop, run_agent.py, prompt builder comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Azure Foundry provider should support Microsoft Entra ID / Bearer Token auth

3 participants