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
| Property | Returns | Description |
|---|---|---|
| agentDefTimerUnits | Map<String,String> | The available timer units for use in an agent definition timer, such as minutes, hours and days. |
| agentService | AgentService | The service AgentManager delegates agent definition parsing, timer calculation, buffered-event bookkeeping and agent execution to. |
| modelTiers | List<String> | The model tiers a handler may ask for, for populating a picker. |
| reasoningEfforts | Map<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.
| Parameter | Description |
|---|---|
agent | the 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.
| Parameter | Description |
|---|---|
agent | the agent |
timerName | timer name |
findTimer(Agent agent, String timerName)
Returns: AgentDefTimer
Find a specific timer by name for an agent (including overrides)
| Parameter | Description |
|---|---|
agent | the agent |
timerName | the timer name |
findAllTimers(Agent agent)
Returns: List<AgentDefTimer>
Find all timers for an agent (including overrides)
| Parameter | Description |
|---|---|
agent | the 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.
| Parameter | Description |
|---|---|
agent | the agent to add the timer override to |
override | the 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.
| Parameter | Description |
|---|---|
agent | the agent |
timerName | the 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.
| Parameter | Description |
|---|---|
timerName | the 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.
| Parameter | Description |
|---|---|
eventName | the name of the platform event this handler reacts to |
findTimerOverrides(Agent agent)
Returns: List<AgentDefTimer>
Find all timer overrides for an agent
| Parameter | Description |
|---|---|
agent | the 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.
| Parameter | Description |
|---|---|
agent | the 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.
| Parameter | Description |
|---|---|
agentDef | the agent definition to create the agent from |
owner | the 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.
| Parameter | Description |
|---|---|
id | the agent's id |
findAgentsForUser(Profile owner)
Returns: List<Agent>
Finds all agents, across every agent definition, that run as the given owner.
| Parameter | Description |
|---|---|
owner | the profile to find agents for |
findAgentsForUser(String agentDefName, Profile owner)
Returns: List<Agent>
Finds the owner's agents for one specific agent definition.
| Parameter | Description |
|---|---|
agentDefName | the agent definition name to filter by |
owner | the profile to find agents for |
findAgents(String agentDefName)
Returns: List<Agent>
Finds every agent, across all owners, created from the named agent definition.
| Parameter | Description |
|---|---|
agentDefName | the 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.
| Parameter | Description |
|---|---|
name | the 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.
| Parameter | Description |
|---|---|
id | the 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.
| Parameter | Description |
|---|---|
agent | the agent the workflow runs against |
w | the 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.
| Parameter | Description |
|---|---|
agentDefs | the 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.
| Parameter | Description |
|---|---|
name | the 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.
| Parameter | Description |
|---|---|
name | the 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.
| Parameter | Description |
|---|---|
name | the 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.
| Parameter | Description |
|---|---|
names | which 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.
| Parameter | Description |
|---|---|
agentDef | the 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.
| Parameter | Description |
|---|---|
name | the 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.
| Parameter | Description |
|---|---|
agentDefName | the 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.
| Parameter | Description |
|---|---|
agentDefName | the definition's name, with or without the .xml suffix |
handlers | the 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.
| Parameter | Description |
|---|---|
name | the event to listen for: a FunnelEvent class name, or the trigger id of an event an app fires |
instructions | what the agent should do when it fires |
scope | null to match every event, or SCOPE_CUST_PROFILE to match only events about the agent owner |
bufferSecs | buffer matching events for up to this many seconds before running, or null for the default |
bufferSize | buffer 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.