Skip to content

Configuration

OpenPaw Configuration

OpenPaw uses a two-tier configuration system: global configuration (config.yaml) and per-workspace overrides (agent.yaml).

Configuration is managed by Pydantic models in openpaw/core/config/models/ with loading and merging logic in openpaw/core/config/loader.py.

Global Configuration

The global configuration file (config.yaml) defines defaults for all workspaces.

Complete Example

# Path to agent workspaces directory
workspaces_path: agent_workspaces

# Logging configuration
logging:
  level: INFO              # DEBUG, INFO, WARNING, ERROR, CRITICAL
  directory: logs          # Directory for log files
  max_size_mb: 10          # Maximum log file size before rotation
  backup_count: 5          # Number of backup files to keep
  per_workspace: true      # Create separate log files per workspace

# Queue settings (OpenClaw-inspired)
queue:
  mode: collect          # collect, steer, followup, interrupt
  debounce_ms: 1000      # Wait before processing collected messages
  cap: 20                # Max queued messages per session
  drop_policy: summarize # old, new, summarize

# Lane concurrency limits
lanes:
  main_concurrency: 4      # Interactive message processing
  subagent_concurrency: 8  # Delegated subagent tasks
  cron_concurrency: 2      # Scheduled jobs

# Channel configurations
channels:
  telegram:
    token: ${TELEGRAM_BOT_TOKEN}
    allowed_users: []
    allowed_groups: []

# Agent defaults
agent:
  # Model format: provider:model_id
  model: anthropic:claude-sonnet-4-20250514
  max_turns: 50
  temperature: 0.7

# Builtin capabilities
builtins:
  allow: []
  deny: []

  brave_search:
    enabled: true
    config:
      count: 5

  whisper:
    enabled: true
    config:
      model: whisper-1

  elevenlabs:
    enabled: true
    config:
      voice_id: 21m00Tcm4TlvDq8ikWAM
      model_id: eleven_turbo_v2_5

  browser:
    enabled: true
    config:
      headless: true
      allowed_domains: []
      blocked_domains: []
      timeout_seconds: 30
      persist_cookies: false

  file_persistence:
    enabled: true
    config:
      max_file_size: 52428800  # 50 MB
      clear_data_after_save: false

  # email:
  #   enabled: true
  #   config:
  #     provider: gmail
  #     service_account_file: config/service-account.json
  #     delegated_user: agent@yourdomain.com
  #     allowed_recipients:
  #       - "*@yourdomain.com"
  #     max_recipients: 10

Configuration Sections

Workspaces Path

workspaces_path: agent_workspaces

Directory containing agent workspace folders. Can be absolute or relative to config file location.


Logging

logging:
  level: INFO              # Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL
  directory: logs          # Directory for log files
  max_size_mb: 10          # Max log file size before rotation
  backup_count: 5          # Number of backup files to keep
  per_workspace: true      # Separate log file per workspace

level — Logging verbosity. Use DEBUG for troubleshooting, INFO for normal operation.

directory — Where log files are written. Created if it doesn't exist.

max_size_mb — When a log file exceeds this size, it's rotated.

backup_count — Number of rotated log files to keep (e.g., openpaw.log.1, openpaw.log.2).

per_workspace — If true, each workspace gets its own log file (e.g., gilfoyle.log, assistant.log).


Queue Settings

queue:
  mode: collect          # Queue mode
  debounce_ms: 1000      # Debounce delay in milliseconds
  cap: 20                # Max messages per session
  drop_policy: summarize # Policy when cap is reached

mode — How messages are queued and processed: - collect — Gather messages briefly before processing (default) - steer — Process immediately, redirect agent if new message arrives during run - followup — Process sequentially, no redirection - interrupt — Cancel current processing on new message

debounce_ms — Wait time before processing collected messages (only for collect mode). This batches rapid-fire messages into a single agent invocation.

cap — Maximum queued messages per session. When exceeded, drop_policy applies.

drop_policy — Action when queue cap is reached: - old — Drop oldest messages - new — Drop newest messages - summarize — Compress old messages into a summary

See queue-system.md for detailed behavior and middleware interactions.


Lane Concurrency

lanes:
  main_concurrency: 4      # User messages
  subagent_concurrency: 8  # Delegated tasks
  cron_concurrency: 2      # Scheduled jobs

Controls how many concurrent tasks can run per lane. Higher values allow more parallelism but consume more resources.

main_concurrency — Interactive user messages processing

