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

# Web and app chat

> Connect your own interface to the same tools, skills and conversation runtime.

Keep your own chat UI and let Flow handle the conversation. Define how your backend sends replies
and status updates; your frontend decides how to display them.

## Define the channel

This fragment uses `chat`, your application's delivery layer. Add the resulting channel to the
agent's `channels` configuration:

```ts Channel configuration fragment theme={null}
import { customUI } from "@flow-engineer/flow";

const web = customUI("web", {
  sendMessage: (to, message) => chat.publish(to, message),
  typing: (to, on) => chat.typing(to, on),
  status: (to, text) => chat.status(to, text),
});
```

Only `sendMessage` is required. Optional hooks add typing, reactions, read receipts and status
lines. Use `info` and `params` to describe extra capabilities and structured fields your UI supports.

To let the agent fix what it sent, resolve `sendMessage` with the message's id
(`{ status: "sent", messageId }`) and add `editMessage(to, messageId, text)` and
`unsendMessage(to, messageId)`. With them the agent is offered `edit_message` and `unsend_message`.
Reject either one to refuse it, and the reason goes back to the agent.

## Accept a signed-in request

For request/response delivery, call `agent.request` from your authenticated backend:

```ts Authenticated request handler fragment theme={null}
const result = await agent.request({
  channel: "web",
  key: verifiedAccountId,
  text: messageText,
});
// Return result.replies to this signed-in client.
```

Get `verifiedAccountId` from server-verified authentication, never a user-supplied body field.
Serialize requests per channel and account. If you pass a `conversationId`, Flow checks that it
belongs to the authenticated person.

For pushed delivery instead, verify and map the channel identity in your backend before calling
`agent.message({ channel: "web", from, message, messageId })`. Use `resolve` to join that verified
identity to the right account.

## Check it worked

Ask a question that invokes a tool and send a correction while it runs. Verify the final result
in the UI, then check the [runtime events](https://docs.flow.engineer/traces.md). Your delivery layer must also route later
background results and scheduled messages, not just immediate replies.

For a local test UI without building your own frontend, use the [playground](https://docs.flow.engineer/playground.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.