Add groundwork for starting flows from a chat slash command

What does this MR do and why?

I'm out of office until 10 September, so replies to review comments will be slow. The change is small and self-contained, so please do merge it without me if you're happy with it.

Groundwork for starting an AI Catalog flow from a Duo Agentic Chat slash command (#605161). Three things that have to exist before that feature can be turned on, none of which do anything on their own.

An AI Catalog flow can only run today if a trigger is attached to it, so a flow like a repository-wide scan has no sensible way to be started at all. The work to offer one slash command per flow enabled in a project is behind duo_chat_flow_commands, declared here so the pieces can land ahead of it.

The presenter change is the part worth reading

Starting a flow means telling the Duo Workflow Service which flow to run. The identifier travels as an additional context item under a duo_chat_command category, because a dedicated field on the start request would not survive Workhorse — it decodes client events with protojson and DiscardUnknown, so it drops fields it does not know about. There is precedent for internal categories used this way in orbit_context and permissions_form_context.

That category is machine addressing rather than user context, so it is not in AiAdditionalContextCategory and never should be. But:

  • the gateway writes additional_context verbatim into the checkpoint's ui_chat_log
  • WorkflowCheckpointEventPresenter serialises those items into AiAdditionalContext, whose category is a null: false enum over a fixed list
  • so an unlisted category does not fail its own item, it fails the whole duoMessages field
  • and the checkpoint keeps it, so that session never reads back again

Listing it in INTERNAL_CONTEXT_CATEGORIES strips it on read instead. That is also what keeps it from rendering as a context chip the user never added.

Adding it now rather than alongside the code that produces it means the guard is in place first, and the ordering between the monolith and the gateway stops mattering.

How to set up and validate locally

There is nothing user-facing to see: the flag is off, and nothing produces the category yet.

  1. bundle exec rspec ee/spec/presenters/ai/duo_workflows/workflow_checkpoint_event_presenter_spec.rb
  2. Confirm duo_chat_flow_commands shows up at /rails/features and is off.

To see the guard doing its job, the new spec case is the direct demonstration: a ui_chat_log message carrying a duo_chat_command item keeps its other context and drops that one. Reverting the one-line constant change makes it fail.

What comes next

The rest is split into three follow-ups, all frontend, tracked on !252540 (closed) which has the full plan and the working end-to-end version:

  1. Lazy resolution and a store for resolved slash commands
  2. A dispatch capability, so a command can act on the turn it starts
  3. The flow_commands plugin itself

The AI Gateway half is ai-assist!6690.

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.

Merge request reports

Loading
Loading