Resolve AI Catalog agent references at flow save time
To run the whole chain locally: gitlab
poc/ai-catalog-subagents-stack, ai-assistpoc/ai-catalog-subagents, gitlab-lsppoc/ai-catalog-subagents. Each branch stacks the open MRs of that repository plus the pins the chain waits on (Workhorsegopb, the 0.1.70 Node client, a9.25.0-pocDuo CLI build).
What does this MR do and why?
Save-time resolution for flow YAML include field references (which is MR 2 and 4 of the plan on #628153 (closed)).
For each reference:
- The item and pinned version must exist.
- The saving user needs
read_ai_catalog_item. - The item's visibility must permit the reference (private: same project, restricted: same root group).
- The reference count is checked against
ReferenceLimits. - Resolved references are written as
ItemVersiontoItemVersiondependency rows with the exact pin
The save-time methods live in a new Ai::Catalog::Concerns::AgentReferences concern instead of FlowHelper, which !256807 (merged) deleted as dead code. Turned out we could have kept it, but this may be more semantically precise
User docs for this behaviour are in !259499, which can merge on its own.
References
- Issue: #628153 (closed)
- Parent epic: &23526 (closed)
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/create_service_spec.rb \
ee/spec/services/ai/catalog/flows/update_service_spec.rbDatabase
persist_agent_references replaces a flow version's dependency rows on every save: one relation delete_all, then one bulk_insert!. Both are bounded by ReferenceLimits at 20 rows per flow version.
Plans from postgres.ai (gitlab-production-main), session #59200. The table is empty in production (the feature is unreleased), so the clone was prepared first: the schema from !256807 (merged) (now merged, at the time not yet) was applied via exec (the dependency_version_id column, both indexes, and the composite FK), then 10,000 rows were seeded as 500 flow versions with 20 agent references each, the per-flow ceiling. The applied schema matches what !256807 (merged) merged, so the plans hold for master.
DELETE, 20 rows:
DELETE FROM "ai_catalog_item_version_dependencies"
WHERE "ai_catalog_item_version_dependencies"."ai_catalog_item_version_id" = 10.7 ms, 27 buffer hits: index scan on idx_ai_catalog_item_version_dependencies_version_and_dependency, actual rows=20.
INSERT, 20 rows (one multi-row statement from bulk_insert!):
INSERT INTO "ai_catalog_item_version_dependencies"
("ai_catalog_item_version_id","dependency_id","dependency_version_id","organization_id")
VALUES (1030784, 1015864, 1030734, 1), ... 20 tuples total4.3 ms, 371 buffer hits: Values Scan plus the four FK trigger checks, 20 calls each.