Execution state for one run of an Agent's gather, plan, act and verify loop, as driven by the AgentOrchestrator. The row holds only the small pointer and status fields needed to find, claim and resume a run. The payload - the plan so far, the tool call awaiting consent, budget counters - is not stored here; it lives as a JSON blob in content storage under agent-runs, and the LLM message history stays in ai-lib's conversation storage, referenced by the conversation id. State changes go through the claim, pause, complete, fail and expire transitions rather than by setting status directly, because the claim is what stops two processes from processing the same paused run. The entity is not exported to script code apart from rowId, so an app cannot drive or forge a run's state machine.
Group: Database Entities
Implements: Serializable, Relational
Properties
| Property | Returns | Description |
|---|---|---|
| adminOrg | Organisation | The tenant this run belongs to, copied from the agent when the run is created so the expiry sweep can filter by organisation without joining to the agent. Never null for a persisted run. |
| agent | Agent | The agent this run executes on behalf of. The agent's owner supplies the security context every phase of the run executes under. Never null for a persisted run. |
| awaitingSince | Date | |
| channel | String | Which channel this run reaches its owner through, given as the sourceApp identifier, for example Slack or admin-lib. The expiry sweep runs off a timer with no request and no conversation in hand, so this is what lets it announce an expiry back over the channel the consent request went out on. |
| chatItemId | String | The chat item carrying the consent block this run is waiting on, set when the run pauses for consent. This is a pointer only: the tool name, its arguments and the already-executed flag all live on that chat item, which is what the UI renders and what a resume validates against, so there is exactly one record of what was approved. |
| claimedAt | Date | |
| completedDate | Date | |
| conversationId | String | Opaque key into ai-lib's conversation storage holding the message history for this run. The messages themselves are not duplicated onto this row. Null for a run with no conversation behind it. |
| correlationToken | String | Opaque token generated when the run is created and embedded in outbound consent requests, so a reply arriving over an async channel can be matched back to this run. Unique across all runs and never null. |
| createdDate | Date | |
| currentPhase | String | Which step of the orchestrator loop this run has reached: gather, plan, act or verify, matching the PHASE constants on this class. A new run starts in gather. |
| expiresAt | Date | |
| id | long | Database identifier for this run, assigned when the run is first saved. |
| lastError | String | Short diagnostic message recorded when the run failed, truncated to 2000 characters. Null unless the run has failed. |
| modifiedDate | Date | |
| parentRun | AgentRun | The run which delegated to this one, when this run is a sub-agent. Null for a root run started directly rather than by delegation. |
| pendingSpecialist | String | The specialist whose delegated run asked for the gated call, when the consent request arose inside a delegation. This matters on resume rather than being merely descriptive: a specialist's tools are not in the delegating agent's own whitelist, so the approved call has to be re-delegated to that specialist instead of being run directly. |
| pendingToolId | String | The model's call id for the gated tool call, ie which request on the pending chat item this run is waiting on. Set only while the run is awaiting consent. |
| replyParams | String | The channel's own routing information as JSON - a Slack channel and thread, an email address, or whatever else that channel needs to deliver a message. Channels are marketplace apps that own their own protocols, so the value is carried and handed back untouched and is never interpreted here. |
| status | String | Where the run sits in its lifecycle: running, awaiting_consent, completed, failed or expired, matching the STATUS constants on this class. Only the state transition methods change it. |
Methods
getId() · getAgent() · getAdminOrg() · getParentRun() · getConversationId() · getChatItemId() · getPendingToolId() · getPendingSpecialist() · getChannel() · getReplyParams() · getCurrentPhase() · getStatus() · getCorrelationToken() · getLastError() · rowId()
getId()
Returns: long
Database identifier for this run, assigned when the run is first saved.
getAgent()
Returns: Agent
The agent this run executes on behalf of. The agent's owner supplies the security context every phase of the run executes under. Never null for a persisted run.
getAdminOrg()
Returns: Organisation
The tenant this run belongs to, copied from the agent when the run is created so the expiry sweep can filter by organisation without joining to the agent. Never null for a persisted run.
getParentRun()
Returns: AgentRun
The run which delegated to this one, when this run is a sub-agent. Null for a root run started directly rather than by delegation.
getConversationId()
Returns: String
Opaque key into ai-lib's conversation storage holding the message history for this run. The messages themselves are not duplicated onto this row. Null for a run with no conversation behind it.
getChatItemId()
Returns: String
The chat item carrying the consent block this run is waiting on, set when the run pauses for consent. This is a pointer only: the tool name, its arguments and the already-executed flag all live on that chat item, which is what the UI renders and what a resume validates against, so there is exactly one record of what was approved.
getPendingToolId()
Returns: String
The model's call id for the gated tool call, ie which request on the pending chat item this run is waiting on. Set only while the run is awaiting consent.
getPendingSpecialist()
Returns: String
The specialist whose delegated run asked for the gated call, when the consent request arose inside a delegation. This matters on resume rather than being merely descriptive: a specialist's tools are not in the delegating agent's own whitelist, so the approved call has to be re-delegated to that specialist instead of being run directly.
getChannel()
Returns: String
Which channel this run reaches its owner through, given as the sourceApp identifier, for example Slack or admin-lib. The expiry sweep runs off a timer with no request and no conversation in hand, so this is what lets it announce an expiry back over the channel the consent request went out on.
getReplyParams()
Returns: String
The channel's own routing information as JSON - a Slack channel and thread, an email address, or whatever else that channel needs to deliver a message. Channels are marketplace apps that own their own protocols, so the value is carried and handed back untouched and is never interpreted here.
getCurrentPhase()
Returns: String
Which step of the orchestrator loop this run has reached: gather, plan, act or verify, matching the PHASE constants on this class. A new run starts in gather.
getStatus()
Returns: String
Where the run sits in its lifecycle: running, awaiting_consent, completed, failed or expired, matching the STATUS constants on this class. Only the state transition methods change it.
getCorrelationToken()
Returns: String
Opaque token generated when the run is created and embedded in outbound consent requests, so a reply arriving over an async channel can be matched back to this run. Unique across all runs and never null.
getLastError()
Returns: String
Short diagnostic message recorded when the run failed, truncated to 2000 characters. Null unless the run has failed.
rowId()
Returns: Long
The database identifier for this run, as the generic row id used across Kademi entities. Same value as the id.