---
title: "Chat channel conversations"
description: "Handle replies, questions, approvals and cards in a thread."
canonical_url: "https://docs.oz0.ai/build/apps/chat-channels/conversations"
---
# Chat channel conversations

> Handle replies, questions, approvals and cards in a thread.

For: application developers.

Handle replies, questions, approvals and cards in a thread.

## Questions and approvals in the thread

When a job [asks a question](https://docs.oz0.ai/agents/asking-people), the thread gets it with a button per choice, or an Answer button that opens a form (on Slack you may also just reply in the thread). When a tool call needs an [approval](https://docs.oz0.ai/agents/approvals), the thread gets Approve and Deny, with what the call does, the arguments its schema marks as a recipient, an amount, a host or a path (and a warning for those not in the job's input), and the deadline that denies it.

On Slack, an editable call also gets Edit and approve, a form with the call's current values in the standard field set (its first 20 fields; the arguments it cannot show keep their values, and the form names them); the edit is checked as one made in the console, and the thread's message names the fields that changed. On Teams the approval's card carries the same fields as its inputs (a text box, a number, a choice, several choices, a date and a time, a toggle), and Edit and approve sends them.

An optional date or choice can be left out on purpose (Leave empty). Discord threads say how to edit in OZ instead ([edit forms per chat](https://docs.oz0.ai/agents/approvals/edits-and-repeat-calls#edit-forms-in-chat-threads)). A [typed question](https://docs.oz0.ai/agents/asking-people#typed-questions) gets the same kind of form on Slack and Teams, and Open in OZ on Discord. Every question and approval carries Open in OZ, a link button to the job's page in the console when the server has a `--public-url` (a link carries no token). A call that asks for a typed confirmation offers only Deny in the thread.

## Results as cards

An answer that matches the agent's [output contract](https://docs.oz0.ai/build/parts/contracts-and-limits#results-drawn-as-cards) and is a table or key-values comes to the thread drawn with the chat's own structures: Slack's section fields, a Teams card's FactSet (one per row for a table), Discord's embed fields. At most ten rows, five columns or ten keys are shown, each value as plain text (no mention, no link, no markup), and the message says when OZ has the rest.

Any other answer, or one too large, comes as before, its JSON in a code block. The AI label stays the message's first word. Each step of the [escalation ladder](https://docs.oz0.ai/agents/approvals/configure#the-escalation-ladder) adds a line to the thread.

Only a mapped person whose account may decide approvals (operator and up) decides one; anyone else gets a message only they see that says why, and the approval keeps waiting. The person who started a thread of an `--allow everyone` binding may answer its questions. A decision made in the console or the CLI takes the buttons off the thread's message.

Buttons count only on the message the platform posted for the approval. A message with the same buttons posted by anyone else, such as an agent told by outside text to post one, decides nothing. The same holds for forms: a form decides only when it comes from the message the platform posted it on, so a form opened from any other message decides nothing.

A Teams card's inputs and a Discord modal come with their message from the chat system itself; a Slack modal comes back with only what the plugin put in it, so the edge seals the click that opened it (who clicked, where, on which message, which form) and takes the modal's answer only as that click, from that person, within an hour; a modal left open longer is refused, and the person opens it again.

A form decides only what the platform offered it for: an Answer form and a choice answer a question and nothing else, never a tool call's approval, and Edit and approve comes only for a call the platform offered the edit form for.

Agents that post to a chat use the plugin's `send` function. The channel's own `post` function (which the platform uses for its threads, with reply tokens and buttons) and the function that reads deliveries are refused to other plugins' agents and flows: the edge adds that rule to the tenant's [tool policy](https://docs.oz0.ai/govern/tool-policy) on every node. A tenant that really wants an agent to call one names the function in a rule of its own, which the platform's rule then leaves alone:

```bash [Terminal]
oz0 policy ask oz0_slack.post --reason "posts by others' agents need a person"
```

## The AI label

Every message the app posts for an agent starts with the tenant's [AI label](https://docs.oz0.ai/govern/ai-labels): the opening, the answer, each question and approval, a notice to one person and the update after a decision, as in `@alice [AI agent] The deploy is green.`. It is in the message's text, not only in the app's name. On Teams the label is the card's first line, and the message also carries Teams' own AI-generated label. An agent's own posts through `send` carry it too. Word it with `oz0 tenant ai-label set`.

## Go on in the thread

A reply token (Slack's `response_url`, Discord's interaction token) lasts minutes. While it lasts the edge keeps it in the thread's record, sealed as the tenant's secrets are and bound to the thread, so the database (and management, once an edge holds the cluster's secrets key) holds no usable token; backups leave it out, and it is dropped once it expires.

Every turn of a thread is a turn of one [conversation](https://docs.oz0.ai/agents/conversations): a reply in a Slack thread, or Discord's Reply button under an answer, starts the next turn with the earlier ones, as `oz0 run --continue` does. A reply while the thread's job still runs is answered with "still working"; a reply to an open question without choices answers it.

The console's Chat channels page lists the threads under *Threads*, those started in the [period](https://docs.oz0.ai/getting-started/web-ui/navigation#periods-filters-and-pages) you pick (the last 7 days unless you pick another), newest first, a page at a time.

```bash [Terminal]
oz0 channel threads
```

```text
THREAD        CHANNEL  WHERE  AGENT   TURN  JOB                           STATE  AS          UPDATED
71adbda9e7da  slack    T1/C1  helper  2     channel-slack-71adbda9e7da-2  idle   user:alice  2026-10-07 02:18:32
```


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
