Aster 提供了灵活的配置系统,支持 YAML 配置文件、环境变量展开、配置合并和验证。配置系统使得 Agent 的创建和管理更加简单和可维护。
配置系统的核心功能:
Agent 的完整配置结构:
type AgentConfig struct {
// 基础信息
AgentID string
TemplateID string // 必需
TemplateVersion string
// 模型配置
ModelConfig *ModelConfig
// 工具和中间件
Tools []string
Middlewares []string
// 沙箱配置
Sandbox *SandboxConfig
// 存储配置
Store *StoreConfig
// 多租户配置
Multitenancy *MultitenancyConfig
// 记忆系统配置
Memory *MemoryConfig
// 其他配置
Metadata map[string]any
}
模型提供商配置:
type ModelConfig struct {
Provider string // "anthropic", "openai", etc.
Model string // 模型名称
APIKey string // API 密钥
BaseURL string // 自定义 API 端点
ExecutionMode ExecutionMode // streaming/non-streaming/auto
}
创建 agent.yaml 文件:
# agent.yaml
template_id: "general-assistant"
template_version: "1.0.0"
model_config:
provider: "anthropic"
model: "claude-3-5-sonnet-20241022"
api_key: "${ANTHROPIC_API_KEY}"
execution_mode: "streaming"
tools:
- "read_file"
- "write_file"
- "bash"
middlewares:
- "logging"
- "rate_limit"
metadata:
environment: "production"
team: "platform"
import (
"github.com/astercloud/aster/pkg/config"
)
// 创建配置加载器
loader := config.NewLoader()
// 加载配置
agentConfig, err := loader.LoadAgentConfig("agent.yaml")
if err != nil {
return err
}
// 使用配置创建 Agent
agent, err := agent.NewAgent(agentConfig)
if err != nil {
return err
}
配置系统支持多种环境变量语法:
# 简单变量引用
api_key: "${API_KEY}"
# 或使用 $ 语法
api_key: "$API_KEY"
# 带默认值
api_key: "${API_KEY:-sk-default-key}"
# 必需变量(如果不存在会报错)
api_key: "${API_KEY:?API key is required}"
model_config:
provider: "anthropic"
model: "${MODEL_NAME:-claude-3-5-sonnet-20241022}"
api_key: "${ANTHROPIC_API_KEY:?ANTHROPIC_API_KEY must be set}"
base_url: "${API_BASE_URL:-https://api.anthropic.com}"
database:
host: "${DB_HOST:-localhost}"
port: "${DB_PORT:-5432}"
name: "${DB_NAME}"
user: "${DB_USER}"
password: "${DB_PASSWORD:?Database password is required}"
使用前缀来组织环境变量:
// 使用 APP_ 前缀
loader := config.NewLoader(
config.WithEnvPrefix("APP_"),
)
// 配置文件中使用不带前缀的名称
// api_key: "${API_KEY}"
// 实际会查找 APP_API_KEY 环境变量
除了环境变量,还可以提供自定义变量:
loader := config.NewLoader(
config.WithVariables(map[string]string{
"ENVIRONMENT": "production",
"REGION": "us-west-2",
"VERSION": "1.0.0",
}),
)
// 配置文件中使用
// metadata:
// environment: "${ENVIRONMENT}"
// region: "${REGION}"
支持多个配置文件的合并,用于不同环境或场景:
// 加载基础配置
baseConfig, err := loader.LoadAgentConfig("base.yaml")
if err != nil {
return err
}
// 加载环境特定配置
prodConfig, err := loader.LoadAgentConfig("production.yaml")
if err != nil {
return err
}
// 合并配置(后面的配置会覆盖前面的)
finalConfig := config.MergeConfigs(baseConfig, prodConfig)
base.yaml - 基础配置:
template_id: "general-assistant"
model_config:
provider: "anthropic"
model: "claude-3-5-sonnet-20241022"
tools:
- "read_file"
- "write_file"
metadata:
version: "1.0.0"
production.yaml - 生产环境配置:
model_config:
api_key: "${PROD_API_KEY}"
base_url: "https://api.production.example.com"
metadata:
environment: "production"
log_level: "info"
development.yaml - 开发环境配置:
model_config:
api_key: "${DEV_API_KEY}"
tools:
- "read_file"
- "write_file"
- "bash"
- "debug_tool"
metadata:
environment: "development"
log_level: "debug"
// 合并多个配置
finalConfig := config.MergeConfigs(
baseConfig,
envConfig,
userConfig,
overrideConfig,
)
配置加载时会自动验证:
// template_id 是必需的
agentConfig := &types.AgentConfig{
// 缺少 template_id
ModelConfig: &types.ModelConfig{
Provider: "anthropic",
Model: "claude-3-5-sonnet-20241022",
},
}
// 验证会失败
err := loader.validateAgentConfig(agentConfig)
// err: "template_id is required"
// Provider 和 Model 都是必需的
modelConfig := &types.ModelConfig{
Provider: "anthropic",
// 缺少 Model
}
// 验证会失败
// err: "model is required when model_config is provided"
// 启用多租户时必须提供 org_id 或 tenant_id
multitenancy := &types.MultitenancyConfig{
Enabled: true,
// 缺少 OrgID 和 TenantID
}
// 验证会失败
// err: "org_id or tenant_id is required when multitenancy is enabled"
loader := config.NewLoader(
// 启用/禁用环境变量展开
config.WithEnvExpansion(true),
// 设置环境变量前缀
config.WithEnvPrefix("ASTER_"),
// 提供自定义变量
config.WithVariables(map[string]string{
"APP_NAME": "my-agent",
"VERSION": "1.0.0",
}),
)
configYAML := `
template_id: "test-agent"
model_config:
provider: "anthropic"
model: "claude-3-5-sonnet-20241022"
`
var agentConfig types.AgentConfig
err := loader.LoadFromString(configYAML, &agentConfig)
# production.yaml
template_id: "production-assistant"
template_version: "2.0.0"
agent_id: "${AGENT_ID}"
model_config:
provider: "anthropic"
model: "claude-3-5-sonnet-20241022"
api_key: "${ANTHROPIC_API_KEY:?API key is required}"
base_url: "${API_BASE_URL:-https://api.anthropic.com}"
execution_mode: "streaming"
tools:
- "read_file"
- "write_file"
- "bash"
- "web_search"
middlewares:
- "logging"
- "rate_limit"
- "auth"
- "metrics"
middleware_config:
rate_limit:
requests_per_minute: 60
burst: 10
logging:
level: "info"
format: "json"
sandbox:
enabled: true
kind: "docker"
timeout_seconds: 300
store:
type: "postgres"
connection_string: "${DATABASE_URL:?Database URL is required}"
multitenancy:
enabled: true
org_id: "${ORG_ID}"
tenant_id: "${TENANT_ID}"
memory:
enabled: true
vector_store:
type: "weaviate"
url: "${WEAVIATE_URL:-http://localhost:8080}"
api_key: "${WEAVIATE_API_KEY}"
embedder:
provider: "openai"
model: "text-embedding-3-small"
api_key: "${OPENAI_API_KEY}"
metadata:
environment: "production"
region: "${AWS_REGION:-us-west-2}"
version: "${APP_VERSION}"
team: "platform"
# development.yaml
template_id: "dev-assistant"
agent_id: "dev-agent-001"
model_config:
provider: "anthropic"
model: "claude-3-5-sonnet-20241022"
api_key: "${ANTHROPIC_API_KEY}"
execution_mode: "streaming"
tools:
- "read_file"
- "write_file"
- "bash"
- "debug_tool"
middlewares:
- "logging"
middleware_config:
logging:
level: "debug"
format: "text"
sandbox:
enabled: false
store:
type: "sqlite"
path: "./dev.db"
memory:
enabled: true
vector_store:
type: "weaviate"
url: "http://localhost:8080"
embedder:
provider: "openai"
model: "text-embedding-3-small"
api_key: "${OPENAI_API_KEY}"
metadata:
environment: "development"
debug: true
# 好的做法:敏感信息使用环境变量
model_config:
api_key: "${ANTHROPIC_API_KEY}"
database:
password: "${DB_PASSWORD}"
# 避免:硬编码敏感信息
# api_key: "sk-ant-api03-..."
# 为可选配置提供默认值
model_config:
model: "${MODEL_NAME:-claude-3-5-sonnet-20241022}"
base_url: "${API_BASE_URL:-https://api.anthropic.com}"
database:
host: "${DB_HOST:-localhost}"
port: "${DB_PORT:-5432}"
config/
├── base.yaml # 基础配置
├── development.yaml # 开发环境
├── staging.yaml # 预发布环境
└── production.yaml # 生产环境
// 根据环境加载配置
env := os.Getenv("ENVIRONMENT")
baseConfig, _ := loader.LoadAgentConfig("config/base.yaml")
envConfig, _ := loader.LoadAgentConfig(fmt.Sprintf("config/%s.yaml", env))
finalConfig := config.MergeConfigs(baseConfig, envConfig)
# 使用 :? 语法确保必需变量存在
model_config:
api_key: "${ANTHROPIC_API_KEY:?ANTHROPIC_API_KEY environment variable is required}"
database:
url: "${DATABASE_URL:?DATABASE_URL must be set}"
# 好的做法:清晰的键名
model_config:
provider: "anthropic"
model: "claude-3-5-sonnet-20241022"
api_key: "${ANTHROPIC_API_KEY}"
# 避免:模糊的键名
# config:
# p: "anthropic"
# m: "claude-3-5-sonnet-20241022"
# agent.yaml
# Agent 模板标识符(必需)
template_id: "general-assistant"
# 模板版本(可选)
template_version: "1.0.0"
# 模型配置
model_config:
# 提供商:anthropic, openai, gemini
provider: "anthropic"
# 模型名称
model: "claude-3-5-sonnet-20241022"
# API 密钥(从环境变量读取)
api_key: "${ANTHROPIC_API_KEY}"
// 加载后立即验证
agentConfig, err := loader.LoadAgentConfig("agent.yaml")
if err != nil {
log.Fatalf("配置加载失败: %v", err)
}
// 配置已自动验证,可以安全使用
agent, err := agent.NewAgent(agentConfig)
// 项目配置文件
projectConfig := config.ProjectConfigFile()
// 返回: ./.aster/config.yaml
// 用户配置目录
configDir := config.ConfigDir()
// 返回: ~/.config/aster/
// 数据目录
dataDir := config.DataDir()
// 返回: ~/.local/share/aster/
// 自动查找配置文件
configPath := config.ResolveConfigFile("agent.yaml")
// 查找顺序:
// 1. ./agent.yaml
// 2. ./.aster/agent.yaml
// 3. ~/.config/aster/agent.yaml
除了 YAML 文件,也可以通过代码创建配置:
agentConfig := &types.AgentConfig{
TemplateID: "code-assistant",
TemplateVersion: "1.0.0",
ModelConfig: &types.ModelConfig{
Provider: "anthropic",
Model: "claude-3-5-sonnet-20241022",
APIKey: os.Getenv("ANTHROPIC_API_KEY"),
},
Tools: []string{
"read_file",
"write_file",
"bash",
},
Metadata: map[string]any{
"environment": "production",
"version": "1.0.0",
},
}
agent, err := agent.NewAgent(agentConfig)
实现配置热重载:
import (
"github.com/fsnotify/fsnotify"
)
func watchConfig(configPath string, onReload func(*types.AgentConfig)) error {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
defer watcher.Close()
err = watcher.Add(configPath)
if err != nil {
return err
}
loader := config.NewLoader()
for {
select {
case event := <-watcher.Events:
if event.Op&fsnotify.Write == fsnotify.Write {
// 重新加载配置
newConfig, err := loader.LoadAgentConfig(configPath)
if err != nil {
log.Printf("重载配置失败: %v", err)
continue
}
onReload(newConfig)
}
case err := <-watcher.Errors:
log.Printf("配置监听错误: %v", err)
}
}
}
agentConfig, err := loader.LoadAgentConfig("agent.yaml")
if err != nil {
// 检查文件是否存在
if os.IsNotExist(err) {
log.Fatal("配置文件不存在")
}
// 检查 YAML 语法错误
if strings.Contains(err.Error(), "yaml") {
log.Fatal("YAML 语法错误:", err)
}
// 检查验证错误
if strings.Contains(err.Error(), "validate") {
log.Fatal("配置验证失败:", err)
}
}
# 使用 :? 语法会在变量未设置时报错
api_key: "${API_KEY:?API_KEY environment variable must be set}"
# 或提供默认值
api_key: "${API_KEY:-default-key}"
base := loadConfig("base.yaml")
env := loadConfig("production.yaml")
// 打印合并前的配置
log.Printf("Base config: %+v", base)
log.Printf("Env config: %+v", env)
// 合并
final := config.MergeConfigs(base, env)
// 打印合并后的配置
log.Printf("Final config: %+v", final)