Docs / Reference
Edit on GitHub

Configuration Schema

This document defines the configuration file formats used by OpenViber. Configuration lives under ~/.openviber/ (lightweight, portable). Working data lives in ~/openviber_spaces/ or any directory you point tasks at.

1. Directory Layout

~/.openviber/                        # Config-only (small, portable)
├── config.yaml                      # Viber-level daemon configuration
├── user.md                          # Shared user context (who you are)
├── skills/                          # Shared skill bundles
│   └── my-skill/
│       └── SKILL.md
├── mcp/                             # MCP server configs (optional)
└── vibers/
    ├── default.yaml                 # Default task config
    ├── default/
    │   ├── soul.md                  # Persona for this task
    │   ├── memory.md                # Long-term memory
    │   ├── memory/                  # Daily memory logs
    │   └── sessions/                # Conversation logs (*.jsonl)
    ├── dev.yaml                     # Named task config
    └── dev/
        ├── soul.md
        ├── memory.md
        ├── memory/
        └── sessions/

~/openviber_spaces/                  # Working data (large, git-managed)
├── my-webapp/                       # Cloned repo
├── data-pipeline/                   # Another repo
└── market-research/                 # Non-code workspace

2. Global Configuration (config.yaml)

# ~/.openviber/config.yaml

# Daemon settings
daemon:
  host: "127.0.0.1"              # Listen address
  port: 3000                     # Listen port
  log_level: "info"              # debug | info | warn | error

# Default model settings (can be overridden per task)
defaults:
  model: "anthropic/claude-sonnet-4-20250514"
  temperature: 0.7
  max_tokens: 4096

# Provider credentials
providers:
  anthropic:
    api_key: "${ANTHROPIC_API_KEY}"  # Environment variable reference
  openai:
    api_key: "${OPENAI_API_KEY}"
    organization: "${OPENAI_ORG_ID}"  # Optional
  ollama:
    base_url: "http://localhost:11434"

# Budget limits (global)
budget:
  enabled: true
  mode: "soft"                   # soft | hard
  daily_limit_usd: 50.00
  monthly_limit_usd: 500.00
  warning_threshold: 0.8         # Warn at 80%

# Channel integrations
channels:
  dingtalk:
    enabled: false
    app_key: "${DINGTALK_APP_KEY}"
    app_secret: "${DINGTALK_APP_SECRET}"
  wecom:
    enabled: false
    corp_id: "${WECOM_CORP_ID}"
    agent_id: "${WECOM_AGENT_ID}"
    secret: "${WECOM_SECRET}"
  wechat:
    enabled: false
    apiKey: "${WECHAT_API_KEY}"
    proxyUrl: "${WECHAT_PROXY_URL}"
    accountId: "${WECHAT_ACCOUNT_ID}"

# Channels gateway settings (webhook server for DingTalk, WeCom, etc.; started with `viber channels`)
gateway:
  host: "0.0.0.0"
  port: 6009
  basePath: ""                 # Optional base path for webhook routes

# Security settings
security:
  require_auth: true             # Require authentication for connections
  auto_approve_localhost: true   # Skip auth for 127.0.0.1
  challenge_ttl_seconds: 300     # Nonce validity period
  session_ttl_seconds: 86400     # 24 hours

# MCP servers
mcp_servers: []                  # See MCP section below

Environment Variable Expansion

Values starting with ${ and ending with } are expanded from environment variables:

api_key: "${ANTHROPIC_API_KEY}"  # Reads $ANTHROPIC_API_KEY

3. Task Configuration (vibers/{id}.yaml)

# ~/.openviber/vibers/default.yaml

# Required fields
name: "Developer"                    # Display name
model: "anthropic/claude-sonnet-4-20250514"    # Provider/model identifier

# Optional fields
description: "Full-stack development task"

# Model parameters
temperature: 0.7
max_tokens: 4096
top_p: 1.0

# Tools available to this task
tools:
  - file                         # read_file, write_file, list_files
  - terminal                     # shell_command
  - browser                      # web_search, web_scrape, browser_action
  - desktop                      # screenshot, click, type

# Tools requiring human approval
require_approval:
  - write_file
  - shell_command
  - browser_action

# Skills to load (from ~/.openviber/skills/)
skills:
  - antigravity
  - cursor-agent
  - codex-cli

# Per-task budget override
budget:
  limit_usd: 10.00
  mode: "hard"

# Working mode default
mode: "viber_decides"            # always_ask | viber_decides | always_execute

# Spaces this task works on
spaces:
  - ~/openviber_spaces/my-webapp
  - ~/code/legacy-api            # Can point anywhere

