Annotation Interface AgenorMessageHandler
The annotated method must be public and accept a single
Message parameter. The runtime registers the method as a
subscriber on the agent's MessageDispatcher using the provided topic.
Handlers that are not finished when they return
Return void when the work is done by the time the method returns. When it is not
— an LLM call, a database write, anything whose result arrives later — return the
CompletableFuture instead of starting it and returning
void. The framework waits on what you return, and that is what puts the work inside
the delivery guarantees: the message is acknowledged when your future completes, a failure
in the chain reaches the transport rather than vanishing, and the work counts against the
mailbox's limit on concurrent handlers.
// Inside the guarantees: the framework waits for the call.
@AgenorMessageHandler("research.request")
public CompletableFuture<Void> onRequest(Message message) {
return llm.chat(request(message)).thenAccept(this::publishFindings);
}
// Outside them: the method returns at once, the message is acknowledged at once,
// and a later failure in the chain is invisible to the framework.
@AgenorMessageHandler("research.request")
public void onRequest(Message message) {
llm.chat(request(message)).thenAccept(this::publishFindings);
}
Any other return type is rejected when the agent is registered, with the same warning a
wrong parameter list gets. CompletableFuture<Void> was rejected too before 0.30.0,
which meant an asynchronous handler could not be written at all.
The topic is matched exactly. Both delivery paths resolve a handler by map
lookup on Message.topic() — the topic path in the dispatcher and
the direct path in BaseAgent — so a value containing * or # matches
nothing and is rejected when the agent is registered. For pattern matching, subscribe
programmatically with a MessageFilter; TopicFilter
in agenor-runtime-ext builds one from a wildcard with TopicFilter.wildcard().
Example:
@Agent("inventory-agent")
public class InventoryAgent extends BaseAgent {
@AgenorMessageHandler("orders.new")
public void onNewOrder(Message message) {
var order = message.getContentAs(Order.class);
reserveStock(order);
}
@AgenorMessageHandler(value = "inventory.low-stock", autoSubscribe = false)
public void onLowStock(Message message) {
// subscribed manually when needed
}
}
- Since:
- 0.1.0
- See Also:
-
Required Element Summary
Required Elements -
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescriptionbooleanWhether the runtime should subscribe this handler automatically when the agent starts.
-
Element Details
-
value
String valueThe exact topic this handler subscribes to.Compared for equality with the incoming
Message.topic(). No wildcard or pattern syntax is supported; see the type documentation for the filter-based alternative.- Returns:
- the topic, must not be empty and must not contain
*or#
-
autoSubscribe
boolean autoSubscribeWhether the runtime should subscribe this handler automatically when the agent starts.Set to
falseto delay subscription; the handler can then be registered manually at an appropriate point in the agent's lifecycle.- Returns:
trueto subscribe automatically (default),falsefor manual subscription
- Default:
true
-