[louisho5/picobot] Configuration Reference
ChatGPT
API Leak/ChatGPT
15,466 characters
# Configuration Reference
Picobot is configured via `~/.picobot/config.json`. Run `picobot onboard` to generate the default config.
## Full Default Config
```json
{
"agents": {
"defaults": {
"workspace": "~/.picobot/workspace",
"model": "stub-model",
"maxTokens": 8192,
"temperature": 0.7,
"maxToolIterations": 100,
"heartbeatIntervalS": 60,
"requestTimeoutS": 60,
"enableToolActivityIndicator": true
}
},
"mcpServers": {},
"channels": {
"telegram": {
"enabled": false,
"token": "",
"allowFrom": []
},
"discord": {
"enabled": false,
"token": "",
"allowFrom": []
},
"slack": {
"enabled": false,
"appToken": "",
"botToken": "",
"allowUsers": [],
"allowChannels": []
},
"whatsapp": {
"enabled": false,
"dbPath": "",
"allowFrom": []
}
},
"providers": {
"openai": {
"apiKey": "sk-or-v1-REPLACE_ME",
"apiBase": "https://openrouter.ai/api/v1"
}
}
}
```
---
## agents.defaults
Agent behavior settings.
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `workspace` | string | `~/.picobot/workspace` | Path to the agent's workspace directory. Contains bootstrap files, memory, and skills. |
| `model` | string | `stub-model` | Default LLM model to use. Set to a real model like `google/gemini-2.5-flash`. Can be overridden with the `-M` flag. |
| `maxTokens` | int | `8192` | Maximum tokens for LLM responses. |
| `temperature` | float | `0.7` | LLM temperature (0.0 = deterministic, 1.0 = creative). |
| `maxToolIterations` | int | `100` | Maximum number of tool-calling iterations per request. Prevents infinite loops. |
| `heartbeatIntervalS` | int | `60` | How often (in seconds) the heartbeat checks `HEARTBEAT.md` for periodic tasks. Only used in gateway mode. |
| `requestTimeoutS` | int | `60` | HTTP timeout in seconds for each LLM API request. Increase for slow models or poor network conditions. |
| `enableToolActivityIndicator` | bool | `true` | When `true`, sends interim `🤖 Running` / `📢 done` messages to the chat channel as tools are called. Set to `false` for IoT or headless deployments where only the final response should be delivered. |
### Model Priority
The model is resolved in this order:
1. **CLI flag** (`-M` / `--model`)
2. **Config** (`agents.defaults.model`)
3. **Provider default** (fallback)
### Example
```json
{
"agents": {
"defaults": {
"workspace": "/home/user/.picobot/workspace",
"model": "google/gemini-2.5-flash",
"maxTokens": 16384,
"temperature": 0.5,
"maxToolIterations": 200,
"heartbeatIntervalS": 120,
"requestTimeoutS": 120,
"enableToolActivityIndicator": false
}
}
}
```
---
## providers
LLM provider configuration. Picobot uses an OpenAI-compatible API provider.
### providers.openai
Connect to any OpenAI-compatible API service (OpenAI, OpenRouter, Ollama, etc.).
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `apiKey` | string | *(required)* | Your API key. Get OpenRouter keys at https://openrouter.ai/keys |
| `apiBase` | string | `https://openrouter.ai/api/v1` | API base URL. Use `https://api.openai.com/v1` for OpenAI, `http://localhost:11434/v1` for local Ollama, or any compatible endpoint. |
```json
{
"providers": {
"openai": {
"apiKey": "sk-or-v1-your-key-here",
"apiBase": "https://openrouter.ai/api/v1"
}
}
}
```
**Examples:**
```json
// OpenAI
{
"providers": {
"openai": {
"apiKey": "sk-proj-...",
"apiBase": "https://api.openai.com/v1"
}
}
}
// Local Ollama (no API key needed)
{
"providers": {
"openai": {
"apiKey": "not-needed",
"apiBase": "http://localhost:11434/v1"
}
}
}
```
### Provider Fallback
If no valid provider is configured, Picobot uses a **Stub** provider (echoes back your message, for testing).
---
## mcpServers
Connect external [MCP (Model Context Protocol)](https://modelcontextprotocol.io) servers to give the agent additional tools. Each entry is a named server that exposes one or more tools, which are registered automatically at startup under the name `mcp_{server}_{tool}`.
Two transports are supported:
| Transport | When to use | Required fields |
|-----------|-------------|------------------|
| **Stdio** | Local process (npx, uvx, binary, docker) | `command` + `args` |
| **HTTP** | Remote or hosted MCP server | `url` (+ optional `headers`) |
### Stdio transport (command + args)
Picobot spawns the process and communicates over stdin/stdout. This works with any MCP server that supports the stdio transport.
```json
{
"mcpServers": {
"via-npx": {
"command": "npx",
"args": ["-y", "@some/mcp-server"]
}
}
}
```
**Common patterns:**
```json
{
"mcpServers": {
"via-npx": {
"command": "npx",
"args": ["-y", "@some/mcp-server"]
},
"via-uvx": {
"command": "uvx",
"args": ["some-mcp-server"]
},
"via-binary": {
"command": "/usr/local/bin/my-mcp-server",
"args": ["--some-flag"]
},
"via-docker": {
"command": "docker",
"args": ["run", "--rm", "-i", "mcp/some-image"]
}
}
}
```
> **Docker note:** Always include `-i` (interactive) in the `args`. Without it, Docker closes stdin immediately and the MCP handshake fails.
### HTTP transport (url + headers)
For MCP servers accessible over HTTP (Streamable HTTP or SSE). Supports bearer tokens and custom headers.
```json
{
"mcpServers": {
"via-remote": {
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}
```
### MCPServerConfig fields
| Field | Type | Description |
|-------|------|-------------|
| `command` | string | Executable to spawn (for stdio transport). Can be a name on `$PATH` or an absolute path. |
| `args` | string[] | Arguments passed to the command. |
| `url` | string | HTTP endpoint for the MCP server (for HTTP transport). |
| `headers` | object | HTTP headers to attach to every request (e.g. `Authorization`). |
Only one transport is used per server: if both `command` and `url` are set, `command` takes precedence.
### Tool naming
Each MCP tool is registered in the agent's tool registry as `mcp_{server}_{tool}`. For example, a server named `via-npx` exposing a tool `some-action` becomes `mcp_via-npx_some-action`. The agent sees and calls it like any built-in tool.
### Startup behaviour
- Servers are connected when the agent starts (`gateway` or `agent` command).
- If a server fails to connect (process not found, network error, handshake failure), picobot **logs the error and continues** — other servers and built-in tools are unaffected.
- All MCP connections are cleanly shut down when the gateway exits.
---
## channels
Chat channel integrations. Supports Telegram, Discord, Slack, and WhatsApp.
### channels.telegram
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `enabled` | bool | `false` | Set to `true` to start the Telegram bot. |
| `token` | string | `""` | Your Telegram Bot token from [@BotFather](https://t.me/BotFather). |
| `allowFrom` | string[] | `[]` | List of allowed Telegram user IDs. Empty = allow all. |
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
"allowFrom": ["8881234567"]
}
}
}
```
### channels.discord
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `enabled` | bool | `false` | Set to `true` to start the Discord bot. |
| `token` | string | `""` | Your Discord Bot token from the [Developer Portal](https://discord.com/developers/applications). |
| `allowFrom` | string[] | `[]` | List of allowed Discord user IDs. Empty = allow all. |
```json
{
"channels": {
"discord": {
"enabled": true,
"token": "MTIzNDU2Nzg5MDEyMzQ1Njc4OQ.XXXXXX.XXXXXXXXXXXXXXXXXXXXXXXX",
"allowFrom": ["123456789012345678"]
}
}
}
```
The Discord bot uses the Gateway WebSocket API for receiving messages and the REST API for sending. In servers, the bot responds when **mentioned** (`@botname`) or when a message is a **reply** to the bot. In DMs, the bot responds to all messages.
**Required Bot Permissions:**
- Send Messages
- Read Message History
**Required Privileged Intents (enable in Developer Portal → Bot):**
- Message Content Intent
### channels.slack
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `enabled` | bool | `false` | Set to `true` to start the Slack bot. |
| `appToken` | string | `""` | Slack App-Level Token (Socket Mode), starts with `xapp-`. |
| `botToken` | string | `""` | Slack Bot Token, starts with `xoxb-`. |
| `allowUsers` | string[] | `[]` | List of allowed Slack user IDs. Empty = allow all. |
| `allowChannels` | string[] | `[]` | List of allowed Slack channel IDs (C..., G..., D...). Empty = allow all. DMs ignore this list. |
```json
{
"channels": {
"slack": {
"enabled": true,
"appToken": "xapp-1-AAAAAAAAAAAAAAAAAAAA",
"botToken": "xoxb-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAAAAAAAAAAAAAA",
"allowUsers": ["U0123456789"],
"allowChannels": ["C0123456789"]
}
}
}
```
The Slack bot uses Socket Mode. In channels, the bot responds only when mentioned. In DMs, the bot responds to all messages from allowed users and ignores `allowChannels`. Thread replies are preserved when the inbound message is in a thread.
### channels.whatsapp
Uses a personal WhatsApp account (via [whatsmeow](https://go.mau.fi/whatsmeow)) rather than a dedicated bot account. Only direct messages are handled — group messages are ignored.
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `enabled` | bool | `false` | Set to `true` to start the WhatsApp channel. |
| `dbPath` | string | `~/.picobot/whatsapp.db` | Path to the SQLite session database. Created automatically by `picobot channels login`. |
| `allowFrom` | string[] | `[]` | List of **LID numbers** allowed to send messages. Empty `[]` = allow everyone. See below. |
```json
{
"channels": {
"whatsapp": {
"enabled": true,
"dbPath": "~/.picobot/whatsapp.db",
"allowFrom": ["12345678901234"]
}
}
}
```
**One-time setup:** Link your phone by running:
```
picobot channels login
```
Select **3) WhatsApp**. This shows a QR code. In WhatsApp on your phone: **Settings → Linked Devices → Link a Device**. The session is saved to `dbPath` — no QR code is needed on subsequent starts. The config is updated automatically.
#### Finding your LID for allowFrom
Modern WhatsApp accounts use an internal **LID** (Linked ID) — a numeric identifier that is different from the phone number. Picobot routes messages using LIDs, so `allowFrom` must contain LID numbers, not phone numbers.
**How to find your LID:**
Start the gateway after pairing and check the startup log:
```
whatsapp: connected as 85298765432 (LID: 12345678901234)
```
The number after `LID:` is this device's own LID. To find the LID of another person you want to allow, ask them to send you a message, then check the picobot log:
```
whatsapp: dropped message from unauthorized sender 99999999999@lid (add '99999999999' to allowFrom to permit)
```
The number in the log is the sender's LID. Add that number to `allowFrom`.
**Examples:**
| Scenario | `allowFrom` value |
|----------|-------------------|
| Allow only yourself (Notes to Self) | `[]` *(self-chat is always allowed regardless)* |
| Allow one other person | `["12345678901234"]` |
| Allow multiple people | `["12345678901234", "99999999999"]` |
| Allow everyone | `[]` |
> **Why not phone numbers?** Newer WhatsApp accounts use LID-based addressing internally. If you put a phone number in `allowFrom`, messages from that person will be silently dropped because WhatsApp delivers them with a LID, not the phone number.
> **Self-chat (Notes to Self):** Your own messages to yourself always bypass the `allowFrom` list — no entry needed.
> **Note:** Unlike Telegram/Discord bots, WhatsApp uses a personal phone number. Messages are sent and received from that number.
---
## Docker Environment Variables
When running with Docker, you can override config values using environment variables. The `entrypoint.sh` script applies these overrides at container startup.
| Environment Variable | Config Path | Description |
|---------------------|-------------|-------------|
| `OPENAI_API_KEY` | `providers.openai.apiKey` | OpenAI-compatible API key |
| `OPENAI_API_BASE` | `providers.openai.apiBase` | API base URL |
| `PICOBOT_MODEL` | `agents.defaults.model` | LLM model to use |
| `PICOBOT_MAX_TOKENS` | `agents.defaults.maxTokens` | Maximum tokens for LLM responses |
| `PICOBOT_MAX_TOOL_ITERATIONS` | `agents.defaults.maxToolIterations` | Maximum tool iterations per request |
| `TELEGRAM_BOT_TOKEN` | `channels.telegram.token` | Telegram bot token (also enables the channel) |
| `TELEGRAM_ALLOW_FROM` | `channels.telegram.allowFrom` | Comma-separated allowed Telegram user IDs |
| `DISCORD_BOT_TOKEN` | `channels.discord.token` | Discord bot token (also enables the channel) |
| `DISCORD_ALLOW_FROM` | `channels.discord.allowFrom` | Comma-separated allowed Discord user IDs |
| `SLACK_APP_TOKEN` | `channels.slack.appToken` | Slack App-Level Token (also enables the channel) |
| `SLACK_BOT_TOKEN` | `channels.slack.botToken` | Slack Bot Token (also enables the channel) |
| `SLACK_ALLOW_USERS` | `channels.slack.allowUsers` | Comma-separated allowed Slack user IDs |
| `SLACK_ALLOW_CHANNELS` | `channels.slack.allowChannels` | Comma-separated allowed Slack channel IDs |
---
## Workspace Files
The workspace directory (default `~/.picobot/workspace`) contains files that shape agent behavior:
| File | Purpose | Who edits |
|------|---------|-----------|
| `SOUL.md` | Agent personality, values, communication style | You (once) |
| `AGENTS.md` | Agent instructions, rules, guidelines | You (once) |
| `USER.md` | Your profile — name, timezone, preferences | You (once) |
| `TOOLS.md` | Tool reference documentation | You (once) |
| `HEARTBEAT.md` | Periodic tasks checked every `heartbeatIntervalS` seconds | You / Agent |
| `memory/MEMORY.md` | Long-term memory | Agent (via write_memory tool) |
| `memory/YYYY-MM-DD.md` | Daily notes | Agent (via write_memory tool) |
| `skills/` | Skill packages | Agent (via skill tools) or you manually |
---
## Example: Minimal Production Config
```json
{
"agents": {
"defaults": {
"workspace": "/home/user/.picobot/workspace",
"model": "openrouter/free",
"maxTokens": 8192,
"temperature": 0.7,
"maxToolIterations": 200,
"heartbeatIntervalS": 60
}
},
"mcpServers": {
"via-npx": {
"command": "npx",
"args": ["-y", "@some/mcp-server"]
}
},
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_TELEGRAM_BOT_TOKEN",
"allowFrom": ["YOUR_TELEGRAM_USER_ID"]
},
"discord": {
"enabled": true,
"token": "YOUR_DISCORD_BOT_TOKEN",
"allowFrom": ["YOUR_DISCORD_USER_ID"]
}
},
"providers": {
"openai": {
"apiKey": "sk-or-v1-YOUR_KEY",
"apiBase": "https://openrouter.ai/api/v1"
}
}
}
```