# Retry configuration
retry:
  max_attempts: 3
  base_delay_ms: 1000
  backoff: "exponential"

# Fallback model (used when primary fails)
fallback_model: "openai/gpt-4o-mini"

# Context management
context:
  max_history_messages: 50       # Truncate older messages
  max_tool_result_length: 10000  # Truncate long tool outputs
  include_system_info: true      # Add OS/env info to context

Model Identifier Format

provider/model-name

Examples:
- anthropic/claude-sonnet-4-20250514
- anthropic/claude-3-haiku-20240307
- openai/gpt-4o
- openai/gpt-4o-mini
- ollama/llama2
- ollama/codellama

Tool Reference

Tool IDFunctions Provided
fileread_file, write_file, list_files, delete_file
terminalshell_command
browserweb_search, web_scrape, browser_action
desktopscreenshot, mouse_click, keyboard_type
searchsemantic_search (workspace search)

4. Channel Configuration

DingTalk

# In config.yaml under channels:
dingtalk:
  enabled: true
  app_key: "${DINGTALK_APP_KEY}"
  app_secret: "${DINGTALK_APP_SECRET}"
  
  # Message formatting
  max_message_length: 2000       # Characters per message
  chunk_on_newline: true         # Prefer splitting on newlines
  
  # Rate limiting
  rate_limit:
    messages_per_minute: 20
    messages_per_hour: 200
  
  # Webhook for outgoing messages (optional)
  webhook_url: "${DINGTALK_WEBHOOK_URL}"

WeCom (企业微信)

wecom:
  enabled: true
  corp_id: "${WECOM_CORP_ID}"
  agent_id: "${WECOM_AGENT_ID}"
  secret: "${WECOM_SECRET}"
  
  # Token for callback verification
  callback_token: "${WECOM_CALLBACK_TOKEN}"
  callback_aes_key: "${WECOM_AES_KEY}"
  
  # Message formatting
  max_message_length: 2048
  
  # Rate limiting
  rate_limit:
    messages_per_second: 5

WeChat (微信)

wechat:
  enabled: true
  apiKey: "${WECHAT_API_KEY}"
  proxyUrl: "${WECHAT_PROXY_URL}"
  accountId: "default"               # Optional account ID header for proxy

  # Inbound webhook (provided by OpenViber channel gateway)
  # POST /webhook/wechat

Discord

discord:
  enabled: true
  botToken: "${DISCORD_BOT_TOKEN}"
  appId: "${DISCORD_APP_ID}"          # Optional
  requireMention: true                # Require @mention in guild channels
  replyMode: "reply"                  # reply | channel
  allowGuildIds: ["123", "456"]       # Optional allowlists
  allowChannelIds: ["123", "456"]
  allowUserIds: ["123", "456"]

Feishu / Lark

feishu:
  enabled: true
  appId: "${FEISHU_APP_ID}"
  appSecret: "${FEISHU_APP_SECRET}"
  domain: "feishu"                    # feishu | lark | custom URL
  connectionMode: "websocket"         # websocket | webhook
  webhookPath: "/webhook/feishu"      # Used in webhook mode
  verificationToken: "${FEISHU_VERIFICATION_TOKEN}"
  encryptKey: "${FEISHU_ENCRYPT_KEY}"
  allowGroupMessages: false
  requireMention: true

Web Channel

web:
  enabled: true
  cors_origins:
    - "http://localhost:3000"
    - "https://board.example.com"
  
  # Streaming settings
  streaming:
    mode: "auto"                 # auto | token | block
    block_min_chars: 100
    block_max_chars: 500

5. Budget Configuration

budget:
  enabled: true
  
  # Enforcement mode
  mode: "soft"                   # soft: warn only | hard: block at limit
  
  # Limits
  per_task_limit_usd: 5.00       # Per-task maximum
  daily_limit_usd: 50.00         # Daily maximum
  monthly_limit_usd: 500.00      # Monthly maximum
  
  # Thresholds
  warning_threshold: 0.8         # Warn at 80% of limit
  
  # Cost tracking
  track_by: "task"               # task | session | agent | global
  
  # Actions when exceeded
  on_exceed:
    soft: "warn"                 # warn | pause | stop
    hard: "pause"                # pause | stop

Cost Estimation

Costs are estimated using provider pricing:

ProviderModelInput (per 1M)Output (per 1M)
Anthropicclaude-sonnet-4-20250514$3.00$15.00
Anthropicclaude-3-haiku$0.25$1.25
OpenAIgpt-4o$5.00$15.00
OpenAIgpt-4o-mini$0.15$0.60

