Keep flow agent references at least as visible as the flow

To run the whole chain locally: gitlab poc/ai-catalog-subagents-stack, ai-assist poc/ai-catalog-subagents, gitlab-lsp poc/ai-catalog-subagents. Each branch stacks the open MRs of that repository plus the pins the chain waits on (Workhorse gopb, the 0.1.70 Node client, a 9.25.0-poc Duo CLI build).

What does this MR do and why?

A flow can only reference agents that are at least as visible as the flow itself. Without this, a public flow could reference a private or restricted agent, and most people who can see the flow would not be able to run it.

  • Private flow: private agents (in the flow's own project), restricted agents (in the flow's top-level group), or public agents
  • Restricted flow: restricted agents (in the flow's top-level group) or public agents
  • Public flow: public agents only

Making an existing flow more visible checks its saved references too, so changing only the visibility does not get around the rule.

This was raised in review on !258326 (merged), and it is split out to keep that MR under the size limit. It targets master and depends on !258326 (merged), so approvals survive when the base merges. Everything is behind the ai_catalog_flow_agent_references feature flag.

User docs for this behaviour are in !259499, which can merge on its own.

References

Database

The resolver now loads all referenced items in one query and all referenced versions in another, instead of two queries per reference. Both are bounded by ReferenceLimits at 20 references per flow. The root ancestor of each agent's project is preloaded with the existing ProjectRootAncestorPreloader.

Plans from postgres.ai (gitlab-production-main), session #60540, with 15 real agent references:

SELECT "ai_catalog_items".* FROM "ai_catalog_items" WHERE "ai_catalog_items"."id" IN (1016011, 1016010, ...)

1.6 ms, 16 buffer hits: index scan on the primary key, actual rows=15.

SELECT "ai_catalog_item_versions".* FROM "ai_catalog_item_versions"
WHERE ("ai_catalog_item_versions"."ai_catalog_item_id" = 1016011 AND "ai_catalog_item_versions"."version" = '1.0.0'
  OR "ai_catalog_item_versions"."ai_catalog_item_id" = 1016010 AND "ai_catalog_item_versions"."version" = '1.0.0'
  OR ... 15 pairs total)

0.1 ms, 37 buffer hits: bitmap scan on index_ai_catalog_item_versions_on_ai_catalog_item_id_and_id, actual rows=15, 5 rows removed by the version filter.

The delete_all and bulk_insert! on ai_catalog_item_version_dependencies come from !258326 (merged), and their plans are in that MR.

How to set up and validate locally

bundle exec rspec ee/spec/services/ai/catalog/flows/reference_resolver_spec.rb ee/spec/services/ai/catalog/flows/update_service_spec.rb
Edited by Angus Ryer

Merge request reports

Loading
Loading