subagent_concurrency — Background sub-agent tasks spawned via spawn_agent

cron_concurrency — Scheduled tasks (static cron YAML + dynamic agent-scheduled jobs)


Channel Configuration

Channel configuration is typically done per-workspace in agent.yaml rather than globally. See Channels for full setup guides for each platform.

# Global defaults (config.yaml) — optional
channels:
  telegram:
    token: ${TELEGRAM_BOT_TOKEN}
    allowed_users: []
    allowed_groups: []

Agent Defaults

agent:
  model: anthropic:claude-sonnet-4-20250514
  max_turns: 50
  temperature: 0.7

model — Default model for all workspaces. Format: provider:model_id.

max_turns — Maximum conversation turns before agent stops (prevents infinite loops).

temperature — Model temperature (0.0-1.0). Lower = more focused, higher = more creative.


Builtins Configuration

builtins:
  allow: []  # Empty = allow all available
  deny:
    - group:voice  # Deny entire groups

  brave_search:
    enabled: true
    config:
      count: 5  # Number of search results

See builtins.md for detailed builtin configuration.


Workspace Configuration

Per-workspace configuration (agent.yaml) overrides global defaults for a specific agent.

Location

agent_workspaces/<workspace-name>/config/agent.yaml

Complete Example

name: Gilfoyle
description: Sarcastic systems architect
timezone: America/Denver  # IANA timezone identifier (default: UTC)

model:
  provider: anthropic
  model: claude-sonnet-4-20250514
  api_key: ${ANTHROPIC_API_KEY}
  temperature: 0.5
  max_turns: 50

channel:
  type: telegram
  token: ${TELEGRAM_BOT_TOKEN}
  allowed_users: [123456789]  # Only this user
  allowed_groups: []

queue:
  mode: steer          # Override global queue mode
  debounce_ms: 500     # Faster response

builtins:
  deny:
    - elevenlabs       # Disable TTS for this workspace

  browser:
    enabled: true
    config:
      allowed_domains:
        - "calendly.com"
        - "*.google.com"
      blocked_domains: []
      persist_cookies: true

heartbeat:
  enabled: true
  interval_minutes: 30
  active_hours: "09:00-17:00"
  suppress_ok: true
  delivery: channel
  target_channel: telegram
  target_id: 123456789

approval_gates:
  enabled: true
  timeout_seconds: 120
  default_action: deny
  tools:
    overwrite_file:
      require_approval: true
      show_args: true

status_reminder:
  enabled: true
  threshold: 5
  max_reminders: 3
  cooldown_turns: 1

Workspace-Specific Fields

Basic Identity

name: Gilfoyle
description: Sarcastic systems architect
timezone: America/Denver  # IANA timezone identifier

name — Display name for the agent (optional)

description — Brief description (optional)

timezone — IANA timezone identifier for scheduling, display, and file partitioning. Defaults to UTC if not specified. Examples: America/Denver, Europe/London, Asia/Tokyo.

Timezone Validation: Workspace config validates timezone at load time using Pydantic. Invalid IANA identifiers are rejected with a clear error message.

What uses workspace timezone: - Heartbeat active hours window (active_hours: "09:00-17:00") - Cron schedule expressions (APScheduler CronTrigger) - Agent-created scheduled tasks (schedule_at timestamp parsing) - File upload date partitions (data/uploads/{YYYY-MM-DD}/) - /status "tokens today" day boundary - Display timestamps in conversation archives, task notes, and filesystem listings

What remains UTC (internal storage): - JSONL logs (token_usage.jsonl, heartbeat_log.jsonl) - Session state (sessions.json) - Task internal timestamps (created_at, started_at, completed_at in TASKS.yaml) - Conversation archive JSON sidecar files - LangGraph checkpoint data


Model Configuration

model:
  provider: anthropic
  model: claude-sonnet-4-20250514
  api_key: ${ANTHROPIC_API_KEY}
  temperature: 0.5
  max_turns: 50

provider — Model provider: anthropic, openai, xai, fireworks, bedrock_converse, or any OpenAI-compatible API via openai with base_url.

model — Model identifier (provider-specific).

api_key — API key for the model provider. Use ${VAR} syntax for environment variables.

temperature — Model temperature (0.0-1.0).

max_turns — Maximum agent turns per run.

Extra kwargs: The model config supports extra="allow" — any additional fields beyond the standard set are passed through to init_chat_model(). This enables OpenAI-compatible APIs via base_url and other provider-specific options.


