@@ -163,6 +163,10 @@ pub struct RuntimeFeatureConfig {
163163 api_timeout : ApiTimeoutConfig ,
164164 rules_import : RulesImportConfig ,
165165 provider : RuntimeProviderConfig ,
166+ /// Model override used when spawning sub-agents via the Agent tool.
167+ /// Read from `subagentModel` (or `subagent_model`) in settings; falls
168+ /// back to the default model when unset.
169+ subagent_model : Option < String > ,
166170}
167171
168172/// Controls which external AI coding framework rules are imported into the system prompt.
@@ -801,6 +805,7 @@ fn build_runtime_config(
801805 api_timeout : parse_optional_api_timeout_config ( & merged_value) ?,
802806 rules_import : parse_optional_rules_import ( & merged_value) ?,
803807 provider : parse_optional_provider_config ( & merged_value) ?,
808+ subagent_model : parse_optional_subagent_model ( & merged_value) ,
804809 } ;
805810
806811 Ok ( RuntimeConfig {
@@ -880,6 +885,13 @@ impl RuntimeConfig {
880885 self . feature_config . model . as_deref ( )
881886 }
882887
888+ /// Model override used when spawning sub-agents via the Agent tool.
889+ /// Read from `subagentModel` in settings; `None` means "use default model".
890+ #[ must_use]
891+ pub fn subagent_model ( & self ) -> Option < & str > {
892+ self . feature_config . subagent_model . as_deref ( )
893+ }
894+
883895 #[ must_use]
884896 pub fn aliases ( & self ) -> & BTreeMap < String , String > {
885897 & self . feature_config . aliases
@@ -1717,6 +1729,21 @@ fn parse_optional_model(root: &JsonValue) -> Option<String> {
17171729 . map ( ToOwned :: to_owned)
17181730}
17191731
1732+ /// Reads `subagentModel` (or the snake_case `subagent_model` alias) from
1733+ /// merged settings. Returns `None` when absent or blank so the Agent tool
1734+ /// falls back to the default model.
1735+ fn parse_optional_subagent_model ( root : & JsonValue ) -> Option < String > {
1736+ root. as_object ( )
1737+ . and_then ( |object| {
1738+ object
1739+ . get ( "subagentModel" )
1740+ . or_else ( || object. get ( "subagent_model" ) )
1741+ } )
1742+ . and_then ( JsonValue :: as_str)
1743+ . filter ( |s| !s. trim ( ) . is_empty ( ) )
1744+ . map ( |s| s. trim ( ) . to_string ( ) )
1745+ }
1746+
17201747fn parse_optional_aliases ( root : & JsonValue ) -> Result < BTreeMap < String , String > , ConfigError > {
17211748 let Some ( object) = root. as_object ( ) else {
17221749 return Ok ( BTreeMap :: new ( ) ) ;
@@ -2581,6 +2608,49 @@ fn deep_merge_objects(
25812608 }
25822609}
25832610
2611+ /// Read the provider config saved by `/setup` and inject its credentials
2612+ /// into the environment so `ProviderClient::from_model()` can find them via
2613+ /// the env-var-based provider dispatch. Only sets vars that aren't already
2614+ /// present (preserves explicit env). Idempotent.
2615+ ///
2616+ /// Called by the main CLI at startup and by sub-agent threads in the tools
2617+ /// crate so that custom/ exotic providers work for spawned agents too.
2618+ pub fn inject_config_as_env_fallbacks ( ) {
2619+ let cwd = std:: env:: current_dir ( ) . unwrap_or_default ( ) ;
2620+ let Ok ( config) = ConfigLoader :: default_for ( & cwd) . load ( ) else {
2621+ return ;
2622+ } ;
2623+ let provider = config. provider ( ) ;
2624+
2625+ // Map provider kind to the expected env var names
2626+ let ( api_key_env, base_url_env) = match provider. kind ( ) . unwrap_or ( "anthropic" ) {
2627+ "anthropic" => ( "ANTHROPIC_API_KEY" , "ANTHROPIC_BASE_URL" ) ,
2628+ "xai" => ( "XAI_API_KEY" , "XAI_BASE_URL" ) ,
2629+ "openai" => ( "OPENAI_API_KEY" , "OPENAI_BASE_URL" ) ,
2630+ "dashscope" => ( "DASHSCOPE_API_KEY" , "DASHSCOPE_BASE_URL" ) ,
2631+ "custom-openai" => ( "CLAWCUSTOMOPENAI_API_KEY" , "CLAWCUSTOMOPENAI_BASE_URL" ) ,
2632+ _ => return , // unknown provider kind — don't inject
2633+ } ;
2634+
2635+ // Only set env vars that aren't already set (preserve user's explicit env)
2636+ if let Some ( api_key) = provider. api_key ( ) {
2637+ if std:: env:: var ( api_key_env) . is_err ( ) {
2638+ std:: env:: set_var ( api_key_env, api_key) ;
2639+ }
2640+ }
2641+ if let Some ( base_url) = provider. base_url ( ) {
2642+ if std:: env:: var ( base_url_env) . is_err ( ) {
2643+ std:: env:: set_var ( base_url_env, base_url) ;
2644+ }
2645+ }
2646+ // Also inject the saved model so resolve_model_alias sees it
2647+ if let Some ( model) = provider. model ( ) {
2648+ if std:: env:: var ( "CLAWD_PROVIDER_MODEL" ) . is_err ( ) {
2649+ std:: env:: set_var ( "CLAWD_PROVIDER_MODEL" , model) ;
2650+ }
2651+ }
2652+ }
2653+
25842654#[ cfg( test) ]
25852655mod tests {
25862656 use super :: {
0 commit comments