Make agents.<name>.models optional

Changes:
- agents.<name>.models is now optional (uses serde default)
- If models not specified, uses default model for all task types
- AgentModels.for_task() now takes TaskType enum and returns cloned String
- Falls back to default model if task-specific model not set
- Default agent config simplified to only set default model

Example minimal agent config:
[agents.default]
description = "Default agent"
system_prompt = "You are helpful."
tools = ["file", "shell", "git"]
# No models needed - uses provider default

Example with only default model:
[agents.default.models]
default = "ollama/llama3"
# All tasks use llama3

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
2026-03-19 14:44:49 +01:00
parent bd8350b52a
commit d874194d95
3 changed files with 31 additions and 23 deletions

View File

@@ -147,15 +147,8 @@ pub struct AgentRuntimeConfig {
impl AgentRuntimeConfig {
pub fn get_model_for_task(&self, task_type: TaskType) -> Option<String> {
let model_str = match task_type {
TaskType::Chat => self.config.models.chat.as_ref(),
TaskType::Code => self.config.models.code.as_ref(),
TaskType::Planning => self.config.models.planning.as_ref(),
TaskType::ToolUse => self.config.models.tool_use.as_ref(),
TaskType::Default => self.config.models.default.as_ref(),
};
model_str.cloned()
// Use the AgentModels helper which handles fallback to default
self.config.models.for_task(task_type)
}
}

View File

@@ -248,11 +248,9 @@ fn default_agent_config() -> AgentConfig {
AgentConfig {
description: "Default general-purpose agent".to_string(),
models: AgentModels {
chat: Some("ollama/llama3".to_string()),
code: Some("openai/gpt-4o".to_string()),
planning: Some("openai/gpt-4o".to_string()),
tool_use: Some("openai/gpt-4o".to_string()),
// Only set default model - will be used for all task types
default: Some("ollama/llama3".to_string()),
..Default::default()
},
system_prompt: "You are a helpful AI assistant. Help the user with their tasks.".to_string(),
tools: vec!["file".to_string(), "shell".to_string(), "git".to_string()],

View File

@@ -1,6 +1,8 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::providers::TaskType;
/// Main configuration structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
@@ -131,7 +133,8 @@ pub struct AgentConfig {
#[serde(default)]
pub description: String,
/// Model routing configuration
/// Model routing configuration (optional, uses default model for all tasks if not specified)
#[serde(default)]
pub models: AgentModels,
/// System prompt for this agent
@@ -152,6 +155,7 @@ pub struct AgentConfig {
}
/// Model routing for different task types
/// If no models are specified, the default model is used for all tasks
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AgentModels {
/// Model for general chat/conversation
@@ -170,21 +174,34 @@ pub struct AgentModels {
#[serde(default)]
pub tool_use: Option<String>,
/// Fallback model when task type is unclear
/// Fallback model for all tasks (used if task-specific models not set)
#[serde(default)]
pub default: Option<String>,
}
impl AgentModels {
/// Get the model for a specific task type
pub fn for_task(&self, task_type: &str) -> Option<&str> {
match task_type {
"chat" => self.chat.as_deref(),
"code" => self.code.as_deref(),
"planning" => self.planning.as_deref(),
"tool_use" => self.tool_use.as_deref(),
_ => self.default.as_deref(),
}
/// Falls back to default model if task-specific model not set
pub fn for_task(&self, task_type: TaskType) -> Option<String> {
let task_model = match task_type {
TaskType::Chat => self.chat.as_ref(),
TaskType::Code => self.code.as_ref(),
TaskType::Planning => self.planning.as_ref(),
TaskType::ToolUse => self.tool_use.as_ref(),
TaskType::Default => self.default.as_ref(),
};
// Return task-specific model if set, otherwise use default
task_model.or(self.default.as_ref()).cloned()
}
/// Check if any models are configured
pub fn is_empty(&self) -> bool {
self.chat.is_none() &&
self.code.is_none() &&
self.planning.is_none() &&
self.tool_use.is_none() &&
self.default.is_none()
}
}