---
title: "Send one message safely"
locale: en
url: https://tlg.builera.app/en/docs/agent-playbooks/send-safely
verified: 2026-10-24
app_version: "2.0"
---

# Send one message safely

Send approved content to one person, prevent duplicates and track the result through the safety gate.


## Goal

You send one message to exactly one person using an account you have been granted. An accepted call only means a job has been created. It does not mean Telegram has confirmed successful sending.

## Permissions needed

- `messages.read` to read the conversation and context.
- `messages.send` to claim the conversation and send.
- `accounts.read` if you need to check the account before sending.
- `crm.read` if you need to read the customer profile and do-not-contact information.

You do not need connection management or limit-changing permissions to send a normal message.

## Ask the person before

Confirm the recipient, sending account, content and purpose. If you already have explicit authorization for this type of reply, work within that scope. Ask again for content outside it.

Do not infer consent from the recipient's presence in the CRM. Do not change the sending account yourself when the chosen account is blocked.

## Check first

Call `whoami`. Read the conversation with `conversations_get` and the latest messages with `messages_list`.

Check do-not-contact status when data is available. The safety gate still makes the decision when dispatching the job. Claim the conversation with `conversations_claim`; do not use `force` to take the lock.

Read the [`messages.send`](https://tlg.builera.app/en/docs/reference/rest/messages.send) schema with `tools_describe`, especially the message identity fields, latest-message condition and outgoing content.

## Steps

1. Define a stable identifier for the send intent.
2. Finalize the payload for that intent.
3. If using REST, send `Idempotency-Key` according to the operation contract.
4. If the send contract has `clientMessageId`, keep the same value when resubmitting the same intent.
5. Set `ifLastMessageId` when the reply is only appropriate if the customer has not sent another message.

> [!IMPORTANT]
> Stop point — ask the person
>
> If the recipient, content or account has not been authorized, stop before sending. Do not send a “test” to a customer to check the connection.

6. Call MCP `messages_send`, or REST operation `messages.send`.
7. Save the returned operation ID.
8. Call `operations_get` to track it.
9. Release the conversation with `conversations_release` when you finish handling it.

For REST, authentication uses:

```text
Authorization: Bearer $TELEGRAM_AUTO_API_KEY
Idempotency-Key: reply-demo-event-a
```

Do not assume `tools_run` has an idempotency parameter outside its schema. Read the exact contract and use the message identity mechanism the operation supports.

## Check after

Only report successful sending when the status confirms it. If the connection drops after the call, look up the old operation or resubmit the exact same identifier and payload. Do not create a new key just because you have not received a response.

The same identifier with different content may be rejected as a conflict. To change the content, reread the context and decide whether this is genuinely a new send intent.

## On errors

- `409`: read the specific error code. It may be an identity conflict, conversation lock or stale context. Do not retry every `409` unchanged.
- `429`: wait for the time specified in the response. Do not switch connections to get around the limit.
- `held`: track the hold reason and existing operation; do not create a duplicate.
- `confirmation_required`: present the request to the person and wait for a decision.
- `outcome_unknown` or `unverified`: reconcile; do not resend blindly.

## When to stop

Stop when do-not-contact restrictions apply, someone else holds the lock, permissions are revoked, content exceeds your authorization or the outcome is unclear.

See [investigating a failed job](https://tlg.builera.app/en/docs/agent-playbooks/investigate-failed-job) and [Telegram limits](https://tlg.builera.app/en/docs/safety/telegram-limits).

