Skip to content

Unify ModelConfig and ExtendedModelConfig for AgentBuilder #7

@acoliver

Description

@acoliver

Summary

AgentBuilder::from_config() uses ModelConfig which lacks thinking/reasoning support, while build_model_extended() uses ExtendedModelConfig which has these features. These should be unified so AgentBuilder can easily configure thinking and reasoning.

Assign to: @acoliver

Current State

ModelConfig (serdes-ai-agent/src/builder.rs)

pub struct ModelConfig {
    pub spec: String,           // "openai:gpt-4o"
    pub api_key: Option<String>,
    pub base_url: Option<String>,
    pub timeout: Option<Duration>,
    // ❌ NO thinking support
    // ❌ NO reasoning_effort support
}

ExtendedModelConfig (serdes-ai-models/src/lib.rs)

pub struct ExtendedModelConfig {
    pub api_key: Option<String>,
    pub base_url: Option<String>,
    pub timeout: Option<Duration>,
    pub enable_thinking: bool,      // ✅ Has thinking
    pub thinking_budget: Option<u64>,
    pub reasoning_effort: Option<String>,  // ✅ Has reasoning
}

The Problem

To use thinking with AgentBuilder, you currently have to:

// Awkward workaround
let config = ExtendedModelConfig::new()
    .with_api_key("sk-...")
    .with_thinking(Some(10000));
let model = build_model_extended("anthropic", "claude-sonnet-4-20250514", config)?;
let agent = AgentBuilder::from_arc(model)
    .system_prompt("...")
    .build();

Instead of the cleaner:

// What we want
let agent = AgentBuilder::from_config(
    ModelConfig::new("anthropic:claude-sonnet-4-20250514")
        .with_api_key("sk-...")
        .with_thinking(Some(10000))  // Currently not possible!
)?
.system_prompt("...")
.build();

Proposed Fix

Add thinking/reasoning fields to ModelConfig and have build_model() delegate to build_model_extended():

// serdes-ai-agent/src/builder.rs
pub struct ModelConfig {
    pub spec: String,
    pub api_key: Option<String>,
    pub base_url: Option<String>,
    pub timeout: Option<Duration>,
    // ADD:
    pub enable_thinking: bool,
    pub thinking_budget: Option<u64>,
    pub reasoning_effort: Option<String>,
}

impl ModelConfig {
    pub fn with_thinking(mut self, budget: Option<u64>) -> Self {
        self.enable_thinking = true;
        self.thinking_budget = budget;
        self
    }
    
    pub fn with_reasoning_effort(mut self, effort: impl Into<String>) -> Self {
        self.reasoning_effort = Some(effort.into());
        self
    }
    
    pub fn build_model(&self) -> Result<Arc<dyn Model>, ModelError> {
        let (provider, model_name) = self.parse_spec();
        
        let extended = ExtendedModelConfig {
            api_key: self.api_key.clone(),
            base_url: self.base_url.clone(),
            timeout: self.timeout,
            enable_thinking: self.enable_thinking,
            thinking_budget: self.thinking_budget,
            reasoning_effort: self.reasoning_effort.clone(),
        };
        
        build_model_extended(provider, model_name, extended)
    }
}

Alternative: Deprecate ModelConfig

Could also just use ExtendedModelConfig everywhere and add a spec field to it, deprecating ModelConfig. This avoids duplication.

Checklist

  • Add enable_thinking, thinking_budget, reasoning_effort to ModelConfig
  • Add with_thinking() and with_reasoning_effort() builder methods
  • Update build_model() to use build_model_extended() internally
  • Add tests for thinking configuration through AgentBuilder
  • Update documentation/examples

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions