// Package config provides the configuration schema and loader for agents. package config import "time" // AgentConfig is the root configuration for a single agent. type AgentConfig struct { Agent AgentMeta `yaml:"agent"` Personality PersonalityCfg `yaml:"personality"` LLM LLMCfg `yaml:"llm"` Tools ToolsCfg `yaml:"tools"` Matrix MatrixCfg `yaml:"matrix"` Agents AgentsCfg `yaml:"agents"` SSH SSHCfg `yaml:"ssh"` Security SecurityCfg `yaml:"security"` Schedules []ScheduleCfg `yaml:"schedules"` Observability ObservabilityCfg `yaml:"observability"` Resilience ResilienceCfg `yaml:"resilience"` Storage StorageCfg `yaml:"storage"` Memory MemoryCfg `yaml:"memory"` } // ── Identity ────────────────────────────────────────────────────────────── type AgentMeta struct { ID string `yaml:"id"` Name string `yaml:"name"` Version string `yaml:"version"` Enabled bool `yaml:"enabled"` Description string `yaml:"description"` Tags []string `yaml:"tags"` } // ── Personality ─────────────────────────────────────────────────────────── type PersonalityCfg struct { Tone string `yaml:"tone"` Verbosity string `yaml:"verbosity"` Language string `yaml:"language"` LanguagesSupported []string `yaml:"languages_supported"` EmojiStyle string `yaml:"emoji_style"` Prefix string `yaml:"prefix"` ErrorStyle string `yaml:"error_style"` Templates TemplatesCfg `yaml:"templates"` Behavior BehaviorCfg `yaml:"behavior"` } type TemplatesCfg struct { Greeting string `yaml:"greeting"` UnknownCommand string `yaml:"unknown_command"` PermissionDenied string `yaml:"permission_denied"` Error string `yaml:"error"` Success string `yaml:"success"` Busy string `yaml:"busy"` } type BehaviorCfg struct { Proactive bool `yaml:"proactive"` AskConfirmation bool `yaml:"ask_confirmation"` ShowReasoning bool `yaml:"show_reasoning"` ThreadReplies bool `yaml:"thread_replies"` TypingIndicator bool `yaml:"typing_indicator"` AcknowledgeReceipt bool `yaml:"acknowledge_receipt"` } // ── LLM ─────────────────────────────────────────────────────────────────── type LLMCfg struct { Primary LLMProviderCfg `yaml:"primary"` Fallback LLMProviderCfg `yaml:"fallback"` Reasoning LLMReasoningCfg `yaml:"reasoning"` ToolUse LLMToolUseCfg `yaml:"tool_use"` RateLimit LLMRateLimitCfg `yaml:"rate_limit"` } type LLMProviderCfg struct { Provider string `yaml:"provider"` Model string `yaml:"model"` APIKeyEnv string `yaml:"api_key_env"` BaseURL string `yaml:"base_url"` MaxTokens int `yaml:"max_tokens"` Temperature float64 `yaml:"temperature"` // ClaudeCode holds configuration for the claude-code provider (claude -p). ClaudeCode ClaudeCodeCfg `yaml:"claude_code"` } // ClaudeCodeCfg configures the claude -p subprocess provider. type ClaudeCodeCfg struct { Binary string `yaml:"binary"` // path to claude binary (default: "claude") Timeout time.Duration `yaml:"timeout"` // subprocess timeout (default: 5m) DisableTools bool `yaml:"disable_tools"` // pass --tools "" to disable all internal tools AllowedTools []string `yaml:"allowed_tools"` // tools claude -p can use internally (e.g. Bash, Read, Edit) DisallowedTools []string `yaml:"disallowed_tools"` // tools to block WorkingDir string `yaml:"working_dir"` // working directory for claude -p PermissionMode string `yaml:"permission_mode"` // default, acceptEdits, bypassPermissions, plan Model string `yaml:"model"` // inner model: sonnet, opus, haiku, or full name FallbackModel string `yaml:"fallback_model"` // fallback model if primary is overloaded SessionID string `yaml:"session_id"` // fixed session ID for continuity AddDirs []string `yaml:"add_dirs"` // additional directories accessible } type LLMReasoningCfg struct { SystemPromptFile string `yaml:"system_prompt_file"` ContextWindow int `yaml:"context_window"` MemoryMessages int `yaml:"memory_messages"` } type LLMToolUseCfg struct { Enabled bool `yaml:"enabled"` MaxIterations int `yaml:"max_iterations"` ParallelCalls bool `yaml:"parallel_calls"` } type LLMRateLimitCfg struct { RequestsPerMinute int `yaml:"requests_per_minute"` TokensPerMinute int `yaml:"tokens_per_minute"` ConcurrentRequests int `yaml:"concurrent_requests"` } // ── Tools ───────────────────────────────────────────────────────────────── type ToolsCfg struct { SSH SSHToolCfg `yaml:"ssh"` HTTP HTTPToolCfg `yaml:"http"` Scripts ScriptsCfg `yaml:"scripts"` FileOps FileOpsCfg `yaml:"file_ops"` Matrix MatrixToolCfg `yaml:"matrix_send"` MCP MCPToolCfg `yaml:"mcp"` Memory MemoryToolCfg `yaml:"memory"` Knowledge KnowledgeToolCfg `yaml:"knowledge"` SharedKnowledge SharedKnowledgeToolCfg `yaml:"shared_knowledge"` } type MatrixToolCfg struct { AllowedRooms []string `yaml:"allowed_rooms"` // if non-empty, only these room IDs can be targeted } type KnowledgeToolCfg struct { Enabled bool `yaml:"enabled"` Dir string `yaml:"dir"` // default: "./knowledge" (relative to agent dir) } type SharedKnowledgeToolCfg struct { Enabled bool `yaml:"enabled"` // default false Dir string `yaml:"dir"` // default "knowledges" (relative to project root) DBPath string `yaml:"db_path"` // default "knowledges/data/knowledge.db" } type SSHToolCfg struct { Enabled bool `yaml:"enabled"` AllowedTargets []string `yaml:"allowed_targets"` AllowedCommands []string `yaml:"allowed_commands"` // allowlist: if non-empty, only these command prefixes are permitted ForbiddenCommands []string `yaml:"forbidden_commands"` Timeout time.Duration `yaml:"timeout"` MaxConcurrent int `yaml:"max_concurrent"` RequireConfirmation []string `yaml:"require_confirmation"` } type HTTPToolCfg struct { Enabled bool `yaml:"enabled"` AllowedDomains []string `yaml:"allowed_domains"` Timeout time.Duration `yaml:"timeout"` MaxRetries int `yaml:"max_retries"` } type ScriptsCfg struct { Enabled bool `yaml:"enabled"` ScriptsDir string `yaml:"scripts_dir"` Allowed []string `yaml:"allowed"` Timeout time.Duration `yaml:"timeout"` Sandbox bool `yaml:"sandbox"` } type FileOpsCfg struct { Enabled bool `yaml:"enabled"` AllowedPaths []string `yaml:"allowed_paths"` ReadOnly bool `yaml:"read_only"` } type MCPToolCfg struct { Enabled bool `yaml:"enabled"` Servers []MCPServerCfg `yaml:"servers"` Expose MCPExposeCfg `yaml:"expose"` } type MCPServerCfg struct { Name string `yaml:"name"` // nombre logico del servidor Transport string `yaml:"transport"` // "stdio" | "sse" (default: auto-detect) Command string `yaml:"command"` // stdio: comando a ejecutar Args []string `yaml:"args"` // stdio: argumentos del comando Env map[string]string `yaml:"env"` // stdio: variables de entorno extra URL string `yaml:"url"` // sse: URL del servidor Headers map[string]string `yaml:"headers"` // sse: headers HTTP extra (auth, etc.) Tools []string `yaml:"tools"` // filtro: solo exponer estas tools (vacio = todas) Prefix string `yaml:"prefix"` // prefijo para nombres de tools (evitar colisiones) Timeout time.Duration `yaml:"timeout"` // timeout por llamada (default: 30s) } type MCPExposeCfg struct { Port int `yaml:"port"` Tools []string `yaml:"tools"` } // ── Matrix ──────────────────────────────────────────────────────────────── type MatrixCfg struct { Homeserver string `yaml:"homeserver"` UserID string `yaml:"user_id"` AccessTokenEnv string `yaml:"access_token_env"` DeviceID string `yaml:"device_id"` Encryption EncryptionCfg `yaml:"encryption"` Rooms RoomsCfg `yaml:"rooms"` Filters FiltersCfg `yaml:"filters"` Threads ThreadsCfg `yaml:"threads"` } // ThreadsCfg controls Matrix thread support (m.thread). type ThreadsCfg struct { Enabled bool `yaml:"enabled"` // respond in threads when message is in a thread (default true) AutoThread bool `yaml:"auto_thread"` // auto-create a thread for each new conversation (default false) } type EncryptionCfg struct { Enabled bool `yaml:"enabled"` StorePath string `yaml:"store_path"` PickleKeyEnv string `yaml:"pickle_key_env"` // env var with hex-encoded 32-byte key TrustMode string `yaml:"trust_mode"` // tofu | cross-signing | manual RecoveryKeyEnv string `yaml:"recovery_key_env"` // env var with base58 SSSS recovery key for cross-signing } type RoomsCfg struct { Listen []string `yaml:"listen"` Respond []string `yaml:"respond"` Admin []string `yaml:"admin"` } type FiltersCfg struct { CommandPrefix string `yaml:"command_prefix"` MentionRespond bool `yaml:"mention_respond"` DMRespond bool `yaml:"dm_respond"` IgnoreBots bool `yaml:"ignore_bots"` IgnoreUsers []string `yaml:"ignore_users"` // Deprecated: use security/ centralized groups instead. Kept for backward compatibility. AllowedUsers []string `yaml:"allowed_users"` UnauthorizedResponse string `yaml:"unauthorized_response"` // silent (default) | explicit MinPowerLevel int `yaml:"min_power_level"` } // ── Inter-agent ─────────────────────────────────────────────────────────── type AgentsCfg struct { Peers []PeerCfg `yaml:"peers"` Delegation DelegationCfg `yaml:"delegation"` Protocol ProtocolCfg `yaml:"protocol"` } type PeerCfg struct { ID string `yaml:"id"` Capabilities []string `yaml:"capabilities"` Room string `yaml:"room"` } type DelegationCfg struct { Enabled bool `yaml:"enabled"` CanDelegateTo []string `yaml:"can_delegate_to"` CanReceiveFrom []string `yaml:"can_receive_from"` MaxDepth int `yaml:"max_delegation_depth"` Timeout time.Duration `yaml:"timeout"` } type ProtocolCfg struct { Format string `yaml:"format"` // json | protobuf | msgpack Channel string `yaml:"channel"` // matrix | grpc | channel HeartbeatInterval time.Duration `yaml:"heartbeat_interval"` } // ── SSH Inventory ───────────────────────────────────────────────────────── type SSHCfg struct { Defaults SSHDefaultsCfg `yaml:"defaults"` Targets map[string]SSHTargetCfg `yaml:"targets"` } type SSHDefaultsCfg struct { User string `yaml:"user"` Port int `yaml:"port"` KeyFileEnv string `yaml:"key_file_env"` KnownHosts string `yaml:"known_hosts"` KeepaliveInterval time.Duration `yaml:"keepalive_interval"` Timeout time.Duration `yaml:"timeout"` } type SSHTargetCfg struct { Hosts []string `yaml:"hosts"` User string `yaml:"user"` Port int `yaml:"port"` JumpHost string `yaml:"jump_host"` KeyFileEnv string `yaml:"key_file_env"` } // ── Security ────────────────────────────────────────────────────────────── type SecurityCfg struct { // Deprecated: use security/ centralized groups instead (see security/user-groups.yaml, permissions.yaml). // Kept for backward compatibility; will be removed in a future issue. Roles map[string]RoleCfg `yaml:"roles"` Audit AuditCfg `yaml:"audit"` Secrets SecretsCfg `yaml:"secrets"` Sanitize SanitizeCfg `yaml:"sanitize"` ToolRateLimit ToolRateLimitCfg `yaml:"tool_rate_limit"` } // ToolRateLimitCfg controls per-room rate limiting of tool executions. type ToolRateLimitCfg struct { Enabled bool `yaml:"enabled"` // enable tool rate limiting (default false) MaxCallsPerMin int `yaml:"max_calls_per_min"` // max tool calls per room per minute (default 10) CleanupIntervalS int `yaml:"cleanup_interval_s"` // seconds between stale entry cleanup (default 60) } // SanitizeCfg controls prompt injection detection on incoming messages. type SanitizeCfg struct { Enabled bool `yaml:"enabled"` // enable sanitization (default false) Mode string `yaml:"mode"` // warn | strip | reject (default warn) MinSeverity string `yaml:"min_severity"` // low | medium | high (default medium) DisabledPatterns []string `yaml:"disabled_patterns"` // pattern names to skip } type RoleCfg struct { Users []string `yaml:"users"` Actions []string `yaml:"actions"` } type AuditCfg struct { Enabled bool `yaml:"enabled"` LogFile string `yaml:"log_file"` LogToRoom string `yaml:"log_to_room"` Include []string `yaml:"include"` } type SecretsCfg struct { Provider string `yaml:"provider"` // env | vault | sops } // ── Scheduling ──────────────────────────────────────────────────────────── type ScheduleCfg struct { Name string `yaml:"name"` Cron string `yaml:"cron"` Action ScheduledAction `yaml:"action"` OnFailure FailureAction `yaml:"on_failure"` OutputRoom string `yaml:"output_room"` } type ScheduledAction struct { Kind string `yaml:"kind"` Target string `yaml:"target"` Command string `yaml:"command"` Script string `yaml:"script"` // Phase 1: send_message and llm_prompt fields Message string `yaml:"message"` // inline text for send_message Template string `yaml:"template"` // path to .md file for send_message Prompt string `yaml:"prompt"` // inline prompt text for llm_prompt } type FailureAction struct { NotifyRoom string `yaml:"notify_room"` EscalateTo string `yaml:"escalate_to"` } // ── Observability ───────────────────────────────────────────────────────── type ObservabilityCfg struct { Logging LoggingCfg `yaml:"logging"` Metrics MetricsCfg `yaml:"metrics"` Health HealthCfg `yaml:"health"` Tracing TracingCfg `yaml:"tracing"` } type LoggingCfg struct { Level string `yaml:"level"` Format string `yaml:"format"` // json | text Output string `yaml:"output"` // stdout | file File string `yaml:"file"` } type MetricsCfg struct { Enabled bool `yaml:"enabled"` Port int `yaml:"port"` Path string `yaml:"path"` Export string `yaml:"export"` // prometheus } type HealthCfg struct { Enabled bool `yaml:"enabled"` Port int `yaml:"port"` Path string `yaml:"path"` } type TracingCfg struct { Enabled bool `yaml:"enabled"` Provider string `yaml:"provider"` Endpoint string `yaml:"endpoint"` } // ── Resilience ──────────────────────────────────────────────────────────── type ResilienceCfg struct { CircuitBreaker CircuitBreakerCfg `yaml:"circuit_breaker"` Retry RetryCfg `yaml:"retry"` Shutdown ShutdownCfg `yaml:"shutdown"` Queue QueueCfg `yaml:"queue"` } type CircuitBreakerCfg struct { FailureThreshold int `yaml:"failure_threshold"` Timeout time.Duration `yaml:"timeout"` HalfOpenMax int `yaml:"half_open_max"` } type RetryCfg struct { MaxAttempts int `yaml:"max_attempts"` Backoff string `yaml:"backoff"` // fixed | exponential InitialDelay time.Duration `yaml:"initial_delay"` MaxDelay time.Duration `yaml:"max_delay"` } type ShutdownCfg struct { Timeout time.Duration `yaml:"timeout"` DrainMessages bool `yaml:"drain_messages"` SaveState bool `yaml:"save_state"` StateFile string `yaml:"state_file"` } type QueueCfg struct { Enabled bool `yaml:"enabled"` MaxSize int `yaml:"max_size"` PriorityUsers []string `yaml:"priority_users"` } // ── Storage ─────────────────────────────────────────────────────────────── type StorageCfg struct { BasePath string `yaml:"base_path"` // root for all data; default $AGENTS_DATA_DIR/ or agents//data State StateStorageCfg `yaml:"state"` Cache CacheStorageCfg `yaml:"cache"` History HistoryStorageCfg `yaml:"history"` } type StateStorageCfg struct { Backend string `yaml:"backend"` // sqlite | redis | file Path string `yaml:"path"` } type CacheStorageCfg struct { Enabled bool `yaml:"enabled"` Backend string `yaml:"backend"` // memory | redis TTL time.Duration `yaml:"ttl"` MaxEntries int `yaml:"max_entries"` } type HistoryStorageCfg struct { Backend string `yaml:"backend"` Path string `yaml:"path"` Retention time.Duration `yaml:"retention"` } // ── Memory ──────────────────────────────────────────────────────────────── type MemoryCfg struct { Enabled bool `yaml:"enabled"` WindowSize int `yaml:"window_size"` // sliding window size per room (default 20) DBPath string `yaml:"db_path"` // SQLite path (default agents//data/memory.db) } type MemoryToolCfg struct { Enabled bool `yaml:"enabled"` } // ── Special Agents ──────────────────────────────────────────────────────── // SpecialConfig is the root configuration for a special agent (no Matrix identity). type SpecialConfig struct { Special SpecialMeta `yaml:"special"` LLM LLMCfg `yaml:"llm"` Orchestration OrchestrationCfg `yaml:"orchestration"` } // SpecialMeta identifies a special agent. type SpecialMeta struct { ID string `yaml:"id"` Type string `yaml:"type"` // "orchestrator", "scheduler", etc. Enabled bool `yaml:"enabled"` Description string `yaml:"description"` } // OrchestrationCfg configures the multi-bot orchestrator. type OrchestrationCfg struct { MaxIterations int `yaml:"max_iterations"` QualityThreshold float64 `yaml:"quality_threshold"` DelegationTimeout time.Duration `yaml:"delegation_timeout"` RepetitionThreshold float64 `yaml:"repetition_threshold"` // 0-1: similarity ratio to detect circular conversations Rooms []OrchestratedRoomCfg `yaml:"rooms"` } // OrchestratedRoomCfg defines a room managed by the orchestrator. type OrchestratedRoomCfg struct { RoomID string `yaml:"room_id"` Participants []string `yaml:"participants"` // bot IDs that participate in this room }