6. Job/Schedule Configuration

Jobs are YAML files stored in ~/.openviber/jobs/:

# ~/.openviber/jobs/morning-standup.yaml

name: "morning-standup"
description: "Daily standup summary"

# Cron schedule (cron syntax)
schedule: "0 9 * * 1-5"          # 9 AM, Monday-Friday

# Task configuration
prompt: |
  Check my GitHub notifications and summarize what needs attention.
  Format as a brief bullet list.

# Override task settings for this job
model: "anthropic/claude-3-haiku-20240307"  # Use cheaper model for routine tasks

# Skills to include
skills:
  - github-notifier

# Approval settings
approval_required: false         # Run unattended

# Notification on completion
notify:
  channel: "dingtalk"
  on: ["completed", "error"]

# Budget for this job
budget:
  limit_usd: 0.50

7. MCP Server Configuration

# In config.yaml under mcp_servers:
mcp_servers:
  - name: "github"
    description: "GitHub API access"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-github"]
    env:
      GITHUB_TOKEN: "${GITHUB_TOKEN}"
    
  - name: "filesystem"
    description: "Extended filesystem operations"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
    
  - name: "postgres"
    description: "Database access"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-postgres"]
    env:
      DATABASE_URL: "${DATABASE_URL}"
    # Require approval for write operations
    require_approval:
      - "query"  # Approve all queries (can be more specific)

8. Skill Configuration

Skills are loaded from src/skills/ or ~/.openviber/skills/:

~/.openviber/skills/
└── my-skill/
    ├── SKILL.md                 # Required: frontmatter + instructions
    └── index.ts                 # Optional: tool definitions

SKILL.md Format

---
name: my-skill
description: A custom skill for specific tasks
version: 1.0.0
author: Your Name
tags:
  - productivity
  - automation
tools:
  - my_custom_tool
---

# My Skill

Instructions for the agent when this skill is loaded...

## When to Use

- Situation A
- Situation B

## Procedures

1. Step one
2. Step two

9. Validation

The daemon validates all configuration at startup. Common errors:

ErrorCauseFix
Invalid model formatModel string doesn’t match provider/modelUse correct format
Unknown tool: xyzTool not registeredCheck available tools
Skill not found: abcSkill directory missingInstall or remove from config
Missing required fieldRequired field not setAdd the field
Invalid cron expressionMalformed scheduleFix cron syntax

Validation Command

openviber config validate

10. Example Complete Setup

# ~/.openviber/config.yaml
daemon:
  port: 3000
  log_level: "info"

defaults:
  model: "anthropic/claude-sonnet-4-20250514"

providers:
  anthropic:
    api_key: "${ANTHROPIC_API_KEY}"
  openai:
    api_key: "${OPENAI_API_KEY}"

budget:
  enabled: true
  mode: "soft"
  daily_limit_usd: 25.00

channels:
  web:
    enabled: true

security:
  require_auth: false
  auto_approve_localhost: true
# ~/.openviber/vibers/default.yaml
name: "Viber"
model: "anthropic/claude-sonnet-4-20250514"

tools:
  - file
  - terminal
  - browser

require_approval:
  - shell_command

skills:
  - cursor-agent
  - codex-cli

mode: "viber_decides"

spaces:
  - ~/openviber_spaces/my-project

Schema Definitions (TypeScript)

For programmatic use, here are the TypeScript types:

interface GlobalConfig {
  daemon?: DaemonConfig;
  defaults?: ModelDefaults;
  providers?: Record<string, ProviderConfig>;
  budget?: BudgetConfig;
  channels?: ChannelConfigs;
  security?: SecurityConfig;
  mcp_servers?: McpServerConfig[];
}

interface TaskConfig {
  name: string;
  model: string;
  description?: string;
  temperature?: number;
  max_tokens?: number;
  top_p?: number;
  tools?: string[];
  require_approval?: string[];
  skills?: string[];
  budget?: TaskBudgetConfig;
  mode?: "always_ask" | "viber_decides" | "always_execute";
  spaces?: string[];
  retry?: RetryConfig;
  fallback_model?: string;
  context?: ContextConfig;
}

interface BudgetConfig {
  enabled: boolean;
  mode: "soft" | "hard";
  per_task_limit_usd?: number;
  daily_limit_usd?: number;
  monthly_limit_usd?: number;
  warning_threshold?: number;
  track_by?: "task" | "session" | "agent" | "global";
  on_exceed?: {
    soft?: "warn" | "pause" | "stop";
    hard?: "pause" | "stop";
  };
}