Channel Configuration

Single channel (backward compatible):

channel:
  type: telegram
  token: ${TELEGRAM_BOT_TOKEN}
  allowed_users: [123456789]
  allowed_groups: []

Multi-channel (same workspace, multiple platforms):

channels:
  - type: telegram
    token: ${TELEGRAM_BOT_TOKEN}
    allowed_users: [123456789]
  - type: discord
    token: ${DISCORD_BOT_TOKEN}
    allowed_users: [916552354470461470]
    mention_required: true
    triggers: ["!ask"]

type — Channel type: telegram or discord.

token — Channel-specific bot token.

allowed_users — List of allowed user IDs. Controls who can DM the bot and serves as a fallback for messages from non-allowed groups.

allowed_groups — List of allowed group/guild IDs. When a group is allowed, any user in that group can interact with the bot without being individually listed in allowed_users.

mention_required — Only respond in group channels when @mentioned (default: false).

triggers — List of keyword triggers for group chat activation. Uses OR logic with mention_required.

name — Explicit channel name (required when using two channels of the same type).

context_messages — Number of recent channel messages to fetch as context when the bot is triggered in a group channel (default: 25, set to 0 to disable). Only applies to group/server messages, not DMs.

channel_log — Persistent JSONL logging of all visible channel messages (disabled by default):

channels:
  - type: discord
    token: ${DISCORD_BOT_TOKEN}
    allowed_groups: [111222333]
    mention_required: true
    context_messages: 25        # On-demand context fetch (default: 25)
    channel_log:
      enabled: false            # Disabled by default; set true to enable
      retention_days: 30        # Days before old logs are archived (default: 30)

Logs are written to memory/logs/channel/{server}/{channel}/{YYYY-MM-DD}.jsonl and are readable by the agent via read_file() and grep_files(). DMs are never logged. See Channel History for full details.

See Channels for full setup guides, multi-channel configuration, trigger-based activation, and channel history.


Queue Configuration

queue:
  mode: steer
  debounce_ms: 500

mode — Override global queue mode for this workspace.

debounce_ms — Override global debounce delay.


Heartbeat Configuration

heartbeat:
  enabled: true
  interval_minutes: 30           # How often to check in
  active_hours: "09:00-17:00"    # Only run during these hours (optional)
  suppress_ok: true              # Don't send message if agent responds "HEARTBEAT_OK"
  delivery: channel              # Where to deliver: channel, agent, or both
  target_channel: telegram       # Which channel to deliver to
  target_id: 123456789           # Channel-agnostic user/chat ID (preferred over chat_id)

enabled — Enable proactive heartbeat check-ins.

interval_minutes — How often to run heartbeats.

active_hours — Only run heartbeats within this window (workspace timezone). Format: "HH:MM-HH:MM". Outside active hours, heartbeats are silently skipped.

suppress_ok — If true and the agent responds with exactly "HEARTBEAT_OK", no message is sent. This prevents noisy "all clear" messages.

output — Where to send heartbeat messages.

See Scheduling for detailed heartbeat behavior including pre-flight skip, task-aware prompts, and the HEARTBEAT_OK protocol.


Approval Gates Configuration

approval_gates:
  enabled: true
  timeout_seconds: 120            # Seconds to wait for user response
  default_action: deny            # Action on timeout: "deny" or "approve"
  tools:
    overwrite_file:
      require_approval: true
      show_args: true             # Show tool arguments in approval prompt
    delete_task:
      require_approval: true

Session TTL

# Conversation auto-reset after inactivity (default: 180 minutes, 0 to disable)
session_ttl_minutes: 180

lifecycle:
  notify_session_ttl: true  # Notify user when session expires

session_ttl_minutes — Auto-resets the conversation (equivalent to /new) after the specified minutes of inactivity. Only applies to group/server channels — DMs are never auto-expired. The check is lazy — it only triggers when a new message arrives. When a session expires, channel context history is not injected into the fresh thread. Set to 0 to disable. Archives are tagged ["ttl_expired"].

lifecycle.notify_session_ttl — When true, the user receives a brief notification when a session expires and is reset.

Status Reminder

status_reminder:
  enabled: true              # Default: true
  threshold: 5               # Tool-calling turns before first reminder (1-50)
  max_reminders: 3           # Max reminders per agent run (0-20)
  cooldown_turns: 1          # Min turns between consecutive reminders (0-10)

