Admin Control To Disable External Agents
What does this MR do and why?
This MR introduces a setting to control the availability of AI catalog external agents at the instance or top-level group level. When external agents are disabled, they become inaccessible to users.
A few things to note:
- The setting defaults to
true, so there is no impact on existing external agents. - There is no UI for this setting yet, so it cannot be toggled from the frontend. See the verification section below for testing instructions.
- This MR includes both database and policy changes. I've decided to keep them together in a single MR, rather than splitting them out as we did for custom flows and agents.
For reference, here's how we handled similar implementations for custom flows and agents:
- Database changes MR for custom flow and agent - !231887 (merged)
- Policy enforcement change for custom flow - !232698 (merged)
- Policy enforcement change for custom agents - !233219 (merged)
- Issue - #594615 (closed)
Cascading Settings
To implement cascading settings, we can use the add_cascading_namespace_setting helper method in the migration. By default, this would add 2 columns (duo_external_agents_enabled and lock_duo_external_agents_enabled) to both namespace_settings and application_settings.
However, the application_settings table is already becoming quite wide with many columns. To avoid adding more columns there, we can leverage the existing duo_settings JSONB column and store these new settings as keys within it.
That said, for namespace_settings, we still need to add these as individual columns to take advantage of the cascading_attr helper.
DB changes for Cascading Settings
Added 2 new columns to the namespace_settings table:
- duo_external_agents_enabled
- lock_duo_external_agents_enabled
Added 2 new keys to the existing duo_settings JSONB column in application_settings:
- duo_external_agents_enabled
- lock_duo_external_agents_enabled
References
How to set up and validate locally
Prerequisites
TOKEN="<personal-access-token-of-owner-user-of-TLG>"
BASE_URL="http://gdk.test:3000"Step 1: Check TLG Setting
Verify the default state in Rails console:
top_level_group = Group.find_by_full_path('gitlab-duo') # Namespace setting
top_level_group.namespace_settings.duo_external_agents_enabled # => true (default)
cs = Gitlab::CurrentSettings.current_application_settings # Instance setting
cs.duo_external_agents_enabled # => true (default)Step 2: Disable External Agents via API
curl --request PUT \
--header "PRIVATE-TOKEN: $TOKEN" \
--header "Content-Type: application/json" \
--data '{ "duo_external_agents_availability": false }' \
"$BASE_URL/api/v4/groups/gitlab-duo"Verify the cascade in Rails console:
top_level_group.reload.namespace_settings.reload.duo_external_agents_enabled # => falseCheck the audit log at GitLab Duo > Secure > Audit Events to confirm the change was recorded. Re-enabling the setting will trigger an additional audit event.
Step 3: Verify External Agents Are Disabled
Navigate to Automate > Agents:
- Enabled tab: External agents should not appear here
- Managed tab: External agents created in the project are still visible
- External agent details page: Users cannot perform actions on disabled agents (only report the agent).
- Known issue: The "Enable" and "New Agent" buttons remain visible but non-functional (error on click). Frontend changes needed to hide these buttons
Step 4: Verify External Agents Can Not be Triggered
NOTE: Currently error is just being return and note is not being created so we can't see that. This is existing issue and there is MR which fix this.
Step 5: Disable External Agents at Instance Level
Disable the instance-level setting via API:
Note: For below you need to use admin user's PAT.
curl --request PUT \
--header "PRIVATE-TOKEN: $A_TOKEN" \
--header "Content-Type: application/json" \
--data '{ "duo_external_agents_availability": false }' \
"$BASE_URL/api/v4/application/settings"Restart the Rails console to ensure the application changes are fully loaded:
cs = Gitlab::CurrentSettings.current_application_settings
cs.duo_external_agents_enabled # => falseVerify the change in the audit log at Admin > Monitor > Audit Events.
Step 6: Verify Cascade Lock Behavior
Once the instance-level setting is disabled, group-level settings cannot be changed. Attempting to enable the setting at the group level will return an error:
curl --request PUT \
--header "PRIVATE-TOKEN: $TOKEN" \
--header "Content-Type: application/json" \
--data '{ "duo_external_agents_availability": true }' \
"$BASE_URL/api/v4/groups/gitlab-duo"RESPONSE:
{"message":{"namespace_settings.duo_external_agents_enabled":["cannot be changed because it is locked by an ancestor"]}}Important: Even if external agents are enabled at the top-level group, they will not be accessible if disabled at the instance level. The instance-level setting takes precedence and locks all descendant namespaces.
Testing Notes
- Use an owner or maintainer account for testing
- Do not test with the root user``
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #594615 (closed)





