> Fetch clean Markdown by appending `.md` to any page URL under https://signalwire.com/docs or requesting it with the HTTP header `Accept: text/markdown`. The root index at https://signalwire.com/docs/llms.txt lists the available documentation indexes. # chat > Send a message to an AI agent and return its reply. [ref-aichatclient]: /docs/server-sdks/reference/typescript/agents/ai-chat-client [createconversation]: /docs/server-sdks/reference/typescript/agents/ai-chat-client/create-conversation [swml-user-event]: /docs/server-sdks/reference/typescript/agents/function-result/swml-user-event Send a message and return the agent's reply. One call is one full turn, including any tool calls the agent makes along the way, so expect seconds rather than milliseconds. ## **Parameters** **`conversationId`** `string` — required The conversation to send on. --- **`message`** `string` — required The message to send. --- **`options`** `ChatOptions` Turn options. --- **`options.role`** `string` — default: user `user` or `system`. A `system` message steers the agent without appearing as something the user said. --- **`options.configUrl`** `string` Creates the conversation if it does not exist yet. Saves a call, at the cost of never receiving `initialMessage`, so the agent does not speak first. --- **`options.userMetadata`** `Record` Arbitrary data about the user, echoed back on this conversation's webhooks. Sent as `user_meta_data`. --- **`options.timeout`** `number` Applies only when this call creates the conversation. --- **`options.reinit`** `boolean` — default: false Applies only when this call creates the conversation. --- ## **Returns** `Promise` -- carries `text`, `conversationId`, and `userEvent`. `userEvent` is `null` unless the turn produced one. Its contents are whatever your tool passed to [`swmlUserEvent()`][swml-user-event], so the shape is yours. ## **Throws** `ChatInProgressError` when a turn is already running on this conversation. That is the contract rather than a transient failure, so wait for the first turn to return instead of retrying. ## **Example** ```typescript {8-11} import { AIChatClient, ChatInProgressError } from '@signalwire/sdk'; const CONFIG_URL = 'https://bayview-taxi.example.com/swml'; const client = new AIChatClient({ space: 'your-space' }); await client.createConversation('chat-8f21', { configUrl: CONFIG_URL }); try { const reply = await client.chat( 'chat-8f21', 'How much is a van from 123 Gough Street to the airport?', ); console.log('Ada:', reply.text); if (reply.userEvent) handle(reply.userEvent); } catch (e) { if (e instanceof ChatInProgressError) { // a turn is already running; wait rather than retry } else { throw e; } } ``` > Send a message to an AI agent and return its reply.