Skip to main content

AI Agents Overview

AI Agents enable intelligent, automated interactions within your application. They can process user messages, trigger tools, and respond with contextually relevant information. For a broader introduction, see the AI Agents section.
Note: Currently, an Agent only responds to Text Messages.

Agent Run Lifecycle and Message Flow

This section explains how a user’s text message to an Agent becomes a structured “run” which emits real-time events and then produces agentic messages for historical retrieval.
  • A user sends a text message to an Agent.
  • The platform starts a run and streams real-time events via the AIAssistantListener.
  • After the run completes, persisted Agentic Messages arrive via the MessageListener.

Real-time Events

Events are received via the onAIAssistantEventReceived method of the AIAssistantListener class in this general order:
  1. Run Start
  2. Zero or more tool call cycles (repeats for each tool invocation):
    • Tool Call Start
    • Tool Call Arguments
    • Tool Call End
    • Tool Call Result
  3. Zero or more card streams (repeats for each card the agent produces):
    • Card Start
    • Card
    • Card End
  4. One or more assistant reply streams:
    • Text Message Start
    • Text Message Content (multiple times; token/char streaming)
    • Text Message End
  5. Run Finished
Notes:
  • Run Start and Run Finished are always emitted.
  • Tool Call events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run.
  • Card events (Card StartCardCard End) appear only when the agent produces a card, and repeat for each card.
  • Text Message events are always emitted and carry the assistant’s reply incrementally.

String LISTENERS_TAG = "UNIQUE_LISTENER_ID";

CometChat.addAIAssistantListener(LISTENERS_TAG, new CometChat.AIAssistantListener() {
    @Override
    public void onAIAssistantEventReceived(AIAssistantBaseEvent aiAssistantBaseEvent) {
        Log.d(TAG, "AIAssistant event received successfully: " + aiAssistantBaseEvent.toString());
    }
});

Event descriptions

  • Run Start: A new run has begun for the user’s message.
  • Tool Call Start: The agent decided to invoke a tool.
  • Tool Call Arguments: Arguments being passed to the tool.
  • Tool Call End: Tool execution completed.
  • Tool Call Result: Tool’s output is available.
  • Card Start: The agent began producing a card; carries a cardId and an executionText loading label.
  • Card: The full card payload for the given cardId is available to render.
  • Card End: The card stream for the given cardId is complete.
  • Text Message Start: The agent started composing a reply.
  • Text Message Content: Streaming content chunks for progressive rendering.
  • Text Message End: The agent reply is complete.
  • Run Finished: The run is finalized; persisted messages will follow.

Card Streaming Events

When an agent produces a card, it is delivered through three streaming events on onAIAssistantEventReceived. Each event is a subclass of AIAssistantBaseEvent — check the concrete type to handle it.
EventGetterDescription
AIAssistantCardStartedEventgetCardId()Identifier for the card being generated.
getExecutionText()Loading label shown while the card is built.
getStreamMessageId()Identifier of the streaming message that owns this card.
AIAssistantCardReceivedEventgetCardId()Identifier matching the corresponding start event.
getCard()The complete card payload (JSONObject) to render.
AIAssistantCardEndedEventgetCardId()Signals the card stream for this cardId is complete.

CometChat.addAIAssistantListener(LISTENERS_TAG, new CometChat.AIAssistantListener() {
    @Override
    public void onAIAssistantEventReceived(AIAssistantBaseEvent event) {
        if (event instanceof AIAssistantCardStartedEvent) {
            AIAssistantCardStartedEvent started = (AIAssistantCardStartedEvent) event;
            String cardId = started.getCardId();
            String label = started.getExecutionText(); // e.g. "Building card…"
        } else if (event instanceof AIAssistantCardReceivedEvent) {
            AIAssistantCardReceivedEvent received = (AIAssistantCardReceivedEvent) event;
            String cardId = received.getCardId();
            JSONObject card = received.getCard();       // full card payload
        } else if (event instanceof AIAssistantCardEndedEvent) {
            AIAssistantCardEndedEvent ended = (AIAssistantCardEndedEvent) event;
            // card stream for ended.getCardId() is complete
        }
    }
});

Agentic Messages

These events are received via the MessageListener after the run completes.
  • AIAssistantMessage: The full assistant reply.
  • AIToolResultMessage: The final output of a tool call.
  • AIToolArgumentMessage: The arguments that were passed to a tool.

String listenerId = "UNIQUE_LISTENER_ID";

CometChat.addMessageListener(listenerId, new CometChat.MessageListener() {
    @Override
    public void onAIAssistantMessageReceived(AIAssistantMessage aiAssistantMessage) {
        Log.d(TAG, "AIAssistantMessage received successfully: " + aiAssistantMessage.toString());
    }

    @Override
    public void onAIToolResultReceived(AIToolResultMessage aiToolResultMessage) {
        Log.d(TAG, "AIToolResultMessage received successfully: " + aiToolResultMessage.toString());
    }

    @Override
    public void onAIToolArgumentsReceived(AIToolArgumentMessage aiToolArgumentMessage) {
        Log.d(TAG, "AIToolArgumentMessage received successfully: " + aiToolArgumentMessage.toString());
    }
});

AIAssistantMessage Elements

Once a run completes, the assistant’s reply is persisted as an AIAssistantMessage. Its content is exposed as an ordered list of blocks via getElements(), letting you render text and cards in the exact order the agent produced them. When getElements() is null or empty, fall back to the plain getText() body.
MethodReturnsDescription
getElements()List<AIAssistantElement>Ordered content blocks. null/empty for plain-text replies.
getText()StringPlain-text body (fallback when there are no elements).
Each AIAssistantElement exposes:
MethodReturnsDescription
getType()StringBlock type — "text" or "card".
getData()ObjectThe block body (text string, or card payload).

List<AIAssistantElement> elements = message.getElements();
if (elements == null || elements.isEmpty()) {
    renderText(message.getText());
} else {
    for (AIAssistantElement element : elements) {
        switch (element.getType()) {
            case "text":
                renderText(String.valueOf(element.getData()));
                break;
            case "card":
                renderCard(element.getData());
                break;
        }
    }
}