Class BaseAgent
- All Implemented Interfaces:
Agent,LifecycleHooks
- Direct Known Subclasses:
LLMAgent,MessageSnifferAgent
Provides core functionality including:
- Lifecycle management (start/stop)
- Message handling
- Behavior scheduling
- Agent directory integration
- Memory management (since 0.6.0)
All concrete agents should extend this class and implement the required lifecycle methods.
Memory Support (since 0.6.0):
Agents can optionally use memory features by calling memory methods.
Memory features are only available if setMemoryStore(MemoryStore)
is called during initialization.
Example usage:
@Agent("my-agent")
public class MyAgent extends BaseAgent {
@Override
protected void onStart() {
// Use memory if available
rememberShort("session-id", "abc123", Duration.ofMinutes(30));
rememberLong("user-preference", "dark-mode");
}
@AgenorMessageHandler("process-request")
public void handleRequest(Message message) {
recall("session-id", MemoryScope.SHORT_TERM)
.thenAccept(sessionId -> {
log.info("Processing for session: {}", sessionId);
});
}
}
- Since:
- 0.1.0
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected AgentDescriptorprotected AgentDirectoryprotected BehaviorSchedulerprotected final org.slf4j.Loggerprotected MemoryStore -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedCreate an agent with auto-generated IDprotectedCreate agent with specific IDprotectedBaseAgent(String agentId, AgentContext ctx) Create an agent with a specific ID, receiving all core services viaAgentContext.protectedCreate an agent with ID and nameprotectedBaseAgent(String agentId, String agentName, AgentContext ctx) Create an agent with ID, name, and all core services viaAgentContext. -
Method Summary
Modifier and TypeMethodDescriptionvoidaddBehavior(Behavior behavior) Adds a behavior to this agent's behavior set.protected CompletableFuture<Void> clearMemory(MemoryScope scope) Clears all memories in the specified scope.voidClear all registered start hooksvoidClear all registered stop hooksprotected AgentMailboxcreateMailbox(MessageHandler pushConsumer) Creates this agent's mailbox.protected CompletableFuture<Void> forget(String key, MemoryScope scope) Forgets a memory.Returns the unique identifier for this agent.Returns the human-readable name for this agent.Returns a snapshot of all behaviors currently registered on this agent.Gets memory statistics for this agent.Returns the message dispatcher for this agent.Get current agent statusprotected voidhandleDirectMessage(Message message) Handle direct messages received by this agent.protected voidbooleanChecks whether the agent is currently running.mailbox()Returns this agent's mailbox, the owner of its inbound path.protected MailboxConfigReturns the bounds and overflow behaviour for this agent's mailbox.protected voidonDirectMessage(Message message) Called when agent receives a direct message.protected voidonStart()Lifecycle hook called when agent startsvoidonStartHook(Runnable hook) Register a hook to be executed when the agent starts.protected voidonStop()Lifecycle hook called when agent stopsvoidonStopHook(Runnable hook) Register a hook to be executed when the agent stops.protected CompletableFuture<Optional<String>> recall(String key, MemoryScope scope) Recalls a memory from the specified scope.protected CompletableFuture<Optional<String>> recallShared(String key) Recalls a shared memory.voidregisterDirectTopicHandler(String topic, MessageHandler handler) Registers a handler to be invoked for direct (point-to-point) messages whoseMessage.topic()matches the given topic.voidregisterTopicSubscription(Subscription subscription) Hands this agent the topic subscription created for one of its@AgenorMessageHandlermethods, so that stopping the agent releases it.protected CompletableFuture<Void> rememberLong(String key, String content) Stores a long-term memory (persistent, survives restart).protected CompletableFuture<Void> Stores a long-term memory with metadata.protected CompletableFuture<Void> rememberShort(String key, String content) Stores a short-term memory (volatile, cleared on restart).protected CompletableFuture<Void> rememberShort(String key, String content, Duration ttl) Stores a short-term memory with expiration.voidremoveBehavior(String behaviorId) Removes a behavior from this agent by its ID.booleanremoveStartHook(Runnable hook) Remove a previously registered start hookbooleanremoveStopHook(Runnable hook) Remove a previously registered stop hookprotected CompletableFuture<Void> Reply to a received message.protected CompletableFuture<Message> requestFrom(String receiverAgentId, Object content) Send a request to another agent and wait for response.protected CompletableFuture<Message> requestFrom(String receiverAgentId, Object content, long timeoutMillis) Send a request with custom timeout.protected CompletableFuture<List<MemoryEntry>> searchMemory(MemoryQuery query) Searches with custom filters.protected CompletableFuture<List<String>> searchMemory(String query, MemoryScope scope) Searches through agent's memories.protected CompletableFuture<Void> Send a direct message to another agent (fire-and-forget).voidsetAgentDescriptor(AgentDescriptor descriptor) Method for AgentFactory to set descriptorvoidsetAgentDirectory(AgentDirectory agentDirectory) Set the agent directory for this agentvoidsetBehaviorScheduler(BehaviorScheduler behaviorScheduler) Set the behavior scheduler for this agentvoidsetMemoryStore(MemoryStore memoryStore) Injects the memory store (optional).voidsetMessageDispatcher(MessageDispatcher dispatcher) voidsetTelemetry(AgenorTelemetry telemetry) Sets the telemetry this agent's inbound path reports to.protected CompletableFuture<Void> shareMemory(String key, String content, String... agentIds) Shares a memory with other agents (for coordination).start()Starts the agent and all its registered behaviors asynchronously.stop()Stops the agent and all its running behaviors gracefully.
-
Field Details
-
log
protected final org.slf4j.Logger log -
behaviorScheduler
-
agentDirectory
-
memoryStore
-
agentDescriptor
-
-
Constructor Details
-
BaseAgent
protected BaseAgent()Create an agent with auto-generated ID -
BaseAgent
Create agent with specific ID -
BaseAgent
Create an agent with ID and name- Parameters:
agentId- the agent identifieragentName- the agent display name
-
BaseAgent
Create an agent with a specific ID, receiving all core services viaAgentContext.Convenience for subclasses that want to accept an
AgentContextin their own constructor and propagate it upward:public class MyAgent extends BaseAgent { public MyAgent(AgentContext ctx) { super("my-agent", ctx); } }- Parameters:
agentId- the agent identifierctx- the aggregated core services, not null- Since:
- 0.10.0
-
BaseAgent
Create an agent with ID, name, and all core services viaAgentContext.- Parameters:
agentId- the agent identifieragentName- the agent display namectx- the aggregated core services, not null- Since:
- 0.10.0
-
-
Method Details
-
getAgentId
Description copied from interface:AgentReturns the unique identifier for this agent.The agent ID must be unique within the runtime environment and is used for agent discovery, message routing, and state management. Once assigned, the ID should never change during the agent's lifetime.
Recommended format: lowercase alphanumeric with hyphens (e.g., "order-processor-1").
- Specified by:
getAgentIdin interfaceAgent- Returns:
- the agent's unique identifier, never null or empty
-
getAgentName
Description copied from interface:AgentReturns the human-readable name for this agent.The agent name is primarily for display and logging purposes. Unlike the agent ID, the name doesn't need to be unique and can be changed during the agent's lifetime (though this is discouraged).
Names should be descriptive and help identify the agent's purpose (e.g., "Customer Support Agent", "Inventory Monitor").
- Specified by:
getAgentNamein interfaceAgent- Returns:
- the agent's display name, never null or empty
-
isRunning
public boolean isRunning()Description copied from interface:AgentChecks whether the agent is currently running.An agent is considered running if it has completed startup and is actively executing behaviors. This method returns:
true- Agent is in RUNNING statefalse- Agent is in CREATED, STARTING, STOPPING, or STOPPED state
State Transitions: During startup and shutdown, this method may temporarily return values that don't reflect the final state:
- During
Agent.start(): returnsfalseuntil fully started - During
Agent.stop(): returnstrueuntil fully stopped
For more detailed state information, use the agent's status in its
AgentDescriptor. -
start
Description copied from interface:AgentStarts the agent and all its registered behaviors asynchronously.This method initiates the agent's lifecycle, performing the following:
- Transitions the agent to the STARTING state
- Initializes all registered behaviors
- Starts behavior execution (cyclic, scheduled, etc.)
- Registers the agent with the directory (if enabled)
- Transitions to RUNNING state when complete
Idempotency: Calling
start()on an already running agent should be a no-op and return immediately.Concurrency: This method is asynchronous and non-blocking. Use the returned
CompletableFutureto wait for startup completion or chain subsequent operations.Error Handling: If startup fails, the returned future completes exceptionally. The agent transitions to the ERROR state and set s running to false.
Example:
agent.start() .thenRun(() -> log.info("Agent started successfully")) .exceptionally(ex -> { log.error("Failed to start agent", ex); return null; }); -
stop
Description copied from interface:AgentStops the agent and all its running behaviors gracefully.This method initiates graceful shutdown, performing the following:
- Transitions the agent to the STOPPING state
- Stops all running behaviors (allowing current executions to complete)
- Unregisters the agent from the directory (if registered)
- Releases allocated resources (threads, connections, etc.)
- Transitions to STOPPED state when complete
Graceful Shutdown: The agent attempts to stop cleanly, allowing behaviors to complete their current execution cycle. A timeout may be enforced to prevent indefinite waiting.
Idempotency: Calling
stop()on an already stopped agent should be a no-op and return immediately.Concurrency: This method is asynchronous and non-blocking. Multiple concurrent calls to
stop()should be safe and result in a single shutdown sequence.Resource Cleanup: Implementations must ensure proper cleanup of:
- Thread pools and executors
- Open connections and file handles
- Scheduled tasks
- Message subscriptions
Example:
agent.stop() .thenRun(() -> log.info("Agent stopped gracefully")) .exceptionally(ex -> { log.warn("Error during shutdown (resources may leak)", ex); return null; }); -
addBehavior
Description copied from interface:AgentAdds a behavior to this agent's behavior set.Behaviors represent units of autonomous activity. When a behavior is added to a running agent, it should start executing immediately according to its type (one-shot, cyclic, triggered, etc.).
Dynamic Addition: Behaviors can be added at any time:
- Before
Agent.start()- Behavior will start when agent starts - While running - Behavior starts immediately
- After
Agent.stop()- Behavior is added but won't execute until restart
Behavior Identity: Each behavior must have a unique ID within the agent's scope. Adding a behavior with a duplicate ID may either replace the existing behavior or throw an exception, depending on the implementation.
Thread Safety: This method must be thread-safe and can be called concurrently with other lifecycle operations.
Example:
// Runs every 5 seconds agent.addBehavior(CyclicBehavior.from("monitor", Duration.ofSeconds(5), () -> checkSystemHealth())); // Runs once; subclass when the factories do not cover what you need agent.addBehavior(new OneShotBehavior("warm-cache") { @Override protected void action() { preloadCatalogue(); } });Reacting to a message is not a behavior: annotate a method with
@AgenorMessageHandler("orders.created"), or subscribe through the agent'sMessageDispatcher.- Specified by:
addBehaviorin interfaceAgent- Parameters:
behavior- the behavior to add, must not be null- See Also:
- Before
-
removeBehavior
Description copied from interface:AgentRemoves a behavior from this agent by its ID.If the agent is running, the behavior will be stopped gracefully:
- For one-shot behaviors: current execution completes
- For cyclic behaviors: current cycle completes, no new cycles start
- For triggered behaviors: message subscriptions are cancelled
Not Found: If no behavior exists with the given ID, this method is a no-op.
Thread Safety: This method must be thread-safe and can be called concurrently with behavior execution and other lifecycle operations.
Example:
// Remove a behavior dynamically agent.removeBehavior("monitor");- Specified by:
removeBehaviorin interfaceAgent- Parameters:
behaviorId- the unique identifier of the behavior to remove, must not be null- See Also:
-
getBehaviors
Returns a snapshot of all behaviors currently registered on this agent.The returned list is a point-in-time copy; modifications to it do not affect the agent's behavior collection. Used by
HitlAnnotationProcessorduring agent registration.- Returns:
- immutable snapshot of registered behaviors
- Since:
- 0.13.0
-
setMessageDispatcher
-
getMessageDispatcher
Returns the message dispatcher for this agent.- Specified by:
getMessageDispatcherin interfaceAgent- Returns:
- the message dispatcher for this agent, never null
- Since:
- 0.20.0
- See Also:
-
setBehaviorScheduler
Set the behavior scheduler for this agent -
setTelemetry
Sets the telemetry this agent's inbound path reports to.Set by the runtime at registration, alongside the dispatcher and the directory. An agent that is never registered keeps the no-op instance, so nothing here depends on having a telemetry backend.
- Parameters:
telemetry- the telemetry instance;nullrestores the no-op- Since:
- 0.31.0
-
getTelemetry
- Returns:
- the telemetry wired into this agent; never
null - Since:
- 0.31.0
-
getStatus
Get current agent status -
setAgentDirectory
Set the agent directory for this agent -
setAgentDescriptor
Method for AgentFactory to set descriptor -
setMemoryStore
Injects the memory store (optional). Called by the runtime during agent initialization.If not set, memory operations will throw
IllegalStateException.- Parameters:
memoryStore- the memory store- Since:
- 0.6.0
-
onStartHook
Register a hook to be executed when the agent starts. Hooks are executed AFTER onStart() is called. This is useful for external components (like PersistenceManager) to perform actions during agent startup.- Specified by:
onStartHookin interfaceLifecycleHooks- Parameters:
hook- the runnable to execute on start
-
onStopHook
Register a hook to be executed when the agent stops. Hooks are executed BEFORE onStop() is called. This is critical for persistence - it ensures state is saved before the agent shuts down completely.- Specified by:
onStopHookin interfaceLifecycleHooks- Parameters:
hook- the runnable to execute on stop
-
removeStartHook
Remove a previously registered start hook- Parameters:
hook- the hook to remove- Returns:
- true if the hook was found and removed
-
removeStopHook
Remove a previously registered stop hook- Parameters:
hook- the hook to remove- Returns:
- true if the hook was found and removed
-
clearStartHooks
public void clearStartHooks()Clear all registered start hooks -
clearStopHooks
public void clearStopHooks()Clear all registered stop hooks -
initializeServices
protected void initializeServices() -
onStart
protected void onStart()Lifecycle hook called when agent starts -
onStop
protected void onStop()Lifecycle hook called when agent stops -
createMailbox
Creates this agent's mailbox.The one place the runtime's own implementation is named. Override to hand the agent a different
AgentMailbox— an instrumented one, or a different queueing strategy — without touching how the inbound path is wired. Called once, when the agent starts.- Parameters:
pushConsumer- receives every message the mailbox does not route to a dialogue consumer; must be passed to the mailbox unchanged- Returns:
- a non-null mailbox, not yet started
- Since:
- 0.27.0
-
mailboxConfig
Returns the bounds and overflow behaviour for this agent's mailbox.Override to give one agent a different capacity or overflow policy. Read once, when the agent starts.
- Returns:
- a non-null configuration;
MailboxConfig.defaults()unless overridden
-
mailbox
Returns this agent's mailbox, the owner of its inbound path.Present only while the agent is started and a message dispatcher is set. Intended for components that consume the agent's inbound traffic, such as the dialogue layer.
- Returns:
- the mailbox, or an empty optional if the agent is not started
- Since:
- 0.27.0
-
registerDirectTopicHandler
Registers a handler to be invoked for direct (point-to-point) messages whoseMessage.topic()matches the given topic.Used internally by the runtime's annotation processor so that
@AgenorMessageHandler-annotated methods also fire for messages sent viasendTo()/receiverIdaddressing, not just topic pub/sub.- Parameters:
topic- the exact topic to match againstMessage.topic()handler- the handler to invoke on a match- Since:
- 0.25.0
-
registerTopicSubscription
Hands this agent the topic subscription created for one of its@AgenorMessageHandlermethods, so that stopping the agent releases it.Used internally by the runtime's annotation processor. Without it the
Subscriptionhas no owner and nothing can ever cancel it: the subscription outlives the agent for the life of the process.- Parameters:
subscription- the subscription to release when this agent stops- Since:
- 0.29.0
-
handleDirectMessage
Handle direct messages received by this agent. Override to customize handling, or use @AgenorMessageHandler annotations. -
onDirectMessage
Called when agent receives a direct message. Override to handle direct messages in a centralized way. Note: This is only called if no @AgenorMessageHandler matches.- Parameters:
message- the received message
-
sendTo
Send a direct message to another agent (fire-and-forget).- Parameters:
receiverAgentId- the target agent IDcontent- the message content- Returns:
- CompletableFuture that completes when sent
-
requestFrom
Send a request to another agent and wait for response. Uses the request/response pattern with correlation ID.- Parameters:
receiverAgentId- the target agent IDcontent- the request content- Returns:
- CompletableFuture with the response message
-
requestFrom
protected CompletableFuture<Message> requestFrom(String receiverAgentId, Object content, long timeoutMillis) Send a request with custom timeout.- Parameters:
receiverAgentId- the target agent IDcontent- the request contenttimeoutMillis- timeout in milliseconds- Returns:
- CompletableFuture with the response message
-
replyTo
Reply to a received message. Automatically sets correlation ID and receiver.- Parameters:
originalMessage- the message to reply tocontent- the reply content- Returns:
- CompletableFuture that completes when reply is sent
-
rememberShort
Stores a short-term memory (volatile, cleared on restart).Short-term memories are suitable for:
- Temporary state during task execution
- Caching of computed values
- Session-specific information
- Parameters:
key- the memory key (will be namespaced automatically)content- the memory content- Returns:
- a future that completes when stored
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-
rememberShort
Stores a short-term memory with expiration.- Parameters:
key- the memory key (will be namespaced automatically)content- the memory contentttl- time-to-live (null = never expires)- Returns:
- a future that completes when stored
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-
rememberLong
Stores a long-term memory (persistent, survives restart).Long-term memories are suitable for:
- Learned facts and knowledge
- User preferences
- Historical patterns
- Parameters:
key- the memory key (will be namespaced automatically)content- the memory content- Returns:
- a future that completes when stored
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-
rememberLong
protected CompletableFuture<Void> rememberLong(String key, String content, Map<String, Object> metadata) Stores a long-term memory with metadata.- Parameters:
key- the memory keycontent- the memory contentmetadata- additional metadata- Returns:
- a future that completes when stored
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-
recall
Recalls a memory from the specified scope.- Parameters:
key- the memory key (will be namespaced automatically)scope- the memory scope to search in- Returns:
- a future containing the memory content, or empty if not found
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-
searchMemory
Searches through agent's memories.- Parameters:
query- the search textscope- the memory scope to search in- Returns:
- a future containing matching memory contents
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-
searchMemory
Searches with custom filters.- Parameters:
query- the memory query- Returns:
- a future containing matching entries
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-
forget
Forgets a memory.- Parameters:
key- the memory key (will be namespaced automatically)scope- the memory scope- Returns:
- a future that completes when deleted
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-
clearMemory
Clears all memories in the specified scope.Warning: This operation cannot be undone.
- Parameters:
scope- the memory scope to clear- Returns:
- a future that completes when cleared
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-
getMemoryStats
Gets memory statistics for this agent.- Returns:
- memory usage statistics
- Throws:
IllegalStateException- if memory store not configured- Since:
- 0.6.0
-