Class AgentRuleDispatcher

java.lang.Object
com.xebialabs.xlrelease.agentrules.AgentRuleDispatcher

public class AgentRuleDispatcher extends Object
The agentic-triggers engine: matches every domain event against the user-authored agentic.Rule configurations and dispatches the configured AI agent for each match, posting the agent's analysis back where the event happened (a task comment, when the event carries a task) and recording every firing in the run history.

A rule without a flow is advise-only: the analysis lands as a comment. A rule with a flow classifies the agent's answer into the author's outcome vocabulary and executes the matched branch's actions (AgentRuleFlow) — each action isolated, each carrying its own autonomy mode: auto executes immediately; propose parks an AgentRuleProposal for one-click human approval, and executeApproved(com.xebialabs.xlrelease.agentrules.AgentRuleProposal, java.lang.String, java.lang.String) runs it attributed to the approver.

Rules are ordinary shared configurations, so authoring needs no restart: the rule set is cached and invalidated on any configuration change event. A rule's optional conditions (folder prefix, release-title pattern, task type, tags) are AND-ed; empty conditions match.

Design constraints this class must respect (structural, not stylistic):

  • The event bus swallows handler exceptions, so every failure here surfaces itself explicitly: agent-call failures become a short comment on the task and a failed run in the history, never silence.
  • @AsyncSubscribe handlers share the bus's default executor, so the handler only filters and captures, then hands the slow agent round trip (an LLM turn — minutes, not millis) to this feature's own executor.
  • Events fire on the node that owns the release actor, which gives exactly-once dispatch in a cluster for free.
  • Failure storms must not become agent storms: a per-rule-per-entity debounce, a per-release run budget, and a per-rule circuit breaker (consecutive agent failures pause the rule) cap the blast radius.
  • All outbound policy lives in the gateway: the A2A feature toggle and agent allowlist are enforced by A2aAgentGateway, so a rule cannot reach a non-allowlisted agent by construction.
  • No feedback loops: the comments this class writes are system comments (null author), and CommentCreatedEvents without an author are never matched against rules.

Everything read from a CI attached to an event is copied to plain strings before the executor hand-off — the event's Task/Release are not thread-safe and must not cross threads.

  • Constructor Summary

    Constructors
    Constructor
    Description
    AgentRuleDispatcher(com.xebialabs.xlrelease.events.XLReleaseEventBus eventBus, org.springframework.beans.factory.ObjectProvider<com.xebialabs.xlrelease.a2a.api.A2aAgentGateway> gatewayProvider, com.xebialabs.xlrelease.service.CommentService commentService, com.xebialabs.xlrelease.repository.ConfigurationRepository configurationRepository, com.xebialabs.xlrelease.config.XlrConfig xlrConfig, AgentRuleRunStore runStore, AgentRuleProposalStore proposalStore, com.xebialabs.xlrelease.actors.ReleaseActorService releaseActorService, com.xebialabs.xlrelease.repository.ReleaseRepository releaseRepository, com.xebialabs.xlrelease.service.VariableService variableService, AgentRuleTokenService tokenService, ExecutorService executor)
     
  • Method Summary

    Modifier and Type
    Method
    Description
    executeApproved(AgentRuleProposal proposal, String username, String subjectToken)
    Executes a proposal a human just approved.
    void
    onConfigurationChanged(com.xebialabs.xlrelease.domain.events.ConfigurationEvent event)
    Any configuration change may be a rule change; the snapshot is cheap to rebuild lazily.
    void
    onEvent(com.xebialabs.xlrelease.domain.events.XLReleaseEvent event)
     
    void
     
    void
     

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • AgentRuleDispatcher

      public AgentRuleDispatcher(com.xebialabs.xlrelease.events.XLReleaseEventBus eventBus, org.springframework.beans.factory.ObjectProvider<com.xebialabs.xlrelease.a2a.api.A2aAgentGateway> gatewayProvider, com.xebialabs.xlrelease.service.CommentService commentService, com.xebialabs.xlrelease.repository.ConfigurationRepository configurationRepository, com.xebialabs.xlrelease.config.XlrConfig xlrConfig, AgentRuleRunStore runStore, AgentRuleProposalStore proposalStore, com.xebialabs.xlrelease.actors.ReleaseActorService releaseActorService, com.xebialabs.xlrelease.repository.ReleaseRepository releaseRepository, com.xebialabs.xlrelease.service.VariableService variableService, AgentRuleTokenService tokenService, ExecutorService executor)
  • Method Details

    • subscribe

      @PostConstruct public void subscribe()
    • unsubscribe

      @PreDestroy public void unsubscribe()
    • onConfigurationChanged

      public void onConfigurationChanged(com.xebialabs.xlrelease.domain.events.ConfigurationEvent event)
      Any configuration change may be a rule change; the snapshot is cheap to rebuild lazily.
    • onEvent

      public void onEvent(com.xebialabs.xlrelease.domain.events.XLReleaseEvent event)
    • executeApproved

      public String executeApproved(AgentRuleProposal proposal, String username, String subjectToken)
      Executes a proposal a human just approved. Called on the approver's request thread, so the ambient authenticated identity is the approver — retry/skip are attributed to them, which is exactly the audit trail an approval should leave. The slow delegation action is the one exception: it is handed to this feature's executor and reports back as a comment.
      Parameters:
      subjectToken - the approver's own access token (nullable), captured on their request thread; when the RFC 8693 exchange is configured, the delegated agent then runs on the approver's identity instead of the service account
      Returns:
      a short human-readable result for the approval response