VK bot with an AI model: Bots Long Poll API and Claude in Python
Build a bot for a VK community that answers through Claude: community setup, Bots Long Poll API, cost tracking from usage and complete code.
5 min · · development · автоматизация
A VK bot with an AI model answers community subscribers in private messages: it consults on products, answers typical questions and takes requests. Below is a Python bot that receives messages via the Bots Long Poll API, sends them to Claude through Zukko and makes sure a single user doesn't spend more than a set budget. You don't need an external server or an open port: the bot polls VK itself.
Community setup
All the steps below follow the official VK for developers documentation. VK sometimes renames menu items, so check it if something differs.
- Enable messages and bot features. In the community: "Manage" → "Messages", turn messages on; in "Bot settings" in the same section, enable "Bot features".
- Create an access key. "Manage" → "Advanced" → "API usage" → "Create key". Grant rights for community messages and community management:
groups.getLongPollServerneeds themanageright, andmessages.sendneedsmessages. - Enable Long Poll. In the same section, on the Long Poll API tab choose "Enabled", and under "Event types" tick "Incoming message" (
message_new). - Find the community ID: the number from an address like
club123456789or from the community settings.
Create a Zukko key of the form fetch_... in the dashboard. It's convenient to give the bot a separate key with a daily dollar limit, so even a bug in the code can't spend more than that.
Installation and environment variables
pip install requests openai python-dotenvThe .env file:
VK_GROUP_ID=123456789
VK_TOKEN=vk1.a.your_community_key
ZUKKO_API_KEY=fetch_...
ZUKKO_MODEL=claude-sonnet-5
How a VK bot with an AI model works
The Bots Long Poll API works in three steps:
- The
groups.getLongPollServermethod returnsserver,keyandts. - The bot requests
{server}?act=a_check&key={key}&ts={ts}&wait=25. The server holds the connection for up to 25 seconds and returns new events in theupdatesarray and a newts. - The next request uses the new
ts.
Each event is an object with type, object and group_id fields. For an incoming message type is message_new, and the message itself is in object.message (since API version 5.103): the text is in text, the conversation address in peer_id. Code from old examples like event[0] == 4 belongs to the User Long Poll and doesn't work for community bots.
The server may reply with an error:
| Response | What to do |
|---|---|
{"failed": 1, "ts": ...} | take the new ts from the response and continue |
{"failed": 2} | the key expired: call groups.getLongPollServer again |
{"failed": 3} | information was lost: get a new key and ts |
API methods are called on the api.vk.ru domain, with the key passed in the Authorization: Bearer ... header, as the VK documentation currently recommends. messages.send requires random_id: a random int32 that protects against duplicate sends. The maximum text length is 9000 characters, so long answers are split into parts.
Tracking spend per user
The API response contains a usage field with the number of input (prompt_tokens) and output (completion_tokens) tokens. Multiply them by the model price and accumulate the total per user per day:
cost = (usage.prompt_tokens * PRICE_IN + usage.completion_tokens * PRICE_OUT) / 1_000_000For claude-sonnet-5 the Zukko price is $0.30 per 1M input and $0.30 per 1M output tokens. If a message with history takes 2,000 input tokens and the answer 500 output tokens, the cost is (2,000 × 0.30 + 500 × 0.30) / 1,000,000 = $0.00075. With a budget of $0.05 per user per day, that's about 0.05 / 0.00075 ≈ 66 such messages. Prices of other models are in the table below; if you change the model, change PRICE_IN/PRICE_OUT too.
This is an estimate on the bot side. Exact charges are shown in the dashboard under "Usage", and a hard ceiling for the whole bot is set with key limits.
Full code
import os
import random
import time
from datetime import date
import requests
from dotenv import load_dotenv
from openai import APIConnectionError, APIStatusError, OpenAI
load_dotenv()
VK_API = "https://api.vk.ru/method/"
VK_VERSION = "5.199"
VK_TOKEN = os.environ["VK_TOKEN"]Run it with python vk_bot.py. Send the community a private message and the bot will answer.
A couple of notes on the code. Messages are processed one at a time: while the model answers one user, the others wait. That's enough for a small community; under heavy load, move handle() into a thread pool or rewrite it with asyncio, AsyncOpenAI and an async HTTP client. History and spend live in memory and are lost on restart; for production, move them to Redis or a database.
Which model to choose
| Model | Zukko price, input/output per 1M tokens | Context |
|---|---|---|
claude-sonnet-5 | $0.30 / $0.30 | 1M |
gpt-5.6-sol | $0.30 / $0.30 | 1M |
gpt-5.6-luna | $0.10 / $0.10 | 1M |
glm-5.3-flash | $0.04 / $0.04 | 128K |
The current list is at GET https://api.zukko.pro/v1/models or on the "Models" page in the dashboard. Test which model answers your subscribers best on your own tasks: collect 20–30 real questions from community messages and compare the answers of two or three models with the same system prompt.
FAQ
The bot doesn't receive messages. What should I check?
Whether the Long Poll API is enabled in the community settings and the "Incoming message" event type is ticked. Whether the key has messages and management rights (without manage, groups.getLongPollServer returns an error). Whether community messages are enabled. The code prints the VK error text, so start there.
Why do answers arrive with a delay?
The model needs time to generate, and messages are processed one by one. Lower max_tokens, ask for shorter answers in the system prompt or parallelize processing.
Can I add the bot to a group chat?
Yes, this is enabled in the community bot settings. By default, in a group chat the bot sees only mentions and replies to its own messages. No code changes are needed: the answer goes to the chat's peer_id, and history is kept per that ID as well.
How do I cap total spend, not just per user?
Set a daily and monthly dollar limit on the Zukko key itself in the dashboard. When the limit is reached, the API returns an error and the bot shows the user a message from ERRORS. More in the key documentation.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- Translating subtitles with a neural network: SRT without broken timecodesThe main risk when translating SRT with a neural network is a broken file structure. A scheme where timecodes never reach the model, and a Python script with validation.
- Editing texts with a neural network: proofreading, style and cuttingDifferent kinds of editing need different prompts. Wording for proofreading, style and cutting, how to get edits with explanations and how not to lose the author's voice.
- A neural network for writing scripts: Bash, PowerShell and PythonA model writes scripts for routine fast, but running them blindly is risky. How to state the task, demand a safe dry-run mode and check the result before launch.
- Dify in Docker: installation, first-run setup and connecting modelsInstall Dify with Docker Compose, create the admin account and connect Claude, GPT and DeepSeek models on one key. Plus what to do when containers will not start.