Skip to content

How to Use an LLM Gateway with Fix with AI


By default, the Boost advisor that runs Fix with AI calls your LLM provider directly with the provider's API key. To route these calls through your own OpenAI-compatible LLM gateway instead, set a few more variables in the pipeline that runs the advisor. Nothing changes in the Boost Security dashboard. When none of these variables are set, the advisor keeps calling the provider directly.


Before You Start


  • The Boost advisor is set up for your SCM, as described in the Fix with AI prerequisites.
  • Your gateway exposes the OpenAI chat completions API, with tool calling. The advisor sends tools on every call and can't work without them.
  • Your gateway is reachable over HTTPS from the CI runners of the advisor pipeline. The advisor calls the gateway from your own pipeline, never from Boost Security servers.
  • You know which authentication methods your gateway requires: OAuth2 client credentials, an API key sent in a header, or both.

Gateway Variables


Add these variables to the secrets or variables of the advisor pipeline. You already have BOOST_LLM_MODEL and BOOST_LLM_KEY from the advisor setup. Store at least the client ID, the client secret and BOOST_LLM_KEY as secrets. On GitHub, store all of them as secrets.

Variable Must be secret Required for Can be left empty Value
BOOST_LLM_MODEL No Always No The model name as your gateway knows it.
BOOST_LLM_API_FORMAT No Any gateway Yes openai, the only supported value. Setting it makes the advisor call your gateway.
BOOST_LLM_BASE_URL No Any gateway Yes The base URL of your gateway, starting with https://. The advisor sends its requests to <base URL>/chat/completions and doesn't add /v1, so include it in the base URL when your gateway needs it.
BOOST_LLM_OAUTH_TOKEN_URL No OAuth2 Yes The token endpoint of your identity provider, starting with https://. Setting it turns on OAuth2.
BOOST_LLM_OAUTH_CLIENT_ID Yes OAuth2 Yes The client ID.
BOOST_LLM_OAUTH_CLIENT_SECRET Yes OAuth2 Yes The client secret.
BOOST_LLM_OAUTH_SCOPE No OAuth2, optional Yes The scope sent in the token request, when your identity provider needs one.
BOOST_LLM_API_KEY_HEADER No API key Yes The name of the header that carries the API key, for example HUB_API_KEY, or Authorization. Setting it turns on the API key method.
BOOST_LLM_KEY Yes Direct, or API key Yes Without a gateway: the API key of your LLM provider. With a gateway: the value sent in the API key header, as is. For example, for the Authorization header, a value such as Bearer sk-…. Not needed for OAuth2 only.

The advisor treats a variable marked Can be left empty as not set when it's missing, when its value is empty, or when its value is the text $(<variable name>), as Azure DevOps passes a variable that isn't defined. You can therefore pass all these variables to the advisor and leave empty the ones of the methods you don't use. BOOST_LLM_MODEL must always have a value: the run fails when it's missing.


Authentication Methods


Your gateway can require one or both methods. When both are set, the advisor sends both on every call.

Set BOOST_LLM_OAUTH_TOKEN_URL, BOOST_LLM_OAUTH_CLIENT_ID, BOOST_LLM_OAUTH_CLIENT_SECRET, and optionally BOOST_LLM_OAUTH_SCOPE.

At the start of each run, the advisor gets an access token from the token endpoint and sends it as Authorization: Bearer <token>. Your identity provider must:

  • Support the client credentials grant, with the client authenticated with HTTP Basic (client_secret_basic).
  • Return the token in the access_token field of the response.
  • Issue a token that lasts for the whole run. The advisor gets one token per run and doesn't refresh it. One run produces one fix, and ends well within a typical one-hour token lifetime.
  • Issue the right token without an audience parameter, which the advisor doesn't send. For identity providers that need one, such as Auth0, set the API of your gateway as the default audience of the tenant.

Set BOOST_LLM_API_KEY_HEADER to the header name, and BOOST_LLM_KEY to its value. The advisor sends the value as is, on every call.

Set the variables of both methods. The API key header can't be Authorization, since OAuth2 already uses it.


Pass the Variables to the Advisor


