UFO² features a modern, modular configuration system designed for flexibility, maintainability, and backward compatibility. This guide explains the overall architecture and design principles.
The configuration system follows professional software engineering best practices:
Configuration files are organized by domain rather than monolithic structure:
- Agent configurations (
agents.yaml) - LLM settings for different agents → Agent Config Guide - System configurations (
system.yaml) - Execution and runtime settings → System Config Guide - RAG configurations (
rag.yaml) - Knowledge retrieval settings → RAG Config Guide - MCP configurations (
mcp.yaml) - Model Context Protocol servers → MCP Config Guide - Pricing configurations (
prices.yaml) - Cost tracking for different models → Pricing Config Guide - Third-party configurations (
third_party.yaml) - External agent integration (LinuxAgent, HardwareAgent) → Third-Party Config Guide
Hybrid approach combining:
- Fixed typed fields - IDE autocomplete, type checking, and IntelliSense
- Dynamic YAML fields - Add new settings without code changes
Example:
# Type-safe access (recommended)
config = get_ufo_config()
max_step = config.system.max_step # IDE autocomplete!
api_model = config.app_agent.api_model
# Dynamic access (for custom fields)
custom_value = config.CUSTOM_FEATURE_FLAG
new_setting = config["NEW_YAML_KEY"]
# Backward compatible (legacy code still works)
max_step_old = config["MAX_STEP"]Zero breaking changes - existing code continues to work:
- Old configuration paths still supported (
ufo/config/) - Old access patterns still work (
config["MAX_STEP"]) - Automatic migration warnings guide users to new structure
Your existing code will continue to work without any modifications. The system automatically falls back to legacy paths and access patterns. See the Migration Guide for details on upgrading to the new structure.
No manual file registration needed:
- All
*.yamlfiles inconfig/ufo/are automatically loaded - Files are merged intelligently with deep merging
- Environment-specific overrides (
*_dev.yaml,*_test.yaml) supported
UFO/
├── config/ ← New Configuration Root (Recommended)
│ ├── ufo/ ← UFO² Configurations
│ │ ├── agents.yaml # LLM agent settings
│ │ ├── agents.yaml.template # Template for setup
│ │ ├── system.yaml # System and runtime settings
│ │ ├── rag.yaml # RAG knowledge settings
│ │ ├── mcp.yaml # MCP server configurations
│ │ ├── prices.yaml # Model pricing
│ │ └── third_party.yaml # Third-party agents (optional)
│ │
│ ├── galaxy/ ← Galaxy Configurations
│ │ ├── agent.yaml # Constellation agent settings
│ │ ├── agent.yaml.template # Template for setup
│ │ ├── constellation.yaml # Constellation runtime settings
│ │ └── devices.yaml # Device/client configurations
│ │
│ ├── config_loader.py # Modern config loader
│ └── config_schemas.py # Type definitions
│
└── ufo/config/ ← Legacy Path (Still Supported)
└── config.yaml # Old monolithic config
The Galaxy constellation system has its own set of configuration files in config/galaxy/:
| File | Purpose | Template | Documentation |
|---|---|---|---|
| constellation.yaml | Constellation runtime settings (heartbeat, concurrency, step limits) | No | Galaxy Constellation Config |
| devices.yaml | Device agent definitions (device_id, server_url, capabilities, metadata) | No | Galaxy Devices Config |
| agent.yaml | Constellation agent LLM configuration (API settings, prompts) | Yes (.template) | Galaxy Agent Config |
config/galaxy/
├── constellation.yaml # Runtime settings for orchestrator
│ ├── CONSTELLATION_ID # Constellation identifier
│ ├── HEARTBEAT_INTERVAL # Health check frequency
│ ├── RECONNECT_DELAY # Reconnection delay
│ ├── MAX_CONCURRENT_TASKS # Task concurrency limit
│ ├── MAX_STEP # Step limit per session
│ ├── DEVICE_INFO # Path to devices.yaml
│ └── LOG_TO_MARKDOWN # Markdown logging flag
│
├── devices.yaml # Device definitions
│ └── devices: [] # Array of device configurations
│ ├── device_id # Unique device identifier
│ ├── server_url # WebSocket endpoint
│ ├── os # Operating system
│ ├── capabilities # Device capabilities
│ ├── metadata # Custom metadata
│ ├── max_retries # Connection retry limit
│ └── auto_connect # Auto-connect flag
│
└── agent.yaml # Constellation agent LLM config
└── CONSTELLATION_AGENT:
├── REASONING_MODEL # Enable reasoning mode
├── API_TYPE # API provider (openai, azure, azure_ad)
├── API_BASE # API base URL
├── API_KEY # API authentication key
├── API_VERSION # API version
├── API_MODEL # Model name/deployment
├── AAD_* # Azure AD auth settings
└── *_PROMPT # Prompt template paths
# Load Galaxy configurations
from config.config_loader import get_galaxy_config
# Load Galaxy configuration (includes agent and constellation settings)
galaxy_config = get_galaxy_config()
# Access agent configuration (LLM settings)
agent_config = galaxy_config.agent.constellation_agent
# Access constellation runtime settings
constellation_settings = galaxy_config.constellation
# Or use raw dict access for backward compatibility
constellation_id = galaxy_config["CONSTELLATION_ID"]Galaxy vs UFO Configuration:
- UFO Configurations (
config/ufo/) - Single-agent automation settings - Galaxy Configurations (
config/galaxy/) - Multi-device constellation settings - Both systems can coexist in the same project
The configuration system uses a clear priority chain (highest to lowest):
- New modular configs -
config/{module}/*.yaml - Legacy monolithic config -
{module}/config/config.yaml - Environment variables - Runtime overrides
When the same setting exists in multiple locations, the new modular config takes precedence over legacy configs. Values are merged with later sources overriding earlier ones.
def load_config():
# Step 1: Start with environment variables (lowest priority)
config_data = dict(os.environ)
# Step 2: Load legacy config if exists (middle priority)
if exists("ufo/config/config.yaml"):
legacy_data = load_yaml("ufo/config/config.yaml")
merge(config_data, legacy_data)
# Step 3: Load new modular configs (highest priority)
for yaml_file in discover("config/ufo/*.yaml"):
new_data = load_yaml(yaml_file)
merge(config_data, new_data)
# Step 4: Create typed config object
return UFOConfig.from_dict(config_data)Configuration files are merged recursively, allowing you to split configurations across multiple files without duplication:
# config/ufo/agents.yaml
HOST_AGENT:
API_TYPE: "openai"
API_MODEL: "gpt-4o"
# config/ufo/custom.yaml (added later)
HOST_AGENT:
TEMPERATURE: 0.5 # Added to HOST_AGENT
# Result: HOST_AGENT has all three fieldsFields from later files are added to (not replacing) earlier configurations.
config/ufo/
├── agents.yaml # All agent LLM configs
├── system.yaml # All system settings
├── rag.yaml # All RAG settings
├── mcp.yaml # All MCP servers
└── prices.yaml # Model pricing
Advantages: Easy to find related settings, clear separation of concerns, good for documentation.
config/ufo/
├── host_agent.yaml # HOST_AGENT config
├── app_agent.yaml # APP_AGENT config
├── system.yaml # Shared system config
└── rag.yaml # Shared RAG config
Advantages: Agent-specific settings isolated, easy to customize per agent, good for multi-agent scenarios.
Both patterns work! The loader auto-discovers and merges all YAML files.
Support for development, testing, and production environments:
# Base configuration
config/ufo/agents.yaml # All environments
# Environment-specific overrides
config/ufo/agents_dev.yaml # Development only
config/ufo/agents_test.yaml # Testing only
config/ufo/agents_prod.yaml # Production onlyActivation:
# Set environment
export UFO_ENV=dev # Linux/Mac
$env:UFO_ENV = "dev" # Windows PowerShell
# Configuration loads:
# 1. agents.yaml (base)
# 2. agents_dev.yaml (overrides)Provides IDE autocomplete and type safety:
@dataclass
class SystemConfig:
max_step: int = 50
max_retry: int = 20
temperature: float = 0.0
# ...
# Usage - IDE knows the types!
config.system.max_step # int
config.system.temperature # floatFor custom or experimental settings. Learn more about adding custom fields in the Extending Configuration guide.
Example:
# In YAML
MY_CUSTOM_FEATURE: True
NEW_EXPERIMENTAL_SETTING: "value"
# In code - dynamic access
if config.MY_CUSTOM_FEATURE:
setting = config.NEW_EXPERIMENTAL_SETTINGBest of both worlds:
class SystemConfig:
# Fixed fields
max_step: int = 50
# Dynamic extras
_extras: Dict[str, Any]
def __getattr__(self, name):
# Try extras for unknown fields
return self._extras.get(name)The system provides clear warnings when using legacy paths:
⚠️ LEGACY CONFIG PATH DETECTED: UFO
Using legacy config: ufo/config/
Please migrate to: config/ufo/
Quick migration:
mkdir -p config/ufo
cp ufo/config/*.yaml config/ufo/
Or use migration tool:
python -m ufo.tools.migrate_config
These warnings appear once per session and guide you to migrate to the new structure.
Recommended Practices:
- Use modular files - Split by domain or agent
- Use typed access -
config.system.max_stepoverconfig["MAX_STEP"] - Add templates - Provide
.templatefiles for sensitive data - Document custom fields - Add comments in YAML
- Use environment overrides - For dev/test/prod differences
Anti-Patterns to Avoid:
- Mix old and new - Migrate fully to new structure
- Put secrets in YAML - Use environment variables instead
- Duplicate settings - Leverage deep merging
- Break backward compat - Keep
config["OLD_KEY"]working - Hardcode paths - Use config system
graph LR
A[Application Start] --> B[Load Environment Vars]
B --> C[Check for Legacy Config]
C --> D[Load New Modular Configs]
D --> E[Deep Merge All Sources]
E --> F[Apply Transformations]
F --> G[Create Typed Config Object]
G --> H[Cache for Reuse]
H --> I[Application Running]
- Agent Configuration - LLM and API settings for all agents
- System Configuration - Runtime and execution settings
- RAG Configuration - Knowledge retrieval and learning settings
- MCP Configuration - Model Context Protocol servers
- Pricing Configuration - LLM cost tracking
- Third-Party Configuration - External agent integration (LinuxAgent, HardwareAgent)
- Migration Guide - How to migrate from old to new config
- Extending Configuration - How to add new configuration options
- Galaxy Constellation Configuration - Runtime settings for constellation orchestrator
- Galaxy Devices Configuration - Device definitions and capabilities
- Galaxy Agent Configuration - LLM configuration for constellation agent
For detailed API documentation of configuration classes and methods, see:
config.config_loader.ConfigLoader- Configuration loading and cachingconfig.config_schemas.UFOConfig- UFO configuration schemaconfig.config_schemas.GalaxyConfig- Galaxy configuration schemaconfig.config_loader.get_ufo_config()- Get UFO configuration instanceconfig.config_loader.get_galaxy_config()- Get Galaxy configuration instance