Skip to main content
FeatureDescription
AI AgentsIntelligent automated conversations with real-time streaming
AI ModerationAutomatic content moderation with pending/approved/disapproved flow
AI User CopilotSmart Replies, Conversation Starter, Conversation Summary (Dashboard-enabled)
// Listen for real-time AI Agent events (streaming)
CometChat.addAIAssistantListener("LISTENER_ID", self)

// Listen for persisted agentic messages
// Conform to CometChatMessageDelegate
func onAIAssistantMessageReceived(_ msg: AIAssistantMessage) { }
func onAIToolResultMessageReceived(_ msg: AIToolResultMessage) { }
func onAIToolArgumentsMessageReceived(_ msg: AIToolArgumentMessage) { }

// Cleanup
CometChat.removeAIAssistantListener("LISTENER_ID")
CometChat.removeMessageListener("LISTENER_ID")
Prerequisites: CometChat.init() + CometChat.login() completed, AI features enabled in Dashboard Event flow: Run Start -> Tool Call(s) -> Text Message Stream -> Run Finished
AI Agents enable intelligent, automated interactions within your application. They process user messages, trigger tools, and respond with contextually relevant information. For a broader introduction, see the AI Agents section.
Agents only respond to text messages.

Sending a Message to an AI Agent

Send a text message to an agent’s UID like any other user:
let agentUID = "ai-agent-uid"
let textMessage = TextMessage(
    receiverUid: agentUID,
    text: "What's the weather today?",
    receiverType: .user
)

CometChat.sendTextMessage(message: textMessage) { sentMessage in
    print("Message sent to agent")
} onError: { error in
    print("Error: \(error?.errorDescription)")
}

Agent Run Lifecycle and Message Flow

When a user sends a text message to an Agent:
  1. The platform starts a run and streams real-time events via AIAssistantEventsDelegate
  2. After the run completes, persisted Agentic Messages arrive via CometChatMessageDelegate

Real-time Events

Events are received via onAIAssistantEventReceived as AIAssistantBaseEvent objects, in this order:
OrderEventDescription
1Run StartA new run has begun
2Tool Call StartAgent decided to invoke a tool
3Tool Call ArgumentsArguments being passed to the tool
4Tool Call EndTool execution completed
5Tool Call ResultTool’s output is available
6Card StartAgent began producing a card
7CardFull card payload is available
8Card EndCard stream is complete
9Text Message StartAgent started composing a reply
10Text Message ContentStreaming content chunks (multiple)
11Text Message EndAgent reply is complete
12Run FinishedRun finalized; persisted messages follow
Run Start and Run Finished are always emitted. Tool Call events only appear when tools are invoked. 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.
import CometChatSDK

class AIAssistantEventHandler: AIAssistantEventsDelegate {
    
    private let sdkStreamListenerId = "unique_listener_id"
    
    func addListener() {
        CometChat.addAIAssistantListener(sdkStreamListenerId, self)
    }
    
    func removeListener() {
        CometChat.removeAIAssistantListener(sdkStreamListenerId)
    }
    
    func onAIAssistantEventReceived(_ event: AIAssistantBaseEvent) {
        print("Received AI Event: \(event.type) for Run ID: \(event.id)")
    }
}

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.
EventAccessorDescription
AIAssistantCardStartedEventcardIdIdentifier for the card being generated.
executionTextLoading label shown while the card is built.
streamMessageIdIdentifier of the streaming message that owns this card.
AIAssistantCardReceivedEventcardIdIdentifier matching the corresponding start event.
getCard()The complete card payload ([String: Any]?) to render.
AIAssistantCardEndedEventcardIdSignals the card stream for this cardId is complete.
import CometChatSDK

func onAIAssistantEventReceived(_ event: AIAssistantBaseEvent) {
    switch event {
    case let started as AIAssistantCardStartedEvent:
        let cardId = started.cardId
        let label = started.executionText   // e.g. "Building card…"
    case let received as AIAssistantCardReceivedEvent:
        let cardId = received.cardId
        let card = received.getCard()        // full card payload
    case let ended as AIAssistantCardEndedEvent:
        // card stream for ended.cardId is complete
        break
    default:
        break
    }
}

Agentic Messages

After the run completes, these messages arrive via CometChatMessageDelegate:
Message TypeDescription
AIAssistantMessageThe full assistant reply
AIToolResultMessageThe final output of a tool call
AIToolArgumentMessageThe arguments passed to a tool
import CometChatSDK

let listenerId = "unique_listener_id"

class MessageHandler: CometChatMessageDelegate {
    
    // CometChat.addMessageListener(listenerId, self)
    
    func onAIAssistantMessageReceived(_ aiAssistantMessage: AIAssistantMessage) {
        print("AI Assistant Message Received: \(aiAssistantMessage)")
    }
    
    func onAIToolResultMessageReceived(_ aiToolResultMessage: AIToolResultMessage) {
        print("AI Tool Result Message Received: \(aiToolResultMessage)")
    }
    
    func onAIToolArgumentsMessageReceived(_ aiToolArgumentMessage: AIToolArgumentMessage) {
        print("AI Tool Arguments Message Received: \(aiToolArgumentMessage)")
    }
}
Always remove listeners when they’re no longer needed (e.g., on view dismissal). Failing to remove listeners can cause memory leaks and duplicate event handling.

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 nil or empty, fall back to the plain text body.
MethodReturnsDescription
getElements()[AIAssistantElement]?Ordered content blocks. nil/empty for plain-text replies.
textStringPlain-text body (fallback when there are no elements).
Each AIAssistantElement exposes:
MethodReturnsDescription
getType()StringBlock type — "text" or "card".
getData()Any?The block body (text string, or card payload).
import CometChatSDK

if let elements = message.getElements(), !elements.isEmpty {
    for element in elements {
        switch element.getType() {
        case "text":
            renderText(String(describing: element.getData() ?? ""))
        case "card":
            renderCard(element.getData())
        default:
            break
        }
    }
} else {
    renderText(message.text)
}

Next Steps

AI Chatbots

Set up AI-powered chatbots for automated conversations

AI Moderation

Automatically moderate messages with AI

AI User Copilot

AI-powered features like smart replies and conversation summaries

Send Messages

Send text messages that trigger AI Agent responses