Overview
nanobot supports running multiple instances simultaneously, each with its own:
Configuration file (config.json)
Workspace directory (memory, sessions, cron jobs)
Gateway port
Channel connections
Model and provider settings
This is useful for:
Connecting to multiple chat platforms with different configs
Running separate bots for different teams or projects
Testing configurations without affecting production
Isolating workspaces for security or organizational purposes
Command-Line Options
Each nanobot command accepts these flags:
Option Short Default Description --workspace-w~/.nanobot/workspaceWorkspace directory (MEMORY.md, sessions, cron) --config-c~/.nanobot/config.jsonConfiguration file path --port-p18790Gateway port
Basic Usage
Example: Telegram and Discord Bots
Create separate directories
mkdir -p ~/.nanobot/telegram
mkdir -p ~/.nanobot/discord
Initialize configurations
Initialize each instance: # Telegram instance
nanobot onboard -w ~/.nanobot/telegram
# Discord instance
nanobot onboard -w ~/.nanobot/discord
Each creates its own config.json and workspace.
Configure channels
Edit ~/.nanobot/telegram/config.json: {
"providers" : {
"openrouter" : {
"apiKey" : "sk-or-v1-xxx"
}
},
"agents" : {
"defaults" : {
"model" : "anthropic/claude-opus-4-5"
}
},
"channels" : {
"telegram" : {
"enabled" : true ,
"token" : "TELEGRAM_BOT_TOKEN" ,
"allowFrom" : [ "your_telegram_user_id" ]
}
}
}
Edit ~/.nanobot/discord/config.json: {
"providers" : {
"openrouter" : {
"apiKey" : "sk-or-v1-xxx"
}
},
"agents" : {
"defaults" : {
"model" : "anthropic/claude-opus-4-5"
}
},
"channels" : {
"discord" : {
"enabled" : true ,
"token" : "DISCORD_BOT_TOKEN" ,
"allowFrom" : [ "your_discord_user_id" ]
}
}
}
Run both gateways
In separate terminal windows: # Terminal 1: Telegram bot
nanobot gateway -w ~/.nanobot/telegram -p 18791
# Terminal 2: Discord bot
nanobot gateway -w ~/.nanobot/discord -p 18792
Each instance must use a different port to avoid conflicts. The default is 18790.
Instance Isolation
Each instance is completely isolated:
Workspace Separation
~ /.nanobot/
├── telegram/
│ ├── config.json
│ ├── workspace/
│ │ ├── MEMORY.md # Telegram bot's memory
│ │ ├── HEARTBEAT.md # Telegram bot's periodic tasks
│ │ ├── cron/
│ │ │ └── jobs.json # Telegram bot's cron jobs
│ │ └── sessions/ # Telegram conversation sessions
│ └── .whatsapp-session/ # (if using WhatsApp)
├── discord/
│ ├── config.json
│ ├── workspace/
│ │ ├── MEMORY.md # Discord bot's memory
│ │ ├── HEARTBEAT.md # Discord bot's periodic tasks
│ │ ├── cron/
│ │ │ └── jobs.json # Discord bot's cron jobs
│ │ └── sessions/ # Discord conversation sessions
│ └── matrix-store/ # (if using Matrix)
└── workspace/ # Default instance
Configuration Independence
Each instance can have:
Different LLM providers (OpenRouter, Anthropic, OpenAI, etc.)
Different models (GPT-4, Claude, Gemini, etc.)
Different enabled channels
Different security settings (workspace restrictions, allow lists)
Different tools (MCP servers, skills)
Port Assignment
Assign unique ports to each instance:
# Instance A: Telegram
nanobot gateway -w ~/.nanobot/telegram -p 18791
# Instance B: Discord
nanobot gateway -w ~/.nanobot/discord -p 18792
# Instance C: Feishu
nanobot gateway -w ~/.nanobot/feishu -p 18793
Deployment Methods
Manual (Terminal Windows)
Run each instance in a separate terminal:
# Terminal 1
nanobot gateway -w ~/.nanobot/botA -p 18791
# Terminal 2
nanobot gateway -w ~/.nanobot/botB -p 18792
This method is only suitable for development. Use systemd or Docker for production.
Using tmux/screen
Run instances in persistent terminal sessions:
# Create tmux sessions
tmux new -s nanobot-telegram -d "nanobot gateway -w ~/.nanobot/telegram -p 18791"
tmux new -s nanobot-discord -d "nanobot gateway -w ~/.nanobot/discord -p 18792"
# List sessions
tmux ls
# Attach to a session
tmux attach -t nanobot-telegram
# Kill sessions
tmux kill-session -t nanobot-telegram
Using systemd (Linux)
Create separate service files for each instance:
~/.config/systemd/user/nanobot-telegram.service:
[Unit]
Description =Nanobot Gateway (Telegram)
After =network.target
[Service]
Type =simple
ExecStart =%h/.local/bin/nanobot gateway -w %h/.nanobot/telegram -p 18791
Restart =always
RestartSec =10
NoNewPrivileges =yes
ProtectSystem =strict
ReadWritePaths =%h/.nanobot/telegram
[Install]
WantedBy =default.target
~/.config/systemd/user/nanobot-discord.service:
[Unit]
Description =Nanobot Gateway (Discord)
After =network.target
[Service]
Type =simple
ExecStart =%h/.local/bin/nanobot gateway -w %h/.nanobot/discord -p 18792
Restart =always
RestartSec =10
NoNewPrivileges =yes
ProtectSystem =strict
ReadWritePaths =%h/.nanobot/discord
[Install]
WantedBy =default.target
Enable and start:
systemctl --user daemon-reload
systemctl --user enable --now nanobot-telegram nanobot-discord
# Check status
systemctl --user status nanobot-telegram
systemctl --user status nanobot-discord
# Enable lingering for 24/7 operation
loginctl enable-linger $USER
See Linux Service for more details.
Using Docker Compose
docker-compose.yml:
version : '3.8'
services :
nanobot-telegram :
build : .
container_name : nanobot-telegram
command : [ "gateway" , "-w" , "/root/.nanobot" , "-p" , "18791" ]
restart : unless-stopped
volumes :
- ~/.nanobot/telegram:/root/.nanobot
ports :
- 18791:18791
deploy :
resources :
limits :
cpus : '0.5'
memory : 512M
nanobot-discord :
build : .
container_name : nanobot-discord
command : [ "gateway" , "-w" , "/root/.nanobot" , "-p" , "18792" ]
restart : unless-stopped
volumes :
- ~/.nanobot/discord:/root/.nanobot
ports :
- 18792:18792
deploy :
resources :
limits :
cpus : '0.5'
memory : 512M
nanobot-feishu :
build : .
container_name : nanobot-feishu
command : [ "gateway" , "-w" , "/root/.nanobot" , "-p" , "18793" ]
restart : unless-stopped
volumes :
- ~/.nanobot/feishu:/root/.nanobot
ports :
- 18793:18793
deploy :
resources :
limits :
cpus : '0.5'
memory : 512M
Start all instances:
docker compose up -d
# View logs
docker compose logs -f nanobot-telegram
docker compose logs -f nanobot-discord
# Stop all
docker compose down
See Docker Deployment for more details.
Advanced Configurations
Different Models per Instance
Production bot (uses Claude Opus):
{
"agents" : {
"defaults" : {
"model" : "anthropic/claude-opus-4-5" ,
"provider" : "openrouter"
}
}
}
Testing bot (uses cheaper model):
{
"agents" : {
"defaults" : {
"model" : "anthropic/claude-3.5-sonnet" ,
"provider" : "openrouter"
}
}
}
Different Providers per Instance
Instance A (uses OpenRouter):
{
"providers" : {
"openrouter" : {
"apiKey" : "sk-or-v1-xxx"
}
},
"agents" : {
"defaults" : {
"model" : "anthropic/claude-opus-4-5" ,
"provider" : "openrouter"
}
}
}
Instance B (uses Anthropic directly):
{
"providers" : {
"anthropic" : {
"apiKey" : "sk-ant-xxx"
}
},
"agents" : {
"defaults" : {
"model" : "claude-opus-4-5" ,
"provider" : "anthropic"
}
}
}
Security Isolation
Production instance (restricted workspace):
{
"tools" : {
"restrictToWorkspace" : true ,
"exec" : {
"pathAppend" : ""
}
},
"channels" : {
"telegram" : {
"enabled" : true ,
"allowFrom" : [ "admin_user_id" ]
}
}
}
Development instance (unrestricted):
{
"tools" : {
"restrictToWorkspace" : false
},
"channels" : {
"telegram" : {
"enabled" : true ,
"allowFrom" : [ "dev_user_id" ]
}
}
}
Different MCP Servers per Instance
Data analysis bot (has database access):
{
"tools" : {
"mcpServers" : {
"postgres" : {
"command" : "npx" ,
"args" : [ "-y" , "@modelcontextprotocol/server-postgres" , "postgresql://..." ]
}
}
}
}
File management bot (has filesystem access):
{
"tools" : {
"mcpServers" : {
"filesystem" : {
"command" : "npx" ,
"args" : [ "-y" , "@modelcontextprotocol/server-filesystem" , "/data" ]
}
}
}
}
CLI Operations per Instance
Run CLI commands against specific instances:
# Check status of specific instance
nanobot status -w ~/.nanobot/telegram
# Chat with specific instance
nanobot agent -w ~/.nanobot/telegram -m "Hello"
# Interactive chat with specific instance
nanobot agent -w ~/.nanobot/discord
# Check channel status
nanobot channels status -w ~/.nanobot/telegram
Monitoring Multiple Instances
Check All Instance Statuses
#!/bin/bash
# check-instances.sh
for instance in telegram discord feishu ; do
echo "=== $instance ==="
nanobot status -w ~/.nanobot/ $instance
echo
done
Monitor Logs (systemd)
# Follow all instance logs
journalctl --user -u nanobot-telegram -u nanobot-discord -u nanobot-feishu -f
# Check if all instances are running
systemctl --user status nanobot-telegram nanobot-discord nanobot-feishu
Monitor Containers (Docker)
# View all instance statuses
docker compose ps
# Follow all logs
docker compose logs -f
# Check resource usage
docker stats
Load Balancing
For high-traffic deployments, run multiple instances behind a load balancer:
services :
nanobot-1 :
build : .
command : [ "gateway" , "-p" , "18790" ]
volumes :
- nanobot-shared-config:/root/.nanobot
networks :
- nanobot-net
nanobot-2 :
build : .
command : [ "gateway" , "-p" , "18790" ]
volumes :
- nanobot-shared-config:/root/.nanobot
networks :
- nanobot-net
nginx :
image : nginx:alpine
ports :
- 18790:18790
volumes :
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on :
- nanobot-1
- nanobot-2
networks :
- nanobot-net
volumes :
nanobot-shared-config :
networks :
nanobot-net :
Load balancing requires careful session management. Ensure session affinity (sticky sessions) is configured in your load balancer.
Troubleshooting
Port Conflicts
Error: Address already in use
Solution: Check which instance is using the port:
Either stop the conflicting instance or use a different port.
Config File Not Found
Error: Config file not found: ~/.nanobot/config.json
Solution: Specify the correct config path:
nanobot gateway -w ~/.nanobot/telegram -c ~/.nanobot/telegram/config.json
Or ensure the config exists in the workspace directory:
ls -la ~/.nanobot/telegram/config.json
Workspace Conflicts
Error: Sessions from different instances interfering
Solution: Always use separate workspace directories:
# Bad: Both instances share default workspace
nanobot gateway -p 18791 # Uses ~/.nanobot/workspace
nanobot gateway -p 18792 # Uses ~/.nanobot/workspace (conflict!)
# Good: Separate workspaces
nanobot gateway -w ~/.nanobot/telegram -p 18791
nanobot gateway -w ~/.nanobot/discord -p 18792
Instance Won’t Start
Check logs:
systemd:
journalctl --user -u nanobot-telegram -n 50
Docker:
docker compose logs nanobot-telegram
Common issues:
Port already in use (use different port)
Missing config file (run nanobot onboard -w <workspace>)
Invalid JSON in config (validate with jq)
Missing API keys
High Memory Usage with Multiple Instances
Set resource limits:
systemd:
[Service]
MemoryMax =512M
CPUQuota =50%
Docker Compose:
deploy :
resources :
limits :
cpus : '0.5'
memory : 512M
Best Practices
Use Cases
Team Collaboration
Run separate instances for different teams:
Marketing team : Telegram bot with content creation skills
Engineering team : Discord bot with code execution and GitHub integration
Support team : Email bot with knowledge base access
Environment Separation
Production : Stable model, workspace restrictions, allow list
Staging : Latest model, moderate restrictions, QA team access
Development : Experimental features, no restrictions, developer access
Channel Specialization
Public bot : Restrictive config, rate limiting, limited tools
Private bot : Full access, all tools, trusted users only
Geographic Distribution
US instance : Uses US-based providers, US timezone
EU instance : Uses EU-based providers, GDPR compliance, EU timezone
APAC instance : Uses APAC providers, APAC timezone
Next Steps
Docker Deployment Container-based deployment for multiple instances
Linux Service systemd service configuration for multiple instances
Channel Setup Configure different channels per instance
Configuration Complete configuration reference