A Telegram chat gives an assistant a convenient control surface. It also makes a risky shortcut tempting: pair the bot, tell it to ask before sending, and assume the boundary is enforced. OpenClaw's documentation separates these jobs. Pairing controls who may talk to the bot. Exec approvals control whether a host command may run. A tool that sends an email, publishes a post, or calls an external API may need its own approval gate.
This guide connects a Telegram bot, restricts it to one operator, enables OpenClaw's Telegram approval surface for host execution, and shows how to wrap other outbound tools when host exec approvals do not cover them. The commands and configuration names come from documentation checked on 2026-09-13. The test plan is proposed, not a report of a hands-on run against your installation.
What you are building
The finished setup should have a small, inspectable flow:
- An approved Telegram account sends a request.
- OpenClaw prepares the work or requests a host command.
- The action pauses when the effective policy requires approval.
- The operator sees the exact command, destination, or payload.
- An explicit one-time approval permits that specific operation.
- A denial, timeout, changed payload, or unknown sender leaves the action unexecuted.
That distinction matters. A pairing code is not approval to run a command. A Telegram reply saying yes is not automatically approval for every OpenClaw tool. Keep identity, authority, and action scope as separate decisions.
Prerequisites
You need an OpenClaw installation with a working Gateway, a configured model provider, a Telegram account, access to BotFather, and the current OpenClaw CLI. Prepare a private Telegram chat and a disposable destination for testing. A local test server, an empty folder, or an address under example.invalid is safer than a real mailbox, social account, payment system, or production repository.
You will also need the numeric Telegram user ID of the operator who should approve actions. Use a test identity if possible. Do not put a real bot token in a repository, article, screenshot, prompt, or public diagnostic paste. Telegram says that anyone with the token can control the bot, so treat it as a credential.
1. Create the bot in Telegram
Open the official Telegram Bot Features and BotFather documentation. In Telegram, confirm that the account is exactly @BotFather, send /newbot, follow the prompts, and save the token it returns. Telegram requires a bot username to end in bot.
The token authenticates requests to the Telegram Bot API. Keep it out of shell history when your operating environment makes that possible. If it has already been exposed, replace it through BotFather before continuing and update the OpenClaw token source.
2. Connect Telegram to the Gateway
The official OpenClaw Telegram setup guide documents the quick path:
openclaw channels add --channel telegram --token <BOT_TOKEN>
The placeholder above is not a real token. Use your approved secret-handling method. OpenClaw's Telegram documentation also describes an environment fallback for the default account and account-aware token configuration. Check the installed version before copying a token into a configuration file.
For a first connection, keep direct messages in pairing mode. The resulting configuration should contain the equivalent of:
{
channels: {
telegram: {
enabled: true,
dmPolicy: 'pairing'
}
}
}
Check the channel instead of assuming that a successful CLI command means the bot is ready:
openclaw channels status --probe
If the Gateway is not running, the setup guide documents openclaw gateway start for a managed service and openclaw gateway for a foreground process. Look for an active Telegram account in the status output. The exact formatting is version-sensitive.
3. Pair the operator, then narrow access
Send a harmless message to the new bot. OpenClaw should create a pending DM pairing request. List it and approve it from the CLI:
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
The pairing documentation says that unknown senders are not processed until approval and that pairing codes expire after one hour. A pairing approval grants DM access only. It does not grant group access, node access, or general permission to approve every action.
After the first pairing, identify the numeric Telegram user ID shown in the pairing response or in the relevant Gateway log entry. Use that ID, not a phone number, username, group ID, or the bot's own ID.
For a one-operator bot, replace the temporary pairing policy with an explicit allowlist. This is the shape to adapt in ~/.openclaw/openclaw.json:
{
channels: {
telegram: {
dmPolicy: 'allowlist',
allowFrom: ['123456789']
}
},
commands: {
ownerAllowFrom: ['telegram:123456789']
}
}
The number is an example only. The Telegram access-control documentation recommends numeric IDs for a one-owner allowlist. The CLI can bootstrap the first command owner when the owner list is empty, but setting the owner explicitly makes the configuration easier to inspect. Keep the DM allowlist and the owner list conceptually separate: one controls who can speak to the bot, while the other controls owner-only operations and approval authority.
4. Enable Telegram approval delivery
OpenClaw can deliver host exec approval prompts through Telegram. Add the approval settings under the Telegram channel:
{
channels: {
telegram: {
execApprovals: {
enabled: true,
approvers: ['123456789'],
target: 'dm',
agentFilter: ['main']
},
capabilities: {
inlineButtons: 'dm'
}
}
}
}
These fields follow the current Telegram rich messages and approvals documentation. Approvers must be numeric Telegram user IDs. The dm target keeps approval prompts private. The documentation also supports channel and both, but use those only in groups whose members are trusted because channel delivery can show the approval command in the originating conversation.
allowFrom, groupAllowFrom, and defaultTo decide who can talk to the bot and where normal replies go. They do not, by themselves, make somebody an exec approver. Keep the operator ID in execApprovals.approvers when you want the intent to be obvious.
Inline buttons are a presentation layer. The inlineButtons setting must allow the same target surface. If the native approval client is unavailable, OpenClaw can retain a text fallback with the exact approval command.
5. Make the host policy ask every time
Telegram only carries the approval request. The execution host decides whether an approval is required. OpenClaw documents ask: 'always' as the policy that prompts for every host command, while askFallback: 'deny' blocks the command when no approval UI is reachable or the prompt times out.
Use the documented local policy command:
openclaw exec-policy set --host gateway --security full --ask always --ask-fallback deny
openclaw exec-policy show --json
This is a deliberately strict starting point for a test workflow. It asks for every host command, including commands that might otherwise match a trusted allowlist. Do not use a no-prompt or YOLO preset for this exercise. For a real deployment, reduce the available command surface as well as requiring approval.
The distinction is important: security describes what the host can permit, ask describes when a human decision is needed, and askFallback describes what happens when that decision cannot be obtained. A Telegram button cannot make a denied host policy run, and an unavailable Telegram client should not silently turn a pending operation into an allowed one.
6. Approve one exact operation
Ask the agent to perform a harmless host action that reaches the approval layer. With the policy above, OpenClaw should create an approval request and deliver it to the configured Telegram approver DM. The advanced approval documentation describes Telegram as a native approval client and says that the underlying host policy still decides whether the request needs approval.
Read the entire prompt before approving. Check the agent and host, command, working directory, arguments, and any destination or payload shown in the request. Choose the one-time option when the action should run only now. In a Telegram text fallback, the form is:
/approve <ID> allow-once
Use deny when the request is unexpected. Avoid allow-always until you have deliberately reviewed its scope. OpenClaw documents durable grants for exact operations, and some grants are bound to command arguments and working directory. A standing grant is a different decision from approving one test.
If you need to inspect the queue outside Telegram, the CLI reference documents:
openclaw approvals pending --json
openclaw approvals resolve <ID> allow-once
openclaw approvals resolve <ID> deny
The OpenClaw approvals CLI reference says that pending records can include exec and plugin approvals. Resolve the complete ID shown by the approval surface. A shortened display token or a stale ID should not be guessed.
Exec approvals normally expire after 30 minutes by default. That is separate from the one-hour Telegram DM pairing code. Keep both timers in your operational notes.
When the action is not host exec
This is the boundary that prevents a misleading setup. If the agent sends an email through a first-class message tool, publishes through a plugin, or calls an API through a dedicated integration, the Telegram execApprovals block does not automatically mean that every such call will pause. The OpenClaw documentation treats exec approvals and plugin approvals as separate mechanisms. It also describes typed summaries such as message-send and external-post as display information, not authorization.
For an arbitrary outbound tool, put the approval check around the tool itself. The following is application-level pseudocode, not a built-in OpenClaw configuration block:
pending = create_pending_action(
action_id = random_id(),
destination = destination,
payload = payload,
expires_at = now + 10_minutes,
payload_hash = hash(destination + payload)
)
send_preview_to_operator_dm(pending)
if decision != 'approve' or decision.action_id != pending.action_id:
reject()
if now > pending.expires_at:
reject()
if hash(current_destination + current_payload) != pending.payload_hash:
reject()
consume_pending_atomically(pending.action_id)
perform_outbound(pending.payload)
The agent should receive a prepare operation, not unrestricted access to the final send function. The preview should show the exact recipient or endpoint, content, attachments, account, expiry, and action ID. If any material field changes, create a new pending record. Do not treat a natural-language reply such as yes or looks good as approval when several actions are visible in one chat.
If you are authoring a plugin, use OpenClaw's documented plugin permission request path and configure the matching plugin approval surface. If you are not authoring a plugin, keep the wrapper in your own application and label its command as custom. A custom confirmation command is not the same thing as OpenClaw's native /approve, which resolves pending exec or plugin approval records.
Test the refusal paths first
Use disposable data and record the Telegram message, approval ID, Gateway log entry, host result, and test-server log. These are proposed acceptance tests, not claimed results:
- Message the bot from an unpaired account. It should not enter the agent workflow.
- Send a request from the paired operator that needs only a draft or read operation. Confirm that no outbound tool is called.
- Request a harmless host command. Confirm that the approval arrives in the operator DM and that no command result exists before approval.
- Choose
allow-once. Confirm one execution, then submit the same approval ID again. The second attempt should not execute. - Choose
deny. Confirm that the host command or outbound request did not run. - Let an approval expire or make the approval UI unreachable. With
askFallbackset to deny, the action should remain blocked. - Change the command, working directory, recipient, or payload after the preview. A built-in host request should be re-evaluated where its binding rules apply; a custom wrapper must reject the old hash and create a new preview.
- Call the non-exec outbound tool directly. Confirm that the wrapper refuses it without a matching, unexpired approval record.
For a Telegram group, test membership, mention gating, and approval routing separately. A DM pairing approval does not authorize group commands. Keep target: 'dm' until the private workflow is understood.
Failure paths and limits
If /start produces no usable reply, the official OpenClaw troubleshooting guide recommends checking openclaw pairing list telegram. A startup error such as getMe returned 401 points to the token source; re-copy or regenerate the BotFather token instead of weakening the access policy.
If the bot replies but no approval appears, check the effective host policy first. A channel approval block cannot create a prompt when the action is not a host exec request or when the effective ask policy is off. Then check that the approver is a numeric ID, the agent and session filters match, and the target is allowed by inlineButtons. Use the text fallback when the native runtime is not active.
If a group stays silent, remember that Telegram privacy mode and OpenClaw group policy are separate controls. The bot may need a mention, a group allowlist entry, or an appropriate BotFather setting. Do not open all groups merely to diagnose one missing reply.
Finally, approval is a review surface, not a guarantee that the request is wise. A forwarded document, pasted log, or web page can contain instructions aimed at the model. Keep the tool set narrow, use a dedicated test account, and read the exact target before approving. If multiple people can DM the bot, use an isolated DM session scope and consider separate Gateways for mutually untrusted users.
Sources
- OpenClaw Telegram setup: BotFather flow, token configuration, channel probing, first DM pairing, and group setup. Accessed 2026-09-13.
- OpenClaw Telegram access control: DM policies, numeric allowlists, owner identity, group separation, and user-ID discovery. Accessed 2026-09-13.
- OpenClaw Telegram rich messages and approvals: Telegram approval targets, numeric approvers, inline buttons, and approval expiry. Accessed 2026-09-13.
- OpenClaw exec approvals, advanced: native Telegram approval delivery, text fallback, and the role of host policy. Accessed 2026-09-13.
- OpenClaw exec approvals: host policy values, always-ask behavior, fallback denial, and approval scope. Accessed 2026-09-13.
- OpenClaw approvals CLI: pending approval inspection and allow-once, allow-always, or deny resolution. Accessed 2026-09-13.
- OpenClaw channel troubleshooting: Telegram pairing, token, polling, and group failure paths. Accessed 2026-09-13.
- Telegram Bot Features and BotFather: bot creation, usernames, authentication tokens, and token security. Accessed 2026-09-13.
Reference Trail
Sources and further reading
- Telegram Bot Features and BotFather documentationcore.telegram.org
- OpenClaw Telegram setup guidedocs.openclaw.ai
- Telegram access-control documentationdocs.openclaw.ai
- Telegram rich messages and approvals documentationdocs.openclaw.ai
- advanced approval documentationdocs.openclaw.ai