69607b3a65
Implementa una base de conocimiento persistente por agente siguiendo el patrón pure core / impure shell: - pkg/knowledge/: tipos puros (Document, Store interface) - shell/knowledge/: FileStore con SQLite para indexación y archivos .md - tools/knowledge.go: 4 tools LLM (search, read, write, list) - tools/knowledge_test.go: tests unitarios de las tools - internal/config/schema.go: nuevo KnowledgeToolCfg en ToolsCfg - agents/runtime.go: inicialización del store y registro de tools - agents/*/knowledge/about-me.md: documentos semilla para cada agente Cada agente puede buscar, leer, crear y actualizar documentos de conocimiento. Los archivos .md viven en agents/<id>/knowledge/ y se indexan en SQLite (agents/<id>/data/knowledge.db). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
457 lines
17 KiB
Go
457 lines
17 KiB
Go
// 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"`
|
|
MCP MCPToolCfg `yaml:"mcp"`
|
|
Memory MemoryToolCfg `yaml:"memory"`
|
|
Knowledge KnowledgeToolCfg `yaml:"knowledge"`
|
|
}
|
|
|
|
type KnowledgeToolCfg struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
Dir string `yaml:"dir"` // default: "./knowledge" (relative to agent dir)
|
|
}
|
|
|
|
type SSHToolCfg struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
AllowedTargets []string `yaml:"allowed_targets"`
|
|
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"`
|
|
URL string `yaml:"url"`
|
|
Tools []string `yaml:"tools"`
|
|
}
|
|
|
|
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"`
|
|
}
|
|
|
|
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"`
|
|
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 {
|
|
Roles map[string]RoleCfg `yaml:"roles"`
|
|
Audit AuditCfg `yaml:"audit"`
|
|
Secrets SecretsCfg `yaml:"secrets"`
|
|
}
|
|
|
|
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"`
|
|
}
|
|
|
|
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 {
|
|
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/<id>/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
|
|
}
|