These four Azure pieces are already in the app. This page is the order to wire them, using the sample collection as the thing the pipeline runs.

flowchart LR
  entra["Entra\nclient credentials"]:::step
  kv[("Key Vault\nakv://")]:::secret
  api["Users API\nor an MCP server"]:::out
  aoai["Azure OpenAI\non the tab"]:::store
  ado(["Azure DevOps\ntermorq-cli run"]):::exit

  entra --> api
  kv --> api
  api --> aoai
  api --> ado

  classDef store fill:#134e4a,stroke:#5eead4,stroke-width:2px,color:#f4fbfa
  classDef secret fill:#FFC131,stroke:#b45309,stroke-width:2px,color:#1a1404
  classDef step fill:#0f766e,stroke:#99f6e4,stroke-width:2px,color:#f4fbfa
  classDef out fill:#155e75,stroke:#67e8f9,stroke-width:2px,color:#f4fbfa
  classDef exit fill:#166534,stroke:#86efac,stroke-width:2px,color:#f0fdf4
  linkStyle 0,2 stroke:#5eead4,stroke-width:2.5px
  linkStyle 1 stroke:#FFC131,stroke-width:2.5px
  linkStyle 3 stroke:#86efac,stroke-width:2.5px

1. A secret in Key Vault

Create the secret in Key Vault. In the app, put the reference in the connection’s secret field:

akv://my-vault/users-api

Test reference, or @vault test akv://my-vault/users-api, resolves it with az keyvault secret show under your current az login. The screen shows the length. @workspace save keeps the reference. The guard refuses the raw secret if it is still in a file.

The same reference works for an API key, a bearer token, a client secret, an OpenAI key, or an MCP Azure client secret.

2. Entra client credentials

For an API that expects an app token, @create api → Client credentials: tenant id, client id, client secret (or the akv:// reference), and scope.

For an MCP server that expects the same, @create mcp → Azure client credentials, with the same four fields.

The app requests the token when it calls. It does not open a browser. That is the form termorq-cli can run. Browser OAuth and device code stay on your machine.

3. Azure OpenAI on the tab

@create openai → Azure OpenAI: resource endpoint, deployment name, and key (or akv://). Both URL styles work: a host that contains /openai/v1, and a classic deployment host.

@openai selects it for this tab. @chat, the Agent toggle, @explain, a line that starts with #, a prompt skill, and --llm on a tool call all use that connection. With Agent on, a line that starts with @ still runs as a command. termorq-cli does not call the model. A collection step that is @chat or @agent is skipped.

4. Azure DevOps

Build termorq-cli, point --workspace at the checkout with an absolute path, and publish JUnit from stdout. The secret is a pipeline variable, not a file.

- script: >
    src-tauri/target/release/termorq-cli run Smoke
    --workspace $(Build.SourcesDirectory)
    --env Staging
    --allow-shell
    --format junit
    > $(Build.ArtifactStagingDirectory)/termorq-cli.xml
  env:
    AIT_SECRET_USERS_API: $(USERS_API_KEY)
- task: PublishTestResults@2
  condition: always()
  inputs:
    testResultsFormat: JUnit
    testResultsFiles: $(Build.ArtifactStagingDirectory)/termorq-cli.xml

$(Build.SourcesDirectory) is absolute. A relative . is rejected. If the connection’s secret field is already akv://…, the hosted agent needs az logged in with access to that vault, and you can omit AIT_SECRET_USERS_API. The environment variable wins when both are set.

The full GitHub, GitLab, and Azure DevOps files, including the Linux packages the link needs, are on Pipelines.