Setup your private AI agent connected to Telegram, Gemini Flash, and Tavily web search — at zero ongoing cost.
Nanobot is an autonomous AI agent — it takes real actions and makes real API calls. Understand these risks first:
Nanobot can misinterpret instructions and take unintended actions — looping searches, rewriting files, or sending unexpected messages. Always test in a supervised session before leaving it unattended.
A runaway tool loop or leaked API key can exhaust your Gemini or Tavily quotas fast. Set GCP budget alerts (Section 8) before running Nanobot unattended. The maxToolIterations limit in config provides a safety cap.
If your Telegram bot token or API keys are leaked — from a public repo, shared screenshot, or log file — an attacker can control your agent and rack up API costs. Treat every key like a bank password.
Everything you send to the bot is transmitted to Google Gemini (for processing) and Tavily (for web search). Do not share private data, passwords, or confidential business information with the bot.
This guide is an independent community resource created by Commune.AI. It is provided "as is" without warranty of any kind. Commune.AI, its affiliates, and contributors accept no liability for any damages, costs, or losses arising from the use of this guide, including but not limited to misconfiguration, API charges, data exposure, or service disruptions. By proceeding, you acknowledge that you use this guide entirely at your own risk. Not affiliated with Google LLC, HKUDS/nanobot, Telegram, Tavily, or any third-party service mentioned herein.
ORANGE_VALUES in code blocks are placeholders you must replace. Fill in the input fields in each section — code snippets update automatically.
Collect the items below as you work through each section. Enter your Project ID here now — it will populate all GCP commands automatically.
| Item | Where to get it | Cost |
|---|---|---|
| Google account | accounts.google.com | Free |
| GCP project + billing | console.cloud.google.com | Free |
| Telegram account | telegram.org | Free |
| Gemini API key | aistudio.google.com — Section 3 | Free tier |
| Tavily API key | app.tavily.com — Section 4 | Free · No CC |
Find it: GCP Console → project picker (top-left) → note the ID column (e.g. my-project-123456).
Creates a zero-permission service account, a free-tier e2-micro VM, and automatically configures a 2 GB swap file on first boot — all in one step.
gcloud.The script uses your Project ID entered above. You can also customise the VM and service account names:
Paste the whole script into Cloud Shell and press Enter:
#!/usr/bin/env bash # ── Edit if needed ─────────────────────────────────── PROJECT_ID="YOUR_PROJECT_ID" ZONE="us-central1-a" # keep for Always Free tier # ───────────────────────────────────────────────────── set -euo pipefail trap 'echo "❌ Script aborted on line $LINENO. Check the gcloud error above." >&2' ERR VM_NAME="nanobot-vm" ; SA_NAME="nanobot-sa" echo "🔌 Enabling APIs (Compute + IAM)…" gcloud services enable compute.googleapis.com iam.googleapis.com \ --project="$PROJECT_ID" echo " ↳ APIs confirmed." echo "🔐 Creating restricted service account (no IAM roles)…" set +e # Allow SA creation to fail without stopping script gcloud iam service-accounts create "$SA_NAME" \ --display-name="Nanobot SA — zero GCP permissions" \ --project="$PROJECT_ID" 2>&1 | grep -q "already exists" && echo " ↳ Service account already exists (OK)" || true set -e # Re-enable exit on error SA_EMAIL="${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" echo "🖥️ Creating free-tier VM (with swap auto-configured on first boot)…" # Write startup script to temp file (configures 2GB swap on first boot) cat > /tmp/startup.sh << 'STARTUP_EOF' #!/bin/bash if [ ! -f /swapfile ]; then fallocate -l 2G /swapfile && chmod 600 /swapfile mkswap /swapfile && swapon /swapfile echo "/swapfile none swap sw 0 0" >> /etc/fstab sysctl -w vm.swappiness=10 echo "vm.swappiness=10" >> /etc/sysctl.conf fi STARTUP_EOF gcloud compute instances create "$VM_NAME" \ --project="$PROJECT_ID" \ --zone="$ZONE" \ --machine-type=e2-micro \ --image-project=debian-cloud \ --image-family=debian-12 \ --boot-disk-size=10GB \ --boot-disk-type=pd-standard \ --boot-disk-auto-delete \ --service-account="$SA_EMAIL" \ --scopes=https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write \ --metadata=block-project-ssh-keys=true \ --metadata-from-file=startup-script=/tmp/startup.sh rm /tmp/startup.sh echo "" echo "✅ VM ready! 2 GB swap will be live by the time you SSH in." echo "" echo "▶ SSH into your VM:" echo " gcloud compute ssh $VM_NAME --zone=$ZONE --project=$PROJECT_ID"
Wait ~60 seconds for the VM to boot, then open an SSH session. You can use the Cloud Shell command below, or click the SSH button next to the VM in the GCP Console.
gcloud compute ssh nanobot-vm \
--zone=us-central1-a \
--project="YOUR_PROJECT_ID"
free -h — you should see ~2.0G in the Swap row. If it shows 0, the startup script is still running; wait 30 s and check again.The fastest way is a single Cloud Shell command. No roles are granted — this is intentional.
gcloud iam service-accounts create nanobot-sa \
--display-name="Nanobot SA — zero GCP permissions" \
--project="YOUR_PROJECT_ID"
Or via the Console: IAM & Admin → Service Accounts → + Create Service Account — fill name nanobot-sa, skip the roles step, click Done. Do not create or download a JSON key.
us-central1 Zone: us-central1-a
us-central1 or us-west1. Any other region incurs compute charges.nanobot-sa.SSH in via the GCP Console → VM instances → SSH button next to nanobot-vm. Then run:
sudo bash -c ' fallocate -l 2G /swapfile && chmod 600 /swapfile mkswap /swapfile -q && swapon /swapfile echo "/swapfile none swap sw 0 0" >> /etc/fstab sysctl -w vm.swappiness=10 > /dev/null echo "vm.swappiness=10" >> /etc/sysctl.conf echo "✅ 2 GB swap active"; free -h '
With GCP done, collect your API keys in Sections 2–4 before installing Nanobot.
/newbot.My Nanobot.bot, e.g. mynanobot_xyz_bot.7012345678:AAFxxxxxxxxxxxxxxx. Copy it.Id: 123456789 — that number is your User ID.allowFrom is silently ignored — strangers cannot command your bot. Numeric IDs are permanent; usernames can change.AIzaSy...| Free tier limit | Allowance |
|---|---|
| Requests/day (Gemini 2.0 Flash) | 1,500 |
| Tokens/minute | 1,000,000 |
| GCP billing impact | None — tracked separately via AI Studio |
Tavily is an AI-native search API — free for 1,000 queries/month with no credit card required. Nanobot uses it to answer questions about current events beyond its training data.
nanobot.tvly-.| Free tier limit | Allowance |
|---|---|
| Searches/month | 1,000 |
| Credit card | Not required |
| Overage cost | $5 per 1,000 additional searches |
SSH into the VM first, then run whoami to find your username:
whoami
whoami command above.
All six values from Sections 0–5.1 are pre-filled below if you entered them. Verify the top six lines, then paste the entire script into the VM terminal:
#!/usr/bin/env bash # ── Your values (pre-filled from the form above) ────────────────────────────── LINUX_USER="YOUR_LINUX_USERNAME" TELEGRAM_TOKEN="YOUR_TELEGRAM_BOT_TOKEN" TELEGRAM_USER_ID=YOUR_TELEGRAM_USER_ID GEMINI_API_KEY="YOUR_GEMINI_API_KEY" TAVILY_API_KEY="YOUR_TAVILY_API_KEY" # ────────────────────────────────────────────────────────────────────────────── set -euo pipefail NANOBOT_DIR="/home/${LINUX_USER}/.nanobot" echo "📦 Updating system…" sudo apt-get update -qq && sudo apt-get upgrade -y -qq echo "🐍 Installing Python…" sudo apt-get install -y -qq python3-venv python3-pip echo "📁 Creating directories…" mkdir -p "${NANOBOT_DIR}/workspace" echo "🔧 Creating virtual environment…" python3 -m venv "${NANOBOT_DIR}/venv" echo "📥 Installing nanobot-ai…" "${NANOBOT_DIR}/venv/bin/pip" install --upgrade pip -q "${NANOBOT_DIR}/venv/bin/pip" install nanobot-ai -q echo "📝 Writing config.json…" cat > "${NANOBOT_DIR}/config.json" << EOF { "agents": { "defaults": { "workspace": "/home/${LINUX_USER}/.nanobot/workspace", "model": "google/gemini-2.0-flash", "maxToolIterations": 20 } }, "providers": { "google": { "apiKey": "${GEMINI_API_KEY}" } }, "channels": { "telegram": { "enabled": true, "token": "${TELEGRAM_TOKEN}", "allowFrom": [${TELEGRAM_USER_ID}] } }, "tools": { "web": { "search": { "type": "tavily", "apiKey": "${TAVILY_API_KEY}", "maxResults": 5 } }, "exec": { "enabled": false } } } EOF chmod 600 "${NANOBOT_DIR}/config.json" echo "" echo "════════════════════════════════════════════" echo "✅ Nanobot installed successfully!" echo "════════════════════════════════════════════" echo "" echo "▶ Test (foreground): ~/.nanobot/venv/bin/nanobot gateway" echo "▶ Background: nohup ~/.nanobot/venv/bin/nanobot gateway > ~/.nanobot/nanobot.log 2>&1 &"
sudo apt-get update && sudo apt-get upgrade -y sudo apt-get install -y python3-venv python3-pip
mkdir -p ~/.nanobot/workspace python3 -m venv ~/.nanobot/venv
~/.nanobot/venv/bin/pip install --upgrade pip ~/.nanobot/venv/bin/pip install nanobot-ai
~/.nanobot/venv/bin/nanobot --version
nano ~/.nanobot/config.json
{
"agents": {
"defaults": {
"workspace": "/home/YOUR_LINUX_USERNAME/.nanobot/workspace",
"model": "google/gemini-2.0-flash",
"maxToolIterations": 20
}
},
"providers": {
"google": { "apiKey": "YOUR_GEMINI_API_KEY" }
},
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_TELEGRAM_BOT_TOKEN",
"allowFrom": [YOUR_TELEGRAM_USER_ID]
}
},
"tools": {
"web": {
"search": {
"type": "tavily",
"apiKey": "YOUR_TAVILY_API_KEY",
"maxResults": 5
}
},
"exec": { "enabled": false }
}
}
chmod 600 ~/.nanobot/config.json
| Key | Purpose & security note |
|---|---|
| channels.telegram.allowFrom | Security control. Only this numeric User ID can send commands. All others silently ignored. Must be a number — not a quoted string. |
| tools.exec.enabled: false | Containment. Prevents Nanobot from running shell commands — it cannot modify the OS, install software, or attempt to escape the VM. |
| tools.web.search.type: "tavily" | Selects Tavily as the web search backend (added in nanobot PR #93, Feb 2026). |
| maxToolIterations: 20 | Caps tool calls per response — prevents runaway loops from exhausting API quotas. |
Running as a system service (auto-start on boot, auto-restart on crash) is in Appendix A. For most learners, start here:
Watch all output in real time. Press Ctrl+C to stop.
~/.nanobot/venv/bin/nanobot gateway
nohup ~/.nanobot/venv/bin/nanobot gateway \ > ~/.nanobot/nanobot.log 2>&1 & echo "Started. PID: $!"
| Task | Command |
|---|---|
| Check running | pgrep -a nanobot |
| Watch live logs | tail -f ~/.nanobot/nanobot.log |
| Stop it | pkill -f "nanobot gateway" |
/start. Nanobot should reply.allowFrom value in config.json — ensure it is a number, not a quoted string.Nanobot Budget · Projects: your project · Type: Monthly · Amount: $5 (safety net — normal spend is $0).| % | At $5 budget triggers at | Suggested action |
|---|---|---|
| 50% | $2.50 | Investigate — something may be running outside the free tier. |
| 90% | $4.50 | Stop non-essential resources immediately. |
| 100% | $5.00 | Review all active GCP resources now. |
| Resource | Free allowance/month | This guide's usage |
|---|---|---|
| e2-micro VM (us-central1) | 1 instance | 1 ✅ |
| pd-standard disk | 30 GB | 10 GB ✅ |
| Network egress (Americas/EMEA) | 1 GB | Low ✅ |
| Gemini 2.0 Flash (AI Studio) | 1,500 req/day | Low ✅ |
| Tavily Search | 1,000 queries/mo | Low ✅ |
| Ephemeral external IP (running VM) | Free | Free ✅ |
| Feature | nohup (Section 6) | systemd (this appendix) |
|---|---|---|
| Survives SSH disconnect | ✅ | ✅ |
| Auto-restarts on crash | ❌ | ✅ |
| Starts on VM reboot | ❌ | ✅ |
| OS-level filesystem sandbox | ❌ | ✅ |
pkill -f "nanobot gateway" 2>/dev/null || true
sudo nano /etc/systemd/system/nanobot.service
Paste — replace the four occurrences of YOUR_LINUX_USERNAME:
[Unit] Description=Nanobot AI Agent After=network-online.target Wants=network-online.target [Service] User=YOUR_LINUX_USERNAME WorkingDirectory=/home/YOUR_LINUX_USERNAME Environment=HOME=/home/YOUR_LINUX_USERNAME ExecStart=/home/YOUR_LINUX_USERNAME/.nanobot/venv/bin/nanobot gateway Restart=always RestartSec=10 NoNewPrivileges=true ProtectSystem=strict ProtectHome=read-only ReadWritePaths=/home/YOUR_LINUX_USERNAME/.nanobot PrivateTmp=true [Install] WantedBy=multi-user.target
sudo systemctl daemon-reload sudo systemctl enable nanobot sudo systemctl start nanobot sudo systemctl status nanobot --no-pager
| Command | When to use |
|---|---|
| sudo systemctl restart nanobot | After editing config.json. |
| sudo systemctl stop nanobot | To pause Nanobot. |
| sudo systemctl disable nanobot | Prevent auto-start on boot. |
| sudo systemctl daemon-reload | Required after editing the .service file. |
tail -f ~/.nanobot/nanobot.log
sudo journalctl -u nanobot -f
sudo journalctl -u nanobot -n 100 --no-pager
ERROR or Traceback. Common culprits: wrong API key, invalid bot token, JSON syntax error in config.python3 -m json.tool ~/.nanobot/config.json
Valid = formatted JSON prints. Error = line number where parsing failed.
@BotFather → /mybots → select bot → API Token → update config.json → restart Nanobot.
Visit aistudio.google.com, verify or regenerate the key, update config.json, restart.
allowFrom is a number, not a string: [123456789] not ["123456789"]."type": "tavily" is present in the search config block.Use Brave Search if Tavily is unavailable in your region. New accounts require a credit card and receive $5/month in credits (~1,000 queries).
nanobot → copy the key (starts with BSA...).~/.nanobot/config.json, replace the search block:
"search": {
"type": "brave",
"apiKey": "YOUR_BRAVE_API_KEY",
"maxResults": 5
}