> ## Documentation Index
> Fetch the complete documentation index at: https://www.cometchat.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# AI Agents

# 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](/ai-agents).

> **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 Start` → `Card` → `Card 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.

<Tabs>
  <Tab title="Java">
    ```java theme={null}

    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());
        }
    });

    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}

    val LISTENERS_TAG = "UNIQUE_LISTENER_ID"

    CometChat.addAIAssistantListener(LISTENERS_TAG, object : CometChat.AIAssistantListener() {
        override fun onAIAssistantEventReceived(aiAssistantBaseEvent: AIAssistantBaseEvent) {
            Log.d(TAG, "AIAssistant event received successfully: " + aiAssistantBaseEvent.toString())
        }
    })

    ```
  </Tab>
</Tabs>

#### 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.

| Event                          | Getter                 | Description                                              |
| ------------------------------ | ---------------------- | -------------------------------------------------------- |
| `AIAssistantCardStartedEvent`  | `getCardId()`          | 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. |
| `AIAssistantCardReceivedEvent` | `getCardId()`          | Identifier matching the corresponding start event.       |
|                                | `getCard()`            | The complete card payload (`JSONObject`) to render.      |
| `AIAssistantCardEndedEvent`    | `getCardId()`          | Signals the card stream for this `cardId` is complete.   |

<Tabs>
  <Tab title="Java">
    ```java theme={null}

    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
            }
        }
    });

    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}

    CometChat.addAIAssistantListener(LISTENERS_TAG, object : CometChat.AIAssistantListener() {
        override fun onAIAssistantEventReceived(event: AIAssistantBaseEvent) {
            when (event) {
                is AIAssistantCardStartedEvent -> {
                    val cardId = event.cardId
                    val label = event.executionText  // e.g. "Building card…"
                }
                is AIAssistantCardReceivedEvent -> {
                    val cardId = event.cardId
                    val card = event.card            // full card payload (JSONObject)
                }
                is AIAssistantCardEndedEvent -> {
                    // card stream for event.cardId is complete
                }
            }
        }
    })

    ```
  </Tab>
</Tabs>

### 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.

<Tabs>
  <Tab title="Java">
    ```java theme={null}

    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());
        }
    });

    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}

    val listenerId = "UNIQUE_LISTENER_ID"

    CometChat.addMessageListener(listenerId, object : CometChat.MessageListener() {
        override fun onAIAssistantMessageReceived(aiAssistantMessage: AIAssistantMessage) {
            Log.d(TAG, "AIAssistantMessage received successfully: " + aiAssistantMessage.toString())
        }

        override fun onAIToolResultReceived(aiToolResultMessage: AIToolResultMessage) {
            Log.d(TAG, "AIToolResultMessage received successfully: " + aiToolResultMessage.toString())
        }

        override fun onAIToolArgumentsReceived(aiToolArgumentMessage: AIToolArgumentMessage) {
            Log.d(TAG, "AIToolArgumentMessage received successfully: " + aiToolArgumentMessage.toString())
        }
    })

    ```
  </Tab>
</Tabs>

### 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.

| Method          | Returns                    | Description                                                  |
| --------------- | -------------------------- | ------------------------------------------------------------ |
| `getElements()` | `List<AIAssistantElement>` | Ordered content blocks. `null`/empty for plain-text replies. |
| `getText()`     | `String`                   | Plain-text body (fallback when there are no elements).       |

Each `AIAssistantElement` exposes:

| Method      | Returns  | Description                                    |
| ----------- | -------- | ---------------------------------------------- |
| `getType()` | `String` | Block type — `"text"` or `"card"`.             |
| `getData()` | `Object` | The block body (text string, or card payload). |

<Tabs>
  <Tab title="Java">
    ```java theme={null}

    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;
            }
        }
    }

    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}

    val elements = message.elements
    if (elements.isNullOrEmpty()) {
        renderText(message.text.orEmpty())
    } else {
        for (element in elements) {
            when (element.type) {
                "text" -> renderText(element.data?.toString().orEmpty())
                "card" -> renderCard(element.data)
            }
        }
    }

    ```
  </Tab>
</Tabs>
