Owns AI agent definitions and the Agent instances, timers and event handlers built from them. An agent definition (AgentDef) is XML, either supplied by an app or authored by a tenant; this class resolves the combined definition for an agent, creates and initialises Agent records, computes and stores timer schedules (including per-agent overrides), and buffers matching platform events until an event handler's firing criteria is met, at which point it fires an execute-agent event for the JS side to act on. Most of its methods are exported to GraalJS as the agent API app developers script against.

Group: Managers

Implements: Stoppable


Properties

PropertyReturnsDescription
agentDefTimerUnitsMap<String,String>The available timer units for use in an agent definition timer, such as minutes, hours and days.
agentServiceAgentServiceThe service AgentManager delegates agent definition parsing, timer calculation, buffered-event bookkeeping and agent execution to.
modelTiersList<String>The model tiers a handler may ask for, for populating a picker.
reasoningEffortsMap<String,String>The reasoning efforts a handler may ask for, for populating a picker.

Methods

getAgentService() · nextTimers(Agent agent) · executeAgentTimer(Agent agent, String timerName) · findTimer(Agent agent, String timerName) · findAllTimers(Agent agent) · putTimerOverride(Agent agent, AgentDefTimer override) · deleteTimerOverride(Agent agent, String timerName) · newAgentDefTimer(String timerName) · newAgentDefEventHandler(String eventName) · findTimerOverrides(Agent agent) · initAgent(Agent agent) · createAgent(AgentDef agentDef, Profile owner) · findAgentById(long id) · findAgentsForUser(Profile owner) · findAgentsForUser(String agentDefName, Profile owner) · findAgents(String agentDefName) · findAllAgentDefs() · findAgentDef(String name) · findAgentWorkflowById(long id) · startWorkflow(Agent agent, AgentWorkflowDef w) · deleteAgentDefs(List<AgentDef> agentDefs) · removeRedundantAgentDefOverrides() · isProvidedAgentDef(String name) · isOverriddenAgentDef(String name) · isSupersededAgentDef(String name) · removeSupersededAgentDefOverrides(List<String> names) · newAgentDefBuilder() · saveAgentDef(AgentDef agentDef) · findProvidedAgentDef(String name) · findAccountEventHandlers(String agentDefName) · saveAccountEventHandlers(String agentDefName, List<AgentDefEventHandler> handlers) · newEventHandler(String name, String instructions, String scope, Integer bufferSecs, Integer bufferSize) · getModelTiers() · getReasoningEfforts() · getAgentDefTimerUnits()

getAgentService()

Returns: AgentService

The service AgentManager delegates agent definition parsing, timer calculation, buffered-event bookkeeping and agent execution to.

nextTimers(Agent agent)

Returns: Map<String,Date>

The date each of the agent's timers will next fire, keyed by timer name. Computed from the agent's stored next-timers state.

ParameterDescription
agentthe agent whose timer schedule to read

executeAgentTimer(Agent agent, String timerName)

Returns: void

Executes the named timer for the agent immediately, as if it had fired on schedule. Used for testing and simulating timer events.

ParameterDescription
agentthe agent
timerNametimer name

findTimer(Agent agent, String timerName)

Returns: AgentDefTimer

Find a specific timer by name for an agent (including overrides)

ParameterDescription
agentthe agent
timerNamethe timer name

findAllTimers(Agent agent)

Returns: List<AgentDefTimer>

Find all timers for an agent (including overrides)

ParameterDescription
agentthe agent

putTimerOverride(Agent agent, AgentDefTimer override)

Returns: void

Adds or replaces a per-agent override for one of the agent definition's timers, then recalculates the agent's combined timer schedule and saves it. Overriding is only permitted when the agent definition allows it.

ParameterDescription
agentthe agent to add the timer override to
overridethe timer override to store

deleteTimerOverride(Agent agent, String timerName)

Returns: void

Removes an existing per-agent timer override, then recalculates and saves the agent's combined timer schedule.

ParameterDescription
agentthe agent
timerNamethe timer name

newAgentDefTimer(String timerName)

Returns: AgentDefTimer

Creates a new, otherwise-empty AgentDefTimer with the given name, for use with its builder-style setters before adding it to an agent definition.

ParameterDescription
timerNamethe timer name

newAgentDefEventHandler(String eventName)

Returns: AgentDefEventHandler

