Skip to content
API Blog

lobu.toml Reference

lobu.toml is the project configuration file created by lobu init. It defines agents, providers, connections, skills, network access, worker settings, and optional file-first Owletto memory configuration.

[agents.my-agent]
name = "my-agent"
dir = "./agents/my-agent"
[[agents.my-agent.providers]]
id = "openrouter"
key = "$OPENROUTER_API_KEY"
[agents.my-agent.network]
allowed = ["github.com"]
[memory.owletto]
enabled = true
org = "my-agent"
name = "My Agent"
models = "./models"
data = "./data"
[agents.support]
name = "support"
description = "Customer support agent"
dir = "./agents/support"
# Providers (order = priority, first available is used)
[[agents.support.providers]]
id = "openrouter"
model = "anthropic/claude-sonnet-4"
key = "$OPENROUTER_API_KEY"
[[agents.support.providers]]
id = "gemini"
key = "$GEMINI_API_KEY"
# Platform connections
[[agents.support.connections]]
type = "telegram"
[agents.support.connections.config]
botToken = "$TELEGRAM_BOT_TOKEN"
[[agents.support.connections]]
type = "slack"
[agents.support.connections.config]
botToken = "$SLACK_BOT_TOKEN"
signingSecret = "$SLACK_SIGNING_SECRET"
# Local skills live in skills/<name>/SKILL.md or agents/<id>/skills/<name>/SKILL.md
# MCP servers can still be configured inline here.
[agents.support.skills.mcp.custom-tools]
url = "https://my-mcp.example.com"
headers = { Authorization = "Bearer $MCP_TOKEN" }
[agents.support.skills.mcp.custom-tools.oauth]
auth_url = "https://auth.example.com/authorize"
token_url = "https://auth.example.com/token"
client_id = "$OAUTH_CLIENT_ID"
client_secret = "$OAUTH_CLIENT_SECRET"
scopes = ["read", "write"]
# Network access policy
[agents.support.network]
allowed = ["github.com", "api.linear.app"]
denied = []
# Tool policy (worker-side visibility + MCP approval override)
[agents.support.tools]
# Bypass the in-thread approval card for these destructive MCP tools.
pre_approved = [
"/mcp/gmail/tools/list_messages",
"/mcp/linear/tools/*",
]
# Worker-side tool visibility (optional).
allowed = ["Read", "Grep", "mcp__gmail__*"]
denied = ["Bash(rm:*)"]
strict = false
# Worker customization
[agents.support.worker]
nix_packages = ["imagemagick", "ffmpeg"]
# File-first Owletto memory
[memory.owletto]
enabled = true
org = "support"
name = "Support"
description = "Customer support agent"
models = "./models"
data = "./data"

Optional project-level Owletto memory configuration for file-first projects.

Typical companion layout:

project/
├── lobu.toml
├── models/
└── data/
FieldTypeRequiredDescription
enabledbooleannoEnables file-first Owletto memory resolution for the project
orgstringyes (when enabled)Owletto organization slug — scopes the MCP endpoint
namestringyes (when enabled)Human-readable project name
descriptionstringnoShort project description
visibilitystringnopublic or private; defaults to Lobu’s account setting
modelsstringnoPath to Owletto model files, usually ./models
datastringnoPath to Owletto seed data, usually ./data

When [memory.owletto] is enabled, Lobu reads org directly from lobu.toml and derives the effective Owletto MCP endpoint. MEMORY_URL remains available as an optional base-endpoint override for local or custom Owletto deployments.

Top-level table keyed by agent ID. IDs must match ^[a-z0-9][a-z0-9-]*$ (lowercase alphanumeric with hyphens).

FieldTypeRequiredDescription
namestringyesDisplay name for the agent
descriptionstringnoShort description shown in admin UI
dirstringyesPath to agent content directory containing IDENTITY.md, SOUL.md, USER.md, and optional skills/
providersarraynoLLM provider list (order = priority)
connectionsarraynoPlatform connections
skillstablenoSkills and MCP servers
networktablenoNetwork access policy
toolstablenoTool policy: pre-approval bypass + worker-side visibility
workertablenoWorker customization

Each entry configures an LLM provider. The first available provider is used at runtime.

