1414
1515from __future__ import annotations
1616
17+ import importlib
1718import os
18- from pathlib import Path
19+ from typing import Any
1920
2021import yaml
2122
2223from ..utils .feature_decorator import working_in_progress
2324from .agent_config import AgentConfig
2425from .base_agent import BaseAgent
26+ from .base_agent import SubAgentConfig
2527from .llm_agent import LlmAgent
2628from .llm_agent import LlmAgentConfig
2729from .loop_agent import LoopAgent
@@ -51,13 +53,13 @@ def from_config(config_path: str) -> BaseAgent:
5153 config = _load_config_from_path (abs_path )
5254
5355 if isinstance (config .root , LlmAgentConfig ):
54- return LlmAgent .from_config (config .root )
56+ return LlmAgent .from_config (config .root , abs_path )
5557 elif isinstance (config .root , LoopAgentConfig ):
56- return LoopAgent .from_config (config .root )
58+ return LoopAgent .from_config (config .root , abs_path )
5759 elif isinstance (config .root , ParallelAgentConfig ):
58- return ParallelAgent .from_config (config .root )
60+ return ParallelAgent .from_config (config .root , abs_path )
5961 elif isinstance (config .root , SequentialAgentConfig ):
60- return SequentialAgent .from_config (config .root )
62+ return SequentialAgent .from_config (config .root , abs_path )
6163 else :
6264 raise ValueError ("Unsupported config type" )
6365
@@ -77,12 +79,62 @@ def _load_config_from_path(config_path: str) -> AgentConfig:
7779 FileNotFoundError: If config file doesn't exist.
7880 ValidationError: If config file's content is invalid YAML.
7981 """
80- config_path = Path (config_path )
81-
82- if not config_path .exists ():
82+ if not os .path .exists (config_path ):
8383 raise FileNotFoundError (f"Config file not found: { config_path } " )
8484
8585 with open (config_path , "r" , encoding = "utf-8" ) as f :
8686 config_data = yaml .safe_load (f )
8787
8888 return AgentConfig .model_validate (config_data )
89+
90+
91+ @working_in_progress ("build_sub_agent is not ready for use." )
92+ def build_sub_agent (
93+ sub_config : SubAgentConfig , parent_agent_folder_path : str
94+ ) -> BaseAgent :
95+ """Build a sub-agent from configuration.
96+
97+ Args:
98+ sub_config: The sub-agent configuration (SubAgentConfig).
99+ parent_agent_folder_path: The folder path to the parent agent's YAML config.
100+
101+ Returns:
102+ The created sub-agent instance.
103+ """
104+ if sub_config .config :
105+ if os .path .isabs (sub_config .config ):
106+ return from_config (sub_config .config )
107+ else :
108+ return from_config (
109+ os .path .join (parent_agent_folder_path , sub_config .config )
110+ )
111+ elif sub_config .code :
112+ return _resolve_sub_agent_code_reference (sub_config .code )
113+ else :
114+ raise ValueError ("SubAgentConfig must have either 'code' or 'config'" )
115+
116+
117+ @working_in_progress ("_resolve_sub_agent_code_reference is not ready for use." )
118+ def _resolve_sub_agent_code_reference (code : str ) -> Any :
119+ """Resolve a code reference to an actual agent object.
120+
121+ Args:
122+ code: The code reference to the sub-agent.
123+
124+ Returns:
125+ The resolved agent object.
126+
127+ Raises:
128+ ValueError: If the code reference cannot be resolved.
129+ """
130+ if "." not in code :
131+ raise ValueError (f"Invalid code reference: { code } " )
132+
133+ module_path , obj_name = code .rsplit ("." , 1 )
134+ module = importlib .import_module (module_path )
135+ obj = getattr (module , obj_name )
136+
137+ if callable (obj ):
138+ raise ValueError (f"Invalid code reference to a callable: { code } " )
139+
140+ return obj
0 commit comments