enabled — Enable automatic reminders for the agent to use send_message() during long silent tool-calling runs. Only active when the send_message builtin is loaded. Default: true.

threshold — Number of consecutive tool-calling turns without a send_message() call before the first reminder is injected. Range: 1-50.

max_reminders — Maximum number of reminders the agent receives per agent run. Prevents nagging. Set to 0 to disable reminders entirely while keeping detection active. Range: 0-20.

cooldown_turns — Minimum number of turns between consecutive reminders. Prevents back-to-back reminders. Range: 0-10.

Reminders are injected as <framework_instruction> tags into the agent's message stream — they do not create extra checkpoint entries or consume additional API calls.

Status Updates

status_updates:
  enabled: true              # Default: true
  agent_start: true          # Report when agent run begins
  tool_calls_detected: true  # Report when agent decides to use tools
  tool_start: false          # Report before each tool execution
  tool_complete: false       # Report after each tool execution
  subagent_spawned: true     # Report when sub-agent is dispatched
  min_interval_seconds: 3    # Minimum seconds between auto-updates
  edit_in_place: true        # Edit single message in place (default: true)
  typing_indicator: true      # Send typing indicator while agent is processing
  reactions: true            # Add emoji reactions to the user's original message
  use_emojis: true           # Prefix status messages with relevant emojis

**enabled** — Enable automatic status updates sent to the user during agent execution. Default: `true`.

**agent_start** — Send `"Starting work..."` on the first run of a user message, and `"Continuing work..."` on subsequent runs (e.g., follow-up or self-continuation). Default: `true`. System events (cron, heartbeat, sub-agent completions) skip the agent start status to avoid mid-task confusion.

**tool_calls_detected** — Send `"Using tools: X, Y..."` when the agent decides to call tools. Default: `true`.

**tool_start** — Send `"Running tool: X..."` before each tool execution. Default: `false` (can be noisy).

**tool_complete** — Send `"Completed: X"` after each tool execution. Default: `false` (can be noisy).

**subagent_spawned** — Send `"Dispatched sub-agent: label"` when `spawn_agent` is called. Default: `true`.

**min_interval_seconds** — Minimum seconds between auto-detected status updates. Prevents spam during rapid tool-call sequences. Default: `3`.

**edit_in_place** — When `true` (default), the first status update sends a new message, and subsequent updates edit the same message in place. This prevents chat clutter. The status message is deleted after the agent run completes. When `false`, each update sends a separate message.

**typing_indicator** — When `true` (default), the framework sends a typing indicator (e.g., "typing..." on Telegram or "Agent is typing..." on Discord) while the agent is actively processing. Cleared when the agent completes or sends a real message.

**reactions** — When `true` (default), the framework adds an emoji reaction to the user's original message to indicate the agent has seen it and is working. The reaction is removed when the agent finishes. Only supported on channels that support emoji reactions (Telegram, Discord).

**use_emojis** — When `true` (default), status messages are prefixed with relevant emoji for visual clarity (e.g., `⚙️` for tool calls, `🚀` for starting work, `🤖` for sub-agent dispatch). Set to `false` for plain text status messages.

Status updates are sent directly to the user channel and do not create extra checkpoint entries or consume additional API calls. Agent-driven `report_progress` tool calls bypass all throttling.

---

### Merging Behavior

Workspace configuration deep-merges over global configuration:

- **Missing fields** inherit from global config
- **Present fields** override global values
- **Nested objects** merge recursively

**Example:**