Creates a new, otherwise-empty AgentDefEventHandler for the given event name, for use with its builder-style setters before adding it to an agent definition.

ParameterDescription
eventNamethe name of the platform event this handler reacts to

findTimerOverrides(Agent agent)

Returns: List<AgentDefTimer>

Find all timer overrides for an agent

ParameterDescription
agentthe agent

initAgent(Agent agent)

Returns: void

Re-initialises an agent against its current agent definition: recalculates its timer schedule and saves it. Called after an agent's definition may have changed.

ParameterDescription
agentthe agent to re-initialise

createAgent(AgentDef agentDef, Profile owner)

Returns: Agent

Creates and saves a new Agent for the given owner from the given agent definition, initialises its timer schedule, and records a telemetry event for the account.

ParameterDescription
agentDefthe agent definition to create the agent from
ownerthe profile the agent will run as

findAgentById(long id)

Returns: Agent

Looks up an agent by its database id, within the current tenant's admin organisation.

ParameterDescription
idthe agent's id

findAgentsForUser(Profile owner)

Returns: List<Agent>

Finds all agents, across every agent definition, that run as the given owner.

ParameterDescription
ownerthe profile to find agents for

findAgentsForUser(String agentDefName, Profile owner)

Returns: List<Agent>

Finds the owner's agents for one specific agent definition.

ParameterDescription
agentDefNamethe agent definition name to filter by
ownerthe profile to find agents for

findAgents(String agentDefName)

Returns: List<Agent>

Finds every agent, across all owners, created from the named agent definition.

ParameterDescription
agentDefNamethe agent definition name

findAllAgentDefs()

Returns: List<AgentDef>

All agent definitions available to the current tenant: those supplied by installed apps and any authored or overridden by the tenant, merged.

findAgentDef(String name)

Returns: AgentDef

Looks up a single agent definition by name, combining any tenant override with the app-supplied definition.

ParameterDescription
namethe definition name, with or without the .xml suffix

findAgentWorkflowById(long id)

Returns: AgentWorkflow

Looks up an agent workflow instance by its database id, within the current tenant's admin organisation.

ParameterDescription
idthe workflow's id

startWorkflow(Agent agent, AgentWorkflowDef w)

Returns: AgentWorkflow

Starts a new run of the given workflow definition for the agent, positioned at the workflow's first step.

ParameterDescription
agentthe agent the workflow runs against
wthe workflow definition to start

deleteAgentDefs(List<AgentDef> agentDefs)

Returns: void

Delete a list of AgentDefs. This will throw an exception if any of the AgentDefs are in use by any Agents. The in-use check applies only to definitions a tenant authored. For one an app supplies, deleting removes the tenant's copy and the definition carries on existing at the app's version, so agents using it are not orphaned, they go back to following the app. Refusing there would make resetting impossible for exactly the definitions worth resetting, since any of them in real use has agents.

ParameterDescription
agentDefsthe list of AgentDefs to delete

removeRedundantAgentDefOverrides()

Returns: int

Deletes stored definitions that say nothing their app does not already say. Every tenant has one of these: until now the only way an agent could exist was as a stored copy, so one was written on first use and rewritten on every app update. Left in place those copies would override the supplied definition forever, and nobody would receive an improvement to it again, which is the whole reason for supplying definitions in the first place. Only exact matches are removed, so a tenant who genuinely edited theirs keeps it, and keeps the authority that comes with it.

isProvidedAgentDef(String name)

Returns: boolean

Whether an app supplies a definition of this name. Matters to the admin UI: for a supplied definition the stored file is an override rather than the definition itself, so editing it only records what was changed, and deleting it resets to the app's version rather than removing the agent.

ParameterDescription
namethe definition name, with or without the {@code .xml} suffix

isOverriddenAgentDef(String name)

Returns: boolean