Add the variables as secrets of the .boost repository. The Run boost-advisor step of the advisor workflow maps all of them in its env. A secret that isn't set reaches the advisor as an empty value, which counts as not set, so the same workflow works for every authentication method. Create only the secrets of the methods you use, plus BOOST_LLM_MODEL. If your workflow was created before, replace its Run boost-advisor step with:

      - name: Run boost-advisor
        env:
          BOOST_API_KEY: ${{ secrets.BOOST_API_TOKEN }}
          BOOST_SCM_TOKEN: ${{ secrets.BOOST_SCM_TOKEN }}
          BOOST_LLM_MODEL: ${{ secrets.BOOST_LLM_MODEL }}
          BOOST_LLM_KEY: ${{ secrets.BOOST_LLM_KEY }}
          BOOST_LLM_API_FORMAT: ${{ secrets.BOOST_LLM_API_FORMAT }}
          BOOST_LLM_BASE_URL: ${{ secrets.BOOST_LLM_BASE_URL }}
          BOOST_LLM_OAUTH_TOKEN_URL: ${{ secrets.BOOST_LLM_OAUTH_TOKEN_URL }}
          BOOST_LLM_OAUTH_CLIENT_ID: ${{ secrets.BOOST_LLM_OAUTH_CLIENT_ID }}
          BOOST_LLM_OAUTH_CLIENT_SECRET: ${{ secrets.BOOST_LLM_OAUTH_CLIENT_SECRET }}
          BOOST_LLM_OAUTH_SCOPE: ${{ secrets.BOOST_LLM_OAUTH_SCOPE }}
          BOOST_LLM_API_KEY_HEADER: ${{ secrets.BOOST_LLM_API_KEY_HEADER }}
          PAYLOAD: ${{ inputs.payload }}
        run: |
          echo "$PAYLOAD" | /tmp/boost-advisor/latest -

Add the variables in Settings → CI/CD → Variables of the boost project, with Masked selected for the secrets. The advisor job reads them as they are, with no change to .gitlab-ci.yml. Add only the variables of the methods you use. A variable that is missing, or added with an empty value, counts as not set.

Add the variables in Repository settings → Pipelines → Repository variables of the .boost repository, with Secured selected for the secrets. The advisor step reads them as they are, with no change to bitbucket-pipelines.yml. Add only the variables of the methods you use. A variable that is missing, or added with an empty value, counts as not set.

Add the variables to the boostsecurityio variable group, with the lock icon selected for the secrets. The Run boost-advisor step of the advisor pipeline maps all of them in its env. A variable that isn't in the group reaches the advisor as the text $(<variable name>), and a variable with an empty value as an empty value. Both count as not set, so the same pipeline works for every authentication method. Add to the group only the variables of the methods you use, plus BOOST_LLM_MODEL. If your pipeline was created before, replace its Run boost-advisor step with:

    - script: |
        echo "$PAYLOAD" | /tmp/boost-advisor/latest -
      displayName: Run boost-advisor
      env:
        BOOST_SCM_TOKEN: $(BOOST_SCM_TOKEN)
        BOOST_API_KEY: $(BOOST_API_TOKEN)
        BOOST_LLM_MODEL: $(BOOST_LLM_MODEL)
        BOOST_LLM_KEY: $(BOOST_LLM_KEY)
        BOOST_LLM_API_FORMAT: $(BOOST_LLM_API_FORMAT)
        BOOST_LLM_BASE_URL: $(BOOST_LLM_BASE_URL)
        BOOST_LLM_OAUTH_TOKEN_URL: $(BOOST_LLM_OAUTH_TOKEN_URL)
        BOOST_LLM_OAUTH_CLIENT_ID: $(BOOST_LLM_OAUTH_CLIENT_ID)
        BOOST_LLM_OAUTH_CLIENT_SECRET: $(BOOST_LLM_OAUTH_CLIENT_SECRET)
        BOOST_LLM_OAUTH_SCOPE: $(BOOST_LLM_OAUTH_SCOPE)
        BOOST_LLM_API_KEY_HEADER: $(BOOST_LLM_API_KEY_HEADER)
        PAYLOAD: ${{ parameters.payload }}

Warning

Map the variables in env, not with export BOOST_LLM_BASE_URL=$(BOOST_LLM_BASE_URL) lines in the script. In a script, a variable missing from the group stays as the text $(BOOST_LLM_BASE_URL), which bash runs as a command.

