All configuration lives in ~/.xbot/config.json. Direct editing is
preferred over environment variables.
| What you want to do | Config key |
|---|---|
| Set API key | subscriptions[].api_key |
| Use DeepSeek/Ollama | subscriptions[].base_url |
| Enable Feishu | feishu.enabled: true |
| Enable Web | web.enable: true |
| Docker sandbox | sandbox.mode: "docker" |
| Restrict users | *.allow_from: [...] |
| Max concurrent calls | agent.max_concurrency |
| Context compression | agent.compression_threshold |
- Default:
~/.xbot/config.json - Override with the
XBOT_HOMEenvironment variable (e.g.XBOT_HOME=/opt/xbot) - In Server mode, specify via
xbot-cli serve --config /path/to/config.json
{
"subscriptions": [
{
"name": "default",
"provider": "openai",
"api_key": "sk-xxx",
"model": "gpt-4o"
}
],
"sandbox": {
"mode": "none"
}
}
The admin creates subscriptions via /setup in the TUI, then enables the
Feishu app:
{
"feishu": {
"enabled": true,
"app_id": "cli_xxx",
"app_secret": "xxx"
},
"web": {
"enabled": true
}
}
WarningChannel config keys: Feishu, QQ, and NapCat useenabled. Web usesenable(note: nod). Bothenableandenabledare accepted at runtime for backward compatibility, but match the struct tag for clarity.
xbot manages LLM configuration through a subscription system (not a single
global llm key). You can create multiple subscriptions and switch between
them per session.
{
"subscriptions": [
{
"name": "default",
"provider": "openai",
"api_key": "sk-xxx",
"base_url": "https://api.openai.com/v1",
"model": "gpt-4o",
"max_output_tokens": 0,
"max_context": 0,
"thinking_mode": "",
"active": true,
"per_model_configs": {}
}
]
}
| Field | Type | Default | Description |
|---|---|---|---|
name | string | "default" | Subscription name (shown in switcher) |
provider | string | "openai" | Provider: openai or anthropic |
api_key | string | "" | API key |
base_url | string | "https://api.openai.com/v1" | API base URL (change for compatible services) |
model | string | "gpt-4o" | Default model |
max_output_tokens | int | 0 (= 32768) | Max output tokens |
max_context | int | 0 (= 200000) | Max context tokens (0 = use default) |
thinking_mode | string | "" (= auto) | Thinking mode: auto / enabled / disabled |
active | bool | true | Whether this is the active subscription |
per_model_configs | object | {} | Per-model token overrides (see below) |
per_model_configs overrides max_output_tokens and max_context per
model, taking priority over the subscription-level defaults:
"per_model_configs": {
"gpt-4o": {"max_output_tokens": 16384, "max_context": 128000},
"deepseek-chat": {"max_context": 64000}
}
Switch between them in the TUI via Ctrl+P or /models:
{
"subscriptions": [
{
"name": "GPT-4o",
"provider": "openai",
"api_key": "sk-xxx",
"base_url": "https://api.openai.com/v1",
"model": "gpt-4o",
"active": true
},
{
"name": "Claude",
"provider": "anthropic",
"api_key": "sk-ant-xxx",
"model": "claude-sonnet-4-20250514",
"active": false
}
]
}
{
"subscriptions": [
{
"name": "DeepSeek",
"provider": "openai",
"api_key": "your-key",
"base_url": "https://api.deepseek.com/v1",
"model": "deepseek-chat"
}
]
}
NoteServer mode: theuser_llm_subscriptionstable is the single source of truth. The admin creates subscriptions via TUI/setup, then the whole team shares them. Theuser_settingstable must NOT contain subscription fields (provider, model, api_key, etc.).
Model tiers are user-level settings, stored in user_settings (Server
mode) or the global llm block (CLI mode) — not inside a subscription.
Configure via the /settings panel.
| Field | Description |
|---|---|
vanguard_model | Strongest reasoning (used by SubAgents) |
balance_model | Balanced (used by SubAgents) |
swift_model | Fast/small (used by SubAgents) |
Unconfigured tiers fall back automatically: vanguard → balance → swift.
{
"llm": {
"vanguard_model": "claude-opus-4",
"balance_model": "claude-sonnet-4",
"swift_model": "claude-haiku-4"
}
}
{
"agent": {
"max_iterations": 2000,
"max_concurrency": 100,
"memory_provider": "flat",
"work_dir": ".",
"prompt_file": "prompt.md",
"max_context_tokens": 200000,
"enable_auto_compress": true,
"compression_threshold": 0.9,
"context_mode": "",
"purge_old_messages": false,
"max_sub_agent_depth": 6,
"llm_retry_attempts": 5,
"llm_retry_delay": "1s",
"llm_retry_max_delay": "30s",
"llm_retry_timeout": "120s",
"mcp_inactivity_timeout": "30m",
"mcp_cleanup_interval": "5m",
"session_cache_timeout": "24h"
}
}
| Field | Type | Default | Description |
|---|---|---|---|
max_iterations | int | 2000 | Max tool calls per conversation turn |
max_concurrency | int | 100 | Max concurrent LLM calls |
memory_provider | string | "flat" | Memory system: flat or letta |
work_dir | string | "." | Working directory |
prompt_file | string | "prompt.md" | Custom system prompt file |
max_context_tokens | int | 200000 | Max context window (tokens) |
model_contexts | object | {} | Per-model context overrides (model → tokens) |
enable_auto_compress | bool | true | Auto-compress context when full |
compression_threshold | float | 0.9 | Token ratio that triggers compression |
context_mode | string | "" | Context management mode |
purge_old_messages | bool | false | Purge old messages after compression |
max_sub_agent_depth | int | 6 | Max SubAgent nesting depth |
llm_retry_attempts | int | 5 | LLM call retry count |
llm_retry_delay | duration | "1s" | Initial retry delay |
llm_retry_max_delay | duration | "30s" | Max retry delay |
llm_retry_timeout | duration | "120s" | Per-call LLM timeout |
mcp_inactivity_timeout | duration | "30m" | MCP server inactivity timeout |
mcp_cleanup_interval | duration | "5m" | MCP cleanup interval |
session_cache_timeout | duration | "24h" | Session cache timeout |
NoteDuration values are human-readable strings:"30m","1h30m","5s". For backward compatibility, legacy nanosecond numbers are also accepted.
{
"agent": {
"experimental": {
"auto_worktree": false
}
}
}
| Field | Default | Description |
|---|---|---|
auto_worktree | false | Auto-create git worktrees when multiple agents share a repo |
{
"sandbox": {
"mode": "none",
"docker_image": "ubuntu:22.04",
"host_work_dir": "",
"idle_timeout": "30m",
"ws_port": 8080,
"auth_token": "",
"public_url": ""
}
}
| Field | Type | Default | Description |
|---|---|---|---|
mode | string | "none" | Sandbox mode: none or docker |
remote_mode | string | "" | Remote sandbox mode |
docker_image | string | "ubuntu:22.04" | Docker image |
host_work_dir | string | "" | Host working directory |
idle_timeout | duration | "30m" | Idle timeout (0 = disabled) |
ws_port | int | 8080 | Remote sandbox WebSocket port |
auth_token | string | "" | Runner auth token |
public_url | string | "" | Public URL the runner connects to |
See the Sandbox guide for Docker setup details.
See the per-channel docs:
{
"server": {
"host": "0.0.0.0",
"port": 8082,
"read_timeout": "30s",
"write_timeout": "120s"
}
}
{
"cli": {
"server_url": "ws://127.0.0.1:8082",
"token": "your-admin-token"
}
}
Auto-configured during Server-mode installation; usually no manual editing needed.
| Field | Description |
|---|---|
server_url | WebSocket URL of the remote agent server |
token | Auth token (matches the server’s admin.token) |
{
"admin": {
"token": "random-generated-token",
"chat_id": ""
}
}
| Field | Description |
|---|---|
token | Admin token (auto-generated at install) |
chat_id | Admin chat ID (for startup notifications) |
Required only when using memory_provider: "letta":
{
"embedding": {
"provider": "openai",
"base_url": "https://api.openai.com/v1",
"api_key": "",
"model": "text-embedding-3-small",
"max_tokens": 2048
}
}
{
"plugins": {
"enabled": false,
"dirs": [],
"disabled_plugins": [],
"allow_unverified": false
}
}
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable the plugin system (opt-in) |
dirs | []string | [] | Extra plugin scan directories (default: ~/.xbot/plugins/) |
disabled_plugins | []string | [] | Plugin IDs to skip |
allow_unverified | bool | false | Load plugins without verified manifests |
{
"log": {
"level": "info",
"format": "text"
}
}
- Channels — per-channel configuration
- Sandbox guide — Docker sandboxing
- CLI Reference — keyboard shortcuts and commands