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

# Telegram Bot

> Trade and manage your portfolio via Telegram

The ouroborai Telegram bot is a thin client built on
[grammY](https://grammy.dev/) that forwards user messages to the agent API
server and renders responses as formatted HTML. It supports slash commands for
common actions and free-form natural language for everything else.

## Commands

| Command               | Description                                |
| --------------------- | ------------------------------------------ |
| `/start`              | Welcome message with command reference     |
| `/health`             | Check API server connectivity              |
| `/trade <prompt>`     | Execute a spot swap via natural language   |
| `/perp <prompt>`      | Open or close a perpetual position         |
| `/portfolio`          | View positions across all protocols        |
| `/timeboost <prompt>` | Query express lane status or trigger a bid |

All command prompts are forwarded verbatim to `POST /agent/prompt` on the API
server. The bot polls the job status endpoint until the result is ready or a
timeout is reached.

## Free-Form Messages

Any text message that does not start with `/` is forwarded directly to the
agent as a natural language prompt. This allows users to type requests like
"swap 100 USDC for ETH" without using a specific command.

## Inline Confirmation Buttons

When the agent response contains action-oriented language (e.g. "confirm" or
"execute"), the bot presents inline keyboard buttons:

<CardGroup cols={2}>
  <Card title="Confirm" icon="check">
    Triggers execution of the proposed action. Each confirmation token is a
    UUID bound to the user ID with a 5-minute TTL.
  </Card>

  <Card title="Cancel" icon="xmark">
    Cancels the proposed action and updates the message text.
  </Card>
</CardGroup>

Confirmation tokens are stored in-memory with periodic cleanup (every 60
seconds). A token is invalidated after use or expiration, preventing replay.

## Architecture

```
User (Telegram) --> grammY Bot --> API Client --> Hono API Server
                                                      |
                                                Agent Runner
                                                      |
                                            Protocol Adapters
```

The bot is stateless beyond the confirmation token store. All agent logic,
thread management, and execution happen on the API server.

## Setup

<AccordionGroup>
  <Accordion title="1. Create a bot with BotFather">
    Open [@BotFather](https://t.me/BotFather) on Telegram and run `/newbot`.
    Copy the bot token.
  </Accordion>

  <Accordion title="2. Set environment variables">
    | Variable             | Required | Description                                       |
    | -------------------- | -------- | ------------------------------------------------- |
    | `TELEGRAM_BOT_TOKEN` | Yes      | Bot token from BotFather                          |
    | `API_URL`            | No       | API server URL (default: `http://localhost:3000`) |
  </Accordion>

  <Accordion title="3. Start the bot">
    ```bash theme={"theme":{"light":"dracula","dark":"dracula"}}
    bun run apps/telegram/src/index.ts
    ```

    The bot starts in **long polling** mode by default. On startup it logs the
    bot username and API URL.
  </Accordion>
</AccordionGroup>

## Deployment

<AccordionGroup>
  <Accordion title="Polling mode (default)">
    Long polling is the simplest deployment -- the bot opens a persistent
    connection to Telegram's servers and receives updates in real time. No
    public URL or TLS certificate required.

    Suitable for development and single-instance production deployments.
  </Accordion>

  <Accordion title="Webhook mode">
    For higher throughput or serverless deployments, configure grammY's webhook
    handler:

    1. Set a public HTTPS URL for the bot.
    2. Call `bot.api.setWebhook(url)` on startup.
    3. Route incoming POST requests to `bot.handleUpdate(update)`.

    See the [grammY webhook guide](https://grammy.dev/guide/deployment-types)
    for framework-specific examples.
  </Accordion>
</AccordionGroup>

## Response Formatting

Bot responses are sent as Telegram HTML. The `formatResponse` helper:

* Escapes HTML entities in agent output to prevent injection.
* Wraps the response in a format suitable for Telegram's HTML parse mode.
* Preserves code blocks and structured data from the agent.

<Note>
  The bot uses `parse_mode: "HTML"` for all messages. Markdown is not used
  because Telegram's Markdown parser is more restrictive and error-prone with
  special characters common in DeFi output (addresses, decimals, etc.).
</Note>

## Error Handling

* **API unreachable** -- `/health` reports the specific error message.
* **Job timeout** -- if the job does not complete within the polling window,
  the bot reports the current status and job ID so the user can check later.
* **Agent failure** -- failed jobs surface the error message from the agent
  runner.
