BE - Simplifying agent/flow enablement: Iteration 1 - Bulk-select individual projects (async)
> [!note]
> This is the backend issue, see https://gitlab.com/gitlab-org/gitlab/-/work_items/600526 for the corresponding front end issue.
### Problem
* Users who are members of many (hundreds of) GitLab groups and projects currently have no easy way to enable an agent/flow across multiple projects at once.
* The existing picker is a single-select dropdown requiring opening the modal and selecting a project, then clicking Enable individually.
* This makes bulk rollout of agents and flows impractical at enterprise scale.
### Agreed Implementation Plan
Based on discussion in this issue, we are **skipping** the "frontend looping over the existing backend endpoint" quick-win approach due to its limitations (page navigation interrupts processing, poor experience at scale, no async support). Instead, we will implement this in two meaningful UX iterations backed by a proper async backend mutation.
### Steps
* Create a GraphQL mutation for batch enablement (Done https://gitlab.com/gitlab-org/gitlab/-/merge_requests/236521#whats-remaining)
* Fix permission rules as described in https://gitlab.com/gitlab-org/gitlab/-/work_items/601333
* Catch and log errors when creating the consumers fails
* Do not treat "already exists" as an error
* Email a report of the results https://gitlab.com/gitlab-org/gitlab/-/merge_requests/238315
* Restrict all operations to a single organization https://gitlab.com/gitlab-org/gitlab/-/merge_requests/238468
* Enable feature flag
* Remove feature flag
#### Iteration 1 — MVC: Bulk-select individual projects (async)
**What:**
* Replace the single-select project dropdown in the "Enable agent in a project" modal with a **multi-select picker** that supports bulk selection of individual projects (For now, we'll limit the endpoint to 100 projects, to prevent scaling issues).
* Backed by a **new backend GraphQL mutation** that processes enablements **asynchronously** (via Sidekiq), so users can navigate away from the page after submitting.
* User is **emailed the results** (successes and any failures) when async processing completes — consistent with how GitLab handles other bulk async operations.
* This respects the existing Maintainer+ permission rules for who can enable agents/flows.
**Limitations of this iteration (resolved in Iteration 2):**
* No group-level control — enablement is always per-project (individual records created for each project).
* New projects added to a group after bulk enablement will **not** automatically inherit the enablement.
**Where:**
* On [https://gitlab.com/explore/ai-catalog](https://gitlab.com/explore/ai-catalog/agents/)
* Project-level enablement remains focused on the individual project — no cross-project enablement from the project page.
**Designs:** https://www.figma.com/design/VqpH0V6joIOokfeXS71Yqz/Duo-Agent-Platform-Side-Panel?node-id=17416-14844&t=0VQ2Dz2STdZEvfNe-0 Note: as mentioned above, the UI will only allow per-project enablement not the group enablement in the design. Group enablement aspect of the UI will be done in https://gitlab.com/gitlab-org/gitlab/-/work_items/600203.
**UX requirements:**
* Multi-select with checkboxes per project row. Selections persist across search queries.
* **Stable selected-items list** shown outside of search results so users can audit and deselect items without losing track of their selection (e.g. show up to \~25 selected items, then "+N more").
* **Selection counter** — a persistent badge showing the running count of selected projects (e.g. "12 selected"). This is important given the security-sensitive nature of the action.
* Select all / Deselect all buttons — if the user has filtered by search, "Select all" selects only the filtered results (making it easy to select all projects in a namespace by searching the namespace name and hitting Select all).
| Current | Proposed |
|---------|----------|
| {width="617" height="600"} | {width=774 height=593} |
**API support:** GraphQL API support comes for free as part of the new backend mutation, which also benefits power users who prefer scripting bulk operations.
---
#### Iteration 2 — MVC+1: Group-level enablement via proper inheritance
Iteration 2 will be implemented in a separate issue https://gitlab.com/gitlab-org/gitlab/-/work_items/600203.
---
### Out of Scope (for now)
* **"All projects you maintain" one-click option** — dropped. Without the ability to deselect specific projects it is an all-or-nothing option, which is worse than multi-select. It also requires backend changes and exacerbates async processing concerns.
* **CSV upload / bulk API** — valid power-user feature but separate from this issue. GraphQL API support from the new mutation partially addresses this.
* **Partial trigger override at project level** — omitted for simplicity in the first pass of group-level inheritance.
### Related
* https://gitlab.com/gitlab-org/gitlab/-/work_items/553912 — Group-level inheritance/management (prerequisite for Iteration 2)
* https://gitlab.com/gitlab-org/gitlab/-/work_items/596188 — Customer feedback: agents not usable across intended groups/projects
issue