The sample advisor pipeline already declares the gateway variables in the envVariables of its Run Boost Advisor step. Each one reads a project variable and passes an empty value when that variable isn't defined, which the advisor treats as not set. So you only create what your methods need:

  • Any gateway: create the BOOST_LLM_API_FORMAT project variable, set to openai, and the BOOST_LLM_BASE_URL project variable.
  • OAuth2 client credentials: create the BOOST_LLM_OAUTH_TOKEN_URL project variable, and optionally BOOST_LLM_OAUTH_SCOPE. Create the BOOST_LLM_OAUTH_CLIENT_ID and BOOST_LLM_OAUTH_CLIENT_SECRET secrets. For OAuth2 only, the BOOST_LLM_KEY secret isn't needed.
  • API key header: create the BOOST_LLM_API_KEY_HEADER project variable, and set the BOOST_LLM_KEY secret to the value of the header.

Harness doesn't fail the run on a secret that doesn't exist, but the value it passes is unpredictable. So the command of the step drops the OAuth2 client ID and secret when BOOST_LLM_OAUTH_TOKEN_URL is empty.

If your pipeline was created before, add these lines to the envVariables of the step:

# Optional LLM gateway variables: an undefined project variable is passed as empty, and the advisor ignores it
BOOST_LLM_API_FORMAT: <+<+variable.BOOST_LLM_API_FORMAT> == null?"":variable.BOOST_LLM_API_FORMAT>
BOOST_LLM_BASE_URL: <+<+variable.BOOST_LLM_BASE_URL> == null?"":variable.BOOST_LLM_BASE_URL>
BOOST_LLM_OAUTH_TOKEN_URL: <+<+variable.BOOST_LLM_OAUTH_TOKEN_URL> == null?"":variable.BOOST_LLM_OAUTH_TOKEN_URL>
BOOST_LLM_OAUTH_SCOPE: <+<+variable.BOOST_LLM_OAUTH_SCOPE> == null?"":variable.BOOST_LLM_OAUTH_SCOPE>
BOOST_LLM_API_KEY_HEADER: <+<+variable.BOOST_LLM_API_KEY_HEADER> == null?"":variable.BOOST_LLM_API_KEY_HEADER>
# OAuth2 client credentials: the command drops them when BOOST_LLM_OAUTH_TOKEN_URL is empty
BOOST_LLM_OAUTH_CLIENT_ID: <+secrets.getValue('BOOST_LLM_OAUTH_CLIENT_ID')>
BOOST_LLM_OAUTH_CLIENT_SECRET: <+secrets.getValue('BOOST_LLM_OAUTH_CLIENT_SECRET')>

Then add these lines to its command, right after set -e:

# OAuth2 needs the token URL and both client secrets together: without the URL, drop them
if [ -z "$BOOST_LLM_OAUTH_TOKEN_URL" ]; then unset BOOST_LLM_OAUTH_CLIENT_ID BOOST_LLM_OAUTH_CLIENT_SECRET BOOST_LLM_OAUTH_SCOPE; fi

The same form makes any project variable optional: <+<+variable.NAME> == null?"":variable.NAME>.


Configuration Errors


When the variables don't fit together, the advisor run fails in your pipeline with one of these messages:

Message Cause
token is required No gateway is set, and BOOST_LLM_KEY isn't set either.
oauth_* and api_key_header require api_format OAuth2 or API key variables are set, but BOOST_LLM_API_FORMAT isn't.
api_format requires an https base_url BOOST_LLM_BASE_URL isn't set, or doesn't start with https://.
oauth_token_url must be https BOOST_LLM_OAUTH_TOKEN_URL doesn't start with https://.
oauth_token_url requires oauth_client_id and oauth_client_secret The token URL is set without the client ID and the client secret.
oauth_* requires oauth_token_url The client ID, the client secret or the scope is set without the token URL.
api_key_header must be a valid HTTP header name BOOST_LLM_API_KEY_HEADER isn't a valid header name.
api_key_header requires token BOOST_LLM_API_KEY_HEADER is set without BOOST_LLM_KEY.
api_format requires oauth_token_url or api_key_header A gateway is set, with no authentication method.
only one auth method may set Authorization OAuth2 is set, and BOOST_LLM_API_KEY_HEADER is Authorization.