**Global config.yaml:**
```yaml
agent:
  model: anthropic:claude-sonnet-4-20250514
  temperature: 0.7
  max_turns: 50

Workspace agent.yaml:

model:
  temperature: 0.5  # Override only temperature

Result:

model:
  provider: anthropic                   # From global (parsed from model string)
  model: claude-sonnet-4-20250514       # From global
  temperature: 0.5                      # From workspace
  max_turns: 50                         # From global


Environment Variables

OpenPaw supports environment variable expansion in configuration files using ${VAR_NAME} syntax. This is handled by openpaw/core/config/env_expansion.py.

Example

channel:
  type: telegram
  token: ${TELEGRAM_BOT_TOKEN}

model:
  provider: anthropic
  api_key: ${ANTHROPIC_API_KEY}

At runtime, OpenPaw expands these from the environment:

export TELEGRAM_BOT_TOKEN="123456:ABC-DEF..."
export ANTHROPIC_API_KEY="sk-ant-..."

Per-Workspace .env Files

Each workspace can have its own .env file for workspace-specific secrets:

agent_workspaces/my-agent/config/.env

These are automatically loaded via python-dotenv when the workspace starts.

Best Practices

  1. Never commit secrets — Use environment variables for all API keys and tokens
  2. Use .env files — Create a .env file for local development (add to .gitignore)
  3. Document required variables — List all required environment variables in README
  4. Provide defaults — Set sensible defaults in config.yaml where possible

Required Variables

For basic operation: - At least one channel bot token: - TELEGRAM_BOT_TOKEN — Telegram bot token - DISCORD_BOT_TOKEN — Discord bot token - At least one model provider credential: - ANTHROPIC_API_KEY — Claude API access - OPENAI_API_KEY — OpenAI GPT access - AWS credentials for Bedrock (see below)

For optional builtins: - BRAVE_API_KEY — Web search capability - OPENAI_API_KEY — Whisper audio transcription (also used for GPT models) - ELEVENLABS_API_KEY — Text-to-speech - Google service account JSON file — Email integration (see Builtins - Email)


Model Providers

Anthropic

model:
  provider: anthropic
  model: claude-sonnet-4-20250514
  api_key: ${ANTHROPIC_API_KEY}
  temperature: 0.7

Available models: - claude-sonnet-4-20250514 - claude-opus-4-20250514 - claude-haiku-4-20250514


OpenAI

model:
  provider: openai
  model: gpt-4o
  api_key: ${OPENAI_API_KEY}
  temperature: 0.7

Available models: - gpt-4o - gpt-4o-mini - gpt-4-turbo


AWS Bedrock

OpenPaw supports AWS Bedrock models via the bedrock_converse provider. Available models include Kimi K2 Thinking, Claude, Mistral, Amazon Nova, and others.

Configuration:

model:
  provider: bedrock_converse
  model: moonshot.kimi-k2-thinking
  region: us-east-1  # Optional, defaults to AWS_REGION env var

Available Bedrock Models: - moonshot.kimi-k2-thinking — Moonshot Kimi K2 (1T MoE, 256K context) - us.anthropic.claude-haiku-4-5-20251001-v1:0 — Claude Haiku 4.5 - amazon.nova-pro-v1:0 — Amazon Nova Pro - amazon.nova-lite-v1:0 — Amazon Nova Lite - mistral.mistral-large-2402-v1:0 — Mistral Large

Note: Newer Bedrock models may require inference profile IDs (prefixed with us. or global.) instead of bare model IDs. Use aws bedrock list-inference-profiles to discover available profiles.

AWS Credentials:

Configure via environment variables or AWS CLI profile:

# Environment variables
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_REGION="us-east-1"

# Or use AWS CLI profile
aws configure

Region Availability (Kimi K2): us-east-1, us-east-2, us-west-2, ap-northeast-1, ap-south-1, sa-east-1

API Key Exclusion: The api_key field is automatically excluded for Bedrock providers (uses AWS credentials instead).


OpenAI-Compatible APIs

Any OpenAI-compatible provider can be used by specifying base_url in the workspace model config. Extra kwargs beyond the standard set (provider, model, api_key, temperature, max_turns, timeout_seconds, region) are passed through to init_chat_model().

Example (Moonshot Kimi K2.5):

model:
  provider: openai
  model: kimi-k2.5
  api_key: ${MOONSHOT_API_KEY}
  base_url: https://api.moonshot.ai/v1
  temperature: 1.0

This enables any provider that implements the OpenAI API interface (Moonshot, Together AI, Groq, etc.).


Configuration Validation

OpenPaw validates configuration on startup using Pydantic models. Common errors and solutions:

Missing required field:

ValidationError: field required (type=value_error.missing)
Solution: Add the missing field to your config file.

Invalid value:

ValidationError: value is not a valid enumeration member (type=type_error.enum)
Solution: Check allowed values in this document.

Environment variable not set:

Error: Environment variable TELEGRAM_BOT_TOKEN not set
Solution: Export the variable or set it in your .env file.

Invalid timezone:

ValidationError: Invalid IANA timezone identifier: 'America/InvalidCity'
Solution: Use a valid IANA timezone from the tz database.


Multiple Configurations

You can maintain multiple configuration files for different environments:

# Development
poetry run openpaw -c config.dev.yaml -w my-agent

# Production
poetry run openpaw -c config.prod.yaml -w my-agent

# Testing
poetry run openpaw -c config.test.yaml -w my-agent

This enables environment-specific settings without modifying workspace files.

Example use cases: - Development: verbose logging, low concurrency, test API keys - Production: INFO logging, high concurrency, production API keys - Testing: minimal logging, minimal concurrency, mock channels


Advanced Configuration

Custom Model Timeout

model:
  provider: anthropic
  model: claude-sonnet-4-20250514
  timeout_seconds: 120  # Override default timeout

timeout_seconds — Maximum time to wait for a model response. Defaults to 60 seconds. Useful for long-running tasks or slow providers.


Queue Modes

The four queue modes — collect, steer, interrupt, and followup — control how the system handles messages that arrive while the agent is already working. See Queue System for detailed behavior and examples of each mode.


Builtins Allow/Deny Patterns

Allow all, deny specific:

builtins:
  allow: []  # Empty = allow all
  deny:
    - elevenlabs
    - group:system

Allow specific, deny all others:

builtins:
  allow:
    - brave_search
    - whisper
  # Everything else is denied (not in allow list)

Allow group, deny one member:

builtins:
  allow:
    - group:voice
  deny:
    - elevenlabs  # Deny takes precedence over allow

Priority: Deny always takes precedence over allow.


Configuration File Locations

Global config:

/path/to/project/config.yaml

Workspace config:

agent_workspaces/<workspace-name>/config/agent.yaml

Workspace .env:

agent_workspaces/<workspace-name>/config/.env

Static cron definitions:

agent_workspaces/<workspace-name>/config/crons/*.yaml

Dynamic cron storage:

agent_workspaces/<workspace-name>/data/dynamic_crons.json

Task storage:

agent_workspaces/<workspace-name>/data/TASKS.yaml

Framework-managed state (data/ is write-protected from agents):

agent_workspaces/<workspace-name>/data/
├── conversations.db      # AsyncSqliteSaver checkpoint database
├── sessions.json         # Session/conversation thread state
├── token_usage.jsonl     # Token usage metrics (append-only)
└── subagents.yaml        # Sub-agent requests and results


Configuration Tips

1. Start with config.example.yaml

Copy the example and modify:

cp config.example.yaml config.yaml

This ensures you have all required sections.

2. Use Workspace-Specific Overrides Sparingly

Only override what you need:

# Good — only overrides temperature
model:
  temperature: 0.5

# Bad — duplicates global config unnecessarily
model:
  provider: anthropic
  model: claude-sonnet-4-20250514
  api_key: ${ANTHROPIC_API_KEY}
  temperature: 0.5  # This is the only thing that changed
  max_turns: 50

3. Document Your Environment Variables

Create a .env.example file:

# .env.example
TELEGRAM_BOT_TOKEN=
DISCORD_BOT_TOKEN=
ANTHROPIC_API_KEY=
BRAVE_API_KEY=
OPENAI_API_KEY=
ELEVENLABS_API_KEY=

This helps onboarding and documents required credentials.

4. Test Configuration Changes

After modifying config, test with verbose logging:

poetry run openpaw -c config.yaml -w my-agent -v

Watch startup logs for validation errors.

5. Use Separate Configs for Environments

Don't modify config.yaml for different environments. Instead:

# config.dev.yaml
logging:
  level: DEBUG

# config.prod.yaml
logging:
  level: INFO

# Run with -c flag
poetry run openpaw -c config.dev.yaml -w my-agent

Troubleshooting

Config file not found:

Error: Configuration file not found: config.yaml
Solution: Ensure the file exists and the path is correct. Use -c flag to specify path.

YAML syntax error:

yaml.scanner.ScannerError: while scanning a simple key
Solution: Check YAML syntax. Ensure consistent indentation (use spaces, not tabs).

Environment variable not expanded:

Warning: Token contains literal '${TELEGRAM_BOT_TOKEN}'
Solution: Ensure the environment variable is set before running OpenPaw.

Workspace not found:

Error: Workspace 'my-agent' not found in agent_workspaces/
Solution: Ensure workspace directory exists and contains required identity files (agent/AGENT.md, agent/USER.md, agent/SOUL.md, agent/HEARTBEAT.md).

Model provider error:

Error: Invalid model provider: 'invalid-provider'
Solution: Use a supported provider: anthropic, openai, bedrock_converse, or configure OpenAI-compatible API via base_url.

Timezone validation error:

ValidationError: Invalid IANA timezone identifier: 'America/InvalidCity'
Solution: Use a valid IANA timezone. See list of tz database time zones.