# Botovod agent quickstart

> Build, register and run a bot connected to this Botovod instance. Documentation is public; provisioning requires the owner's explicit authorization and credentials.

Base URL: `https://botovod.srgkslv.ru`. API version: 1. JSON uses UTF-8.
Read the [API reference](https://botovod.srgkslv.ru/agents/api.md) or [OpenAPI schema](https://botovod.srgkslv.ru/agents/openapi.json) for exact payloads.

## Decide which credentials you have

- `BOT_TOKEN` or a private bot-credentials JSON: the bot already exists. Skip provisioning. Use `/api/bot/*` only.
- `BOTOVOD_EMAIL` and `BOTOVOD_PASSWORD`, supplied by the owner for this task: you may provision a bot using `/api/admin/*`, then discard owner credentials from the runtime environment.
- Neither: implement the bot locally and ask the owner for an existing bot token or authorized provisioning credentials. Do not guess passwords, reuse example tokens, or scrape private files.

## Register a bot once

Use one cookie-preserving client for all three requests. Send `Content-Type: application/json`.

1. `POST https://botovod.srgkslv.ru/api/admin/session`

```json
{"email":"<owner-email>","password":"<owner-password>"}
```

The server sets a `session` cookie and returns `{"email":"<owner-email>","csrf_token":"<csrf-token>"}`. Retain the cookie and CSRF token privately. Login failures are limited: five wrong passwords cause a 15-minute block per source address; login also has a request rate limit.

2. `POST https://botovod.srgkslv.ru/api/admin/bots`, with the session cookie and `X-CSRF-Token: <csrf-token>`:

```json
{"name":"Server Monitor","slug":"server-monitor","description":"Reports server health","quick_commands":["status","help"]}
```

Success is HTTP **201**, for example:

```json
{"id":42,"name":"Server Monitor","slug":"server-monitor","description":"Reports server health","status":"unknown","quick_commands":["status","help"],"chat_url":"/bots/server-monitor","token":"<new-bot-token>"}
```

Save `token` immediately in a private file or secret store. It is returned only at creation. Never put it in source code, URLs, logs, screenshots, or a user-facing report. A slug must be 1–64 lowercase ASCII letters/digits with single hyphens between groups. Choose a stable slug for this bot.

If the request returns **409**, that slug already exists; no token is issued or changed. Use `GET /api/admin/bots` to inspect bots, recover the previously saved token, or ask the owner. Do not automatically rotate tokens, create suffixed duplicates, or retry an ambiguous creation with a new slug. On a timeout, inspect the bot list before deciding whether to retry the same slug.

3. `DELETE https://botovod.srgkslv.ru/api/admin/session`, with the same cookie and CSRF header. Success is HTTP **204**. Run the worker with the bot token, never the owner password/session.

Creating the database record does **not** deploy or start a worker. Run the generated code on a computer/server that can reach this instance, using an appropriate service manager for continuous operation.

## Runnable Python examples

Download [register_bot.py](https://botovod.srgkslv.ru/agents/examples/register_bot.py) and [agent_bot.py](https://botovod.srgkslv.ru/agents/examples/agent_bot.py), then install `httpx`:

```sh
python -m pip install httpx
```

With `BOT_API_URL`, `BOTOVOD_EMAIL` and `BOTOVOD_PASSWORD` already provided through your secure environment:

```sh
python register_bot.py --name "Server Monitor" --slug server-monitor --output bot-credentials.json
```

The registrar reserves a new output file, saves only the runtime token, and signs out. It never prints credentials. Keep the JSON outside version control; on Windows, restrict its folder permissions to the account running the bot. Remove the owner credentials from the worker's environment.

Set `BOT_CONFIG` to the private JSON path, then run:

```sh
python agent_bot.py
```

Alternatively set `BOT_TOKEN` and `BOT_API_URL` directly. The starter supports `status`, `help`, and `echo <text>`; replace these handlers with the requested bot's behavior.

## Worker contract

1. Send `Authorization: Bearer <bot-token>` on every `/api/bot/*` request. Never use the admin session in a worker.
2. Send `POST /api/bot/heartbeat` with `{"status":"online"}` on startup and about every 60 seconds.
3. Poll `GET /api/bot/commands/pending` about every 3 seconds. **This GET claims commands**, changing their state to `taken`; it is not a harmless queue preview or health check. Run one worker per bot.
4. For every returned command, call `POST /api/bot/commands/{id}/complete` with either `{"status":"done","result":"..."}` or `{"status":"failed","error":"..."}`.
5. Post proactive chat messages through `/api/bot/messages`; create Inbox notifications through `/api/bot/events`.
6. Back off on network errors, HTTP 429 and 5xx. Stop on HTTP 401 and recover credentials; do not retry invalid credentials forever. Fix 400/422 payloads before retrying.

Commands are delivered **at least once**. By default unfinished `taken` commands can be reclaimed after 300 seconds (server-configurable). There is no lease-renewal endpoint. Keep work within that window or design durable job handling. Multiple workers and long commands can cause duplicates. Persist completed command IDs before repeating irreversible side effects. Completing the same finished command ID is idempotent, but arbitrary message/event posts are not. The `Idempotency-Key` header on completion is echoed; it is not a general deduplication mechanism.

## Verify the integration

- Confirm heartbeat returns `{"ok":true}`.
- Open `https://botovod.srgkslv.ru/bots/<slug>`, send `status`, and confirm the worker posts its result.
- Send an info event with `also_post_to_chat=true`; verify both Inbox and the chat.
- Report the chat URL, where the worker runs, and how to restart it. Do not report its token.

Use the existing bot only for the owner's requested purpose. Do not change Mattermost integrations or other existing services as part of onboarding a bot.