FieldTypeRequiredDescription
idstringyesProvider identifier (e.g. openrouter, anthropic, gemini, openai)
modelstringnoModel override (e.g. anthropic/claude-sonnet-4)
keystringnoAPI key — literal value or $ENV_VAR reference
secret_refstringnoDurable secret reference (for example secret://...)

Provider credentials are optional. A provider entry may omit both key and secret_ref, or set exactly one of them. Setting both is invalid.

Each entry connects the agent to a messaging platform.

FieldTypeRequiredDescription
typestringyesPlatform type: telegram, slack, discord, whatsapp, teams, gchat
configtableyesPlatform-specific configuration (see below)

Telegram

[agents.x.connections.config]
botToken = "$TELEGRAM_BOT_TOKEN"

Slack

[agents.x.connections.config]
botToken = "$SLACK_BOT_TOKEN"
signingSecret = "$SLACK_SIGNING_SECRET"

Discord

[agents.x.connections.config]
botToken = "$DISCORD_BOT_TOKEN"
applicationId = "$DISCORD_APPLICATION_ID"
publicKey = "$DISCORD_PUBLIC_KEY"

WhatsApp (Cloud API)

[agents.x.connections.config]
accessToken = "$WHATSAPP_ACCESS_TOKEN"
phoneNumberId = "$WHATSAPP_PHONE_NUMBER_ID"
verifyToken = "$WHATSAPP_WEBHOOK_VERIFY_TOKEN"
appSecret = "$WHATSAPP_APP_SECRET"

Teams

[agents.x.connections.config]
appId = "$TEAMS_APP_ID"
appPassword = "$TEAMS_APP_PASSWORD"
appTenantId = "$TEAMS_APP_TENANT_ID"
appType = "MultiTenant"

Google Chat

[agents.x.connections.config]
credentials = "$GOOGLE_CHAT_CREDENTIALS"
FieldTypeRequiredDescription
mcptablenoCustom MCP server definitions

Each entry defines a custom MCP server.

FieldTypeRequiredDescription
urlstringnoSSE/Streamable HTTP endpoint URL
commandstringnoStdio transport — command to run
argsarray of stringsnoStdio transport — command arguments
envtablenoEnvironment variables passed to the MCP process
headerstablenoHTTP headers sent with requests
oauthtablenoOAuth configuration (see below)

Specify either url (SSE/HTTP transport) or command (stdio transport), not both.

OAuth configuration for MCP servers that require authenticated access.

FieldTypeRequiredDescription
auth_urlstringyesAuthorization endpoint
token_urlstringyesToken endpoint
client_idstringnoOAuth client ID (literal or $ENV_VAR)
client_secretstringnoOAuth client secret (literal or $ENV_VAR)
scopesarray of stringsnoRequested scopes
token_endpoint_auth_methodstringnoAuth method: none, client_secret_post, client_secret_basic

Controls which domains the worker can reach through the gateway proxy.

FieldTypeRequiredDescription
allowedarray of stringsnoDomains to allow. Empty = no access. Use ["*"] for unrestricted (not recommended)
deniedarray of stringsnoDomains to block (only meaningful when allowed = ["*"])

Domain format: exact match (api.example.com) or wildcard (.example.com matches all subdomains).

Operator-level tool policy. Two independent concerns:

See Tool Policy for behavior and examples; this section is the exact schema reference.

FieldTypeRequiredDescription
pre_approvedarray of stringsnoMCP tool grant patterns that bypass the in-thread approval card. Each entry must match /mcp/<mcp-id>/tools/<tool-name> or /mcp/<mcp-id>/tools/* — malformed entries fail schema validation. Synced to the grant store at deployment time.
allowedarray of stringsnoTools the worker can call. Patterns follow Claude Code’s permission format: Read, Bash(git:*), mcp__github__*, *.
deniedarray of stringsnoTools to always block. Takes precedence over allowed.
strictbooleannoIf true, ONLY allowed tools are permitted (defaults are ignored). Default false.

pre_approved is an operator-only escape hatch. Destructive MCP tools normally require user approval in-thread (per MCP destructiveHint annotations). Skills cannot set this field — bypassing approval is strictly the operator’s call, visible in the lobu.toml diff.

FieldTypeRequiredDescription
nix_packagesarray of stringsnoNix packages to install in the worker environment

Any string value can reference an environment variable with $ENV_VAR syntax. The CLI resolves these from .env at runtime.

key = "$OPENROUTER_API_KEY" # resolved from .env
key = "sk-literal-value" # used as-is
Terminal window
npx @lobu/cli@latest validate

Checks TOML syntax, schema conformance, skill IDs, and provider configuration. Returns exit code 1 on failure.