Whether an app supplies a definition of this name <i>and</i> this tenant has a stored copy that is currently in force. <p> Distinct from {@link #isProvidedAgentDef(String)}, which only says an app has a version: that is true both for a definition following the app and for one shadowing it. Only the second is an override, and the difference is worth showing - a tenant looking at an old copy of a definition the app has since improved has no way to tell from the definition itself, which is exactly how one gets left behind for months. Anything the app later adds - a new function, a corrected instruction, a flag that routes the agent through a new code path - silently does not arrive.

ParameterDescription
namethe definition name, with or without the {@code .xml} suffix

isSupersededAgentDef(String name)

Returns: boolean

Whether this tenant has a stored copy of an app-supplied definition that is <b>no longer taking precedence</b>, because it was saved against an older generation of the definition model. <p> Distinct from {@link #isOverriddenAgentDef(String)}, which reports an override that <i>is</i> winning. Both mean "there is a stored copy", and the difference is whether it is in force - which is exactly what an administrator looking at the page needs to be told, since a superseded copy looks identical to an active one from the outside.

ParameterDescription
namethe definition name, with or without the {@code .xml} suffix

removeSupersededAgentDefOverrides(List<String> names)

Returns: int

Removes stored copies of definitions this tenant never authored, for names an app now supplies. <p> Called on app update. {@link #removeRedundantAgentDefOverrides()} only removes copies byte-identical to what the app supplies now, which does not help the case this exists for: a copy written years ago against a definition that has since changed shape is not identical to anything, and is precisely the copy that has to go. Superseded copies no longer take precedence either way - see {@code AgentService.CURRENT_OVERRIDE_GENERATION} - so this is hygiene rather than correctness: it stops a dead file appearing in the admin UI as though it were configuration. <p> <b>Recoverable.</b> These live in the queries repository, which is versioned, so a removed definition can be read back out of repository history. The XML is also logged before removal, so what a tenant had is recorded even if nobody goes looking in the repo.

ParameterDescription
nameswhich definition names to clean up, with or without the {@code .xml} suffix. Deliberately an explicit list rather than "everything superseded": a sweep is worth doing for a definition whose shape has changed, and is not worth the blast radius for one that has not

newAgentDefBuilder()

Returns: AgentDefBuilder

Create a new AgentDefBuilder to build an AgentDef instance.

saveAgentDef(AgentDef agentDef)

Returns: void

Save an AgentDef to XML. Saved verbatim. Where an app supplies a definition of this name, the stored copy takes over from it completely and from then on is the definition, which is the point of overriding one: a tenant doing it to take something away needs the result to stay taken away.

ParameterDescription
agentDefthe AgentDef to save

findProvidedAgentDef(String name)

Returns: AgentDef

The definition an app supplies under this name, before any account override or addition is applied. Useful for telling what came from the app apart from what the account added, eg deciding whether removing an event handler means dropping the account's copy or disabling the app's.

ParameterDescription
namethe definition's name, with or without the .xml suffix

findAccountEventHandlers(String agentDefName)

Returns: List<AgentDefEventHandler>

The event handlers this account has added to a definition, over and above whatever the app supplies.

ParameterDescription
agentDefNamethe definition's name, with or without the .xml suffix

saveAccountEventHandlers(String agentDefName, List<AgentDefEventHandler> handlers)

Returns: void

Saves this account's own event handlers for a definition, replacing whatever it had. This is how an account subscribes an agent to one more event, changes what a supplied handler does, or takes one away, <b>without</b> taking a copy of the whole definition. A copy wins outright over the app's version and stops tracking it, so an account that forked to add one subscription would never receive another improvement to that agent's instructions, tools, specialists or model tier. Adding is not worth that. A handler whose name matches one the app supplies replaces it; one marked disabled removes it.

ParameterDescription
agentDefNamethe definition's name, with or without the .xml suffix
handlersthe handlers to keep; an empty list removes this account's additions entirely

newEventHandler(String name, String instructions, String scope, Integer bufferSecs, Integer bufferSize)

Returns: AgentDefEventHandler

Builds an event handler, for code assembling a list to hand to saveAccountEventHandlers.

ParameterDescription
namethe event to listen for: a FunnelEvent class name, or the trigger id of an event an app fires
instructionswhat the agent should do when it fires
scopenull to match every event, or SCOPE_CUST_PROFILE to match only events about the agent owner
bufferSecsbuffer matching events for up to this many seconds before running, or null for the default
bufferSizebuffer up to this many events before running, or null for the default

getModelTiers()

Returns: List<String>

The model tiers a handler may ask for, for populating a picker.

getReasoningEfforts()

Returns: Map<String,String>

The reasoning efforts a handler may ask for, for populating a picker.

getAgentDefTimerUnits()

Returns: Map<String,String>

The available timer units for use in an agent definition timer, such as minutes, hours and days.

To get full access to the Kademi Hub existing customers can login here, or new customers can register here.