# MeshAI Configuration # LLM-powered Meshtastic assistant # # Copy this to config.yaml and customize as needed. # For Docker: mount as /data/config.yaml # # Placeholders in and empty strings ("") are meant to be # filled in with your own values. Secrets are best supplied via environment # variables (e.g. ${LLM_API_KEY}) rather than committed to this file. # === BOT IDENTITY === bot: name: ai # Bot's display name owner: "" # Owner's callsign (optional) respond_to_dms: true # Respond to direct messages filter_bbs_protocols: true # Ignore advBBS sync/notification messages # === MESHTASTIC CONNECTION === connection: type: tcp # serial | tcp serial_port: /dev/ttyUSB0 # For serial connection tcp_host: localhost # For TCP connection (meshtasticd / node IP) tcp_port: 4403 # === RESPONSE BEHAVIOR === response: delay_min: 2.2 # Min delay before responding (seconds) delay_max: 3.0 # Max delay before responding max_length: 200 # Max chars per message chunk max_messages: 3 # Max message chunks per response # === CONVERSATION HISTORY === history: database: /data/conversations.db max_messages_per_user: 50 # Messages to keep per user conversation_timeout: 86400 # Conversation expiry (seconds, 86400=24h) auto_cleanup: true # Auto-delete old conversations cleanup_interval_hours: 24 # How often to run cleanup max_age_days: 30 # Delete conversations older than this # === MEMORY OPTIMIZATION === memory: enabled: true # Enable rolling summary memory window_size: 4 # Recent message pairs to keep in full summarize_threshold: 8 # Messages before re-summarizing # === MESH CONTEXT === context: enabled: true # Observe channel traffic for LLM context observe_channels: [] # Channel indices to observe (empty = all) ignore_nodes: [] # Node IDs to exclude from observation max_age: 2592000 # Max age in seconds (default 30 days) max_context_items: 20 # Max observations injected into LLM context # === LLM BACKEND === llm: backend: openai # openai | anthropic | google api_key: "" # API key (or use LLM_API_KEY env var) base_url: https://api.openai.com/v1 # API base URL (point at a local # OpenAI-compatible server if desired) model: gpt-4o-mini # Model name (e.g. gpt-4o-mini, # claude-sonnet, gemini-2.5-flash) timeout: 30 # Request timeout (seconds) system_prompt: >- You are a helpful assistant on a Meshtastic mesh network. Keep responses very brief - 1-2 short sentences, under 300 characters. Only give longer answers if the user explicitly asks for detail or explanation. Be concise but friendly. No markdown formatting. google_grounding: false # Enable Google Search grounding (Gemini only, billed per query) # === WEATHER === weather: primary: openmeteo # openmeteo | wttr | llm fallback: llm # openmeteo | wttr | llm | none default_location: "" # Default location for !weather (optional) # === MESHMONITOR INTEGRATION === meshmonitor: enabled: false # Enable MeshMonitor trigger sync url: "" # MeshMonitor web UI URL (e.g. http://:3333) inject_into_prompt: true # Include trigger list in LLM prompt refresh_interval: 300 # Seconds between trigger refreshes # === KNOWLEDGE BASE (RAG) === # Optional. With no external services, MeshAI uses a self-contained # on-device SQLite knowledge base. To use a network Qdrant hybrid backend # instead, configure your own qdrant_host / tei_host (see README). knowledge: enabled: false # Enable knowledge base search db_path: "" # Path to knowledge SQLite database top_k: 5 # Number of chunks to retrieve per query # === MESH DATA SOURCES === # Connect to Meshview and/or MeshMonitor instances for live mesh # network analysis. Supports multiple sources. Configure via TUI # with `meshai --config` (Mesh Sources menu). # # mesh_sources: # - name: "my-meshview" # type: meshview # url: "https://meshview.example.com" # refresh_interval: 300 # enabled: true # # - name: "my-meshmonitor" # type: meshmonitor # url: "http://:3333" # api_token: "${MM_API_TOKEN}" # refresh_interval: 300 # enabled: true # # - name: "mqtt-broker" # type: mqtt # host: "" # port: 1883 # username: "${MQTT_USER}" # password: "${MQTT_PASSWORD}" # topic_root: "msh/US" # use_tls: false # enabled: true mesh_sources: [] # === MESH INTELLIGENCE === # Geographic clustering and health scoring for mesh analysis. # Requires mesh_sources to be configured with at least one data source. # # mesh_intelligence: # enabled: true # region_radius_miles: 40.0 # Radius for region clustering # locality_radius_miles: 8.0 # Radius for locality clustering # offline_threshold_hours: 2 # Hours before node considered offline # packet_threshold: 500 # Non-text packets per 24h to flag # battery_warning_percent: 30 # Battery level for warnings # infra_overrides: [] # Node IDs to exclude from infrastructure # region_labels: {} # Override auto-names: {"": ""} mesh_intelligence: enabled: false region_radius_miles: 40.0 locality_radius_miles: 8.0 offline_threshold_hours: 2 packet_threshold: 500 battery_warning_percent: 30 infra_overrides: [] region_labels: {} # === ENVIRONMENTAL FEEDS === # Live situational awareness from NWS, NOAA Space Weather, Open-Meteo, and more. # Provides weather alerts, HF propagation assessment, and tropospheric ducting. # All geographic values below are placeholders — set them for your own area. # environmental: enabled: false nws_zones: [] # Your NWS public-forecast zone IDs, e.g. ["XXZ001", "XXZ002"] # Look yours up at https://www.weather.gov/pimar/PubZone # NWS Weather Alerts (api.weather.gov) nws: enabled: true tick_seconds: 60 areas: [] # State/marine codes, e.g. ["ID"] severity_min: "moderate" user_agent: "(meshai.example.com, ops@example.com)" # REQUIRED by NWS — use your own contact # NOAA Space Weather (services.swpc.noaa.gov) swpc: enabled: true # Tropospheric ducting assessment (Open-Meteo GFS, no auth) ducting: enabled: true tick_seconds: 10800 # 3 hours latitude: 0.0 # center of your mesh coverage area longitude: 0.0 # NIFC Fire Perimeters fires: enabled: false tick_seconds: 600 state: "" # e.g. "US-ID" # Avalanche Advisories avalanche: enabled: false tick_seconds: 1800 center_ids: [] # Your avalanche center ID(s), e.g. ["XXFAC"] season_months: [12, 1, 2, 3, 4] # USGS Stream Gauges (waterservices.usgs.gov) # Find site IDs at https://waterdata.usgs.gov/nwis usgs: enabled: false tick_seconds: 900 # Min 15 min per USGS guidelines sites: [] # e.g. ["XXXXXXXX", "XXXXXXXX"] # TomTom Traffic Flow (api.tomtom.com, requires API key) traffic: enabled: false tick_seconds: 300 api_key: "" # Get key at developer.tomtom.com corridors: [] # Example corridor: # - name: "" # lat: 0.0 # lon: 0.0 # 511 Road Conditions (state-specific, configurable base URL) roads511: enabled: false tick_seconds: 300 api_key: "" base_url: "" # e.g. "https://511..gov/api/v2" endpoints: ["/get/event"] bbox: [] # [west, south, east, north] # NASA FIRMS Satellite Fire Detection # Early warning via satellite hotspots, hours before official perimeters. # Get MAP_KEY at: https://firms.modaps.eosdis.nasa.gov/api/area/ firms: enabled: false tick_seconds: 1800 # 30 min default map_key: "" # Required - NASA FIRMS MAP_KEY source: "VIIRS_SNPP_NRT" # VIIRS_SNPP_NRT, VIIRS_NOAA20_NRT, MODIS_NRT bbox: [] # [west, south, east, north] - Required day_range: 1 # 1-10 days of data confidence_min: "nominal" # low, nominal, high proximity_km: 10.0 # km to match known fire perimeters # === NOTIFICATION DELIVERY === # Route alerts to channels (mesh, email, webhook) based on rules. # Categories match alert types from the alert engine. # Severity levels: routine (informational), priority (needs attention), immediate (act now) notifications: enabled: false quiet_hours_enabled: true # Master toggle for quiet hours feature quiet_hours_start: "22:00" # Suppress non-emergency alerts during quiet hours quiet_hours_end: "06:00" # Digest scheduler: collects priority/routine events and delivers a summary # at the configured time to rules with trigger_type='schedule' and # schedule_match='digest'. digest: schedule: "07:00" # HH:MM local time to fire digest include: [] # Toggle names to include (empty = default set) # Default set: weather, fire, seismic, avalanche, roads, mesh_health, tracking, other # Notification rules - each rule is self-contained with its own delivery config. # Default baseline rules are created on a fresh install. rules: # Emergency Broadcast - all emergencies go out immediately - name: "Emergency Broadcast" enabled: true trigger_type: condition categories: [] # Empty = all categories min_severity: "immediate" delivery_type: mesh_broadcast broadcast_channel: 0 cooldown_minutes: 5 override_quiet: true # Send even during quiet hours # Infrastructure Down - critical node and infrastructure offline alerts - name: "Infrastructure Down" enabled: true trigger_type: condition categories: ["infra_offline", "critical_node_down"] min_severity: "priority" delivery_type: mesh_broadcast broadcast_channel: 0 cooldown_minutes: 30 override_quiet: false # Fire Alert - wildfire proximity and new ignition - name: "Fire Alert" enabled: true trigger_type: condition categories: ["wildfire_proximity", "new_ignition"] min_severity: "routine" delivery_type: mesh_broadcast broadcast_channel: 0 cooldown_minutes: 60 override_quiet: false # Severe Weather - weather warnings - name: "Severe Weather" enabled: true trigger_type: condition categories: ["weather_warning"] min_severity: "priority" delivery_type: mesh_broadcast broadcast_channel: 0 cooldown_minutes: 30 override_quiet: false # Example: Morning Digest -> mesh broadcast # - name: "Morning Digest Mesh" # enabled: false # trigger_type: schedule # schedule_match: "digest" # Required for digest delivery # delivery_type: mesh_broadcast # broadcast_channel: 0 # Example: Morning Digest -> email # - name: "Morning Digest Email" # enabled: false # trigger_type: schedule # schedule_match: "digest" # delivery_type: email # smtp_host: "" # smtp_port: 587 # smtp_user: "" # smtp_password: "${SMTP_PASSWORD}" # smtp_tls: true # from_address: "meshai@example.com" # recipients: ["admin@example.com"] # Example: All warnings -> webhook (Discord/Slack/etc.) # - name: "Webhook Alerts" # enabled: true # trigger_type: condition # categories: [] # min_severity: "priority" # delivery_type: webhook # webhook_url: "${ALERT_WEBHOOK_URL}" # cooldown_minutes: 10 # Example: Rule with no delivery (matches and logs, but doesn't send) # - name: "Monitor Only" # enabled: true # trigger_type: condition # categories: ["battery_warning"] # min_severity: "priority" # delivery_type: "" # Empty = no delivery, just tracks matches # === WEB DASHBOARD === dashboard: enabled: true port: 8080 host: "0.0.0.0"