GitLab Duo Integration

GitLab Duo Integration

Power GitLab Duo Chat and Code Suggestions with Ask Sage's FedRAMP-compliant AI models


Table of Contents
  1. Prerequisites
  2. Provider Surfaces
  3. Step 1: Discover Available Model IDs
  4. Step 2: Verify Your API Key
  5. Step 3: Add Self-Hosted Models in GitLab
  6. Step 4: Assign Models to Duo Features
  7. Step 5: Set the Request Timeout
  8. Step 6: Verify
  9. Troubleshooting
  10. Additional Resources

Instance-Specific Base URL: The endpoints shown reflect the instance at chat.asksage.ai. The api. prefix and path suffix stay the same across deployments — only the instance segment in the middle changes based on which Ask Sage instance you are logging into. Always use the instance approved by your organization and applicable regulatory requirements, and match the base URL in your configuration to the instance you authenticate against.


Prerequisites

Prerequisites

Before you begin, ensure you have the following:

Ask Sage Account

Sign up or log in

Ask Sage API Key

From your tenant under Account > API Keys

GitLab EE

With a Duo Enterprise license applied

AI Gateway

Running and reachable, e.g. http://aigw.local:5052/-/health

Provider Surfaces

Step 1: Discover Available Model IDs

Discover Available Model IDs

Ask Sage's available models depend on your subscription tier. Retrieve the list before configuring GitLab to confirm the model IDs your account can access:

curl -s https://api.asksage.ai/server/openai/v1/models \
  -H "Authorization: Bearer $ASK_SAGE_API_KEY" \
  | python -m json.tool | grep '"id"'

When you enter model IDs in GitLab, prefix each with the matching provider identifier prefix. For example, anthropic/claude-sonnet-4-6 for a Claude model, or custom_openai/gpt5 for a GPT model.

Common Models (verify availability against your account):
  • anthropic/claude-sonnet-4-6 — Anthropic Claude Sonnet 4.6
  • custom_openai/gpt5 — GPT-5
  • gemini/gemini-2.5-flash — Google Gemini 2.5 Flash

Step 2: Verify Your API Key


Step 3: Add Self-Hosted Models in GitLab

Step 4: Assign Models to Duo Features

Assign Models to Duo Features

Navigate to Admin > GitLab Duo > Configure models for GitLab Duo and assign each model you created to its corresponding feature.

Duo Feature Recommended model entry
Duo ChatAsk Sage — Duo Chat
Code generationAsk Sage — Code Generation
Code completionAsk Sage — Code Completion
Duo Workflow (agentic)Ask Sage — Duo Chat (or a dedicated model)
Unassigned Features: Features you do not assign default to the AI Gateway's cloud-connected path if licensed. For a fully self-hosted setup, assign a model to every feature you intend to use.

Step 5: Set the Request Timeout

Set the Request Timeout

GitLab's default 30-second timeout may be too short for slower models or long prompts.

Navigate to Admin > GitLab Duo > Change configuration > Request timeout and set a value appropriate for your use case:

Use case Recommended timeout
Fast models (GPT-4.1, Gemini Flash)60 seconds
Standard use120 seconds
Large prompts or slow models360 seconds

Step 6: Verify

Verify the Configuration

Health Check

Navigate to Admin > GitLab Duo > Run health check. This tests AI Gateway connectivity and confirms each configured model endpoint responds.

Rake Task

docker exec gitlab gitlab-rake "gitlab:duo:verify_self_hosted_setup[root]"

Live Chat Test

Open any GitLab project and open the Duo Chat panel in the sidebar. Send a message — a response should stream within a few seconds. If nothing appears, check the logs:

# AI Gateway — outbound requests to Ask Sage
docker logs gitlab-aigw 2>&1 | grep -i "asksage\|error" | tail -20

# Workhorse — WebSocket / gRPC errors
docker exec gitlab bash -c "tail -50 /var/log/gitlab/gitlab-workhorse/current"

Troubleshooting

Troubleshooting

Issue: Duo Chat produces no response — DAP service URL

On GitLab 19.2 and later, Workhorse reads the DAP service URL from ApplicationSetting, not Ai::Setting. If the value is only set on Ai::Setting, Workhorse reads nil and the WebSocket returns HTTP 500 with invalid target address "": missing address.

Diagnose:

docker exec gitlab gitlab-rails runner "
  puts 'AppSetting: ' + ApplicationSetting.current.duo_agent_platform_service_url.inspect
  fs = Ai::FeatureSetting.find_by(feature: :duo_agent_platform_agentic_chat)
  puts 'Workhorse sees: ' + Gitlab::DuoWorkflow::Client.url_for(feature_setting: fs, user: User.find_by(username: 'root')).inspect
"

Both values must print "gitlab-aigw:50052" — no URL scheme prefix. If either prints nil, set it:

docker exec gitlab gitlab-rails runner "ApplicationSetting.current.update!(duo_agent_platform_service_url: 'gitlab-aigw:50052', self_hosted_duo_agent_platform_service_secure: false)"
Issue: Chat fails with a TLS certificate error (online cloud license)

When the GitLab license is a subscription-based online cloud license, GitLab instructs Workhorse to open a billing tracking stream to duo-workflow-svc.runway.gitlab.net:443. In an isolated Docker environment, the TLS certificate cannot be verified, so Workhorse aborts the WebSocket before any message reaches the AI Gateway. The Workhorse log contains: failed to open self-hosted tracking stream ... x509: certificate signed by unknown authority.

Diagnose:

docker exec gitlab gitlab-rails runner '
  puts "online_cloud_license? = #{License.current&.online_cloud_license?}"
  puts "should_bill? = #{Ai::SelfHostedDapBilling.should_bill?(Ai::FeatureSetting.find_by(feature: :duo_agent_platform_agentic_chat))}"
'

If both print true, patch should_bill? to return false — this removes the cloud tracking stream from the Workhorse config. The patch survives gitlab-ctl restart but is lost on container recreation.

docker exec gitlab bash -c "sed -i 's/def self\.should_bill?(feature_setting)/def self.should_bill?(feature_setting)\n      return false # local-dev: cloud tracking stream disabled/' /opt/gitlab/embedded/service/gitlab-rails/ee/lib/ai/self_hosted_dap_billing.rb"
docker exec gitlab gitlab-ctl restart puma

Verify the patch applied:

docker exec gitlab bash -c "grep -A2 'def self.should_bill' /opt/gitlab/embedded/service/gitlab-rails/ee/lib/ai/self_hosted_dap_billing.rb"

Expected output: the line immediately after def self.should_bill? reads return false.

Issue: gRPC service not running on port 50052

The AI Gateway container image does not include ss or netstat. Check the startup log instead:

docker logs gitlab-aigw 2>&1 | grep -E "gRPC server on port 50052|Started server"

If the line is absent, the gRPC service did not start — often a JWKS-fetch race when the gateway started before GitLab was ready. Restart the gateway: docker restart gitlab-aigw

Issue: 429 / rate limit errors in AI Gateway logs

Ask Sage applies rate limits per API key. If you see 429s:

  • Check your Ask Sage account tier limits
  • Reduce concurrent Duo Chat sessions
  • Switch to a model with higher rate limits on your plan
Issue: Model identifier not found / 404

Solutions:

  • Verify the model ID exactly matches what /v1/models returns — model IDs are case-sensitive
  • Confirm the identifier prefix matches the provider surface (custom_openai/, anthropic/, or gemini/)
  • For Anthropic: enter the endpoint without /v1 — the AI Gateway appends it automatically
  • Confirm the model is available on your Ask Sage subscription tier

Additional Resources


Back to top

Copyright © 2026 Ask Sage Inc. All Rights Reserved. Ask Sage is a BigBear.ai company.