Feature: Add custom agents via config (#8245)

This commit is contained in:
Chase
2025-05-08 09:15:15 -07:00
committed by GitHub
parent b06bd277ba
commit c6c94d979b
3 changed files with 33 additions and 0 deletions

View File

@@ -255,6 +255,11 @@ enable_history_truncation = true
# useful when an agent doesn't demand high quality but uses a lot of tokens # useful when an agent doesn't demand high quality but uses a lot of tokens
llm_config = 'gpt3' llm_config = 'gpt3'
[agent.CustomAgent]
# Example: use a custom agent from a different package
# This will be automatically be registered as a new agent named "CustomAgent"
classpath = "my_package.my_module.MyCustomAgent"
#################################### Sandbox ################################### #################################### Sandbox ###################################
# Configuration for the sandbox # Configuration for the sandbox
############################################################################## ##############################################################################

View File

@@ -10,6 +10,8 @@ from openhands.core.logger import openhands_logger as logger
class AgentConfig(BaseModel): class AgentConfig(BaseModel):
llm_config: str | None = Field(default=None) llm_config: str | None = Field(default=None)
"""The name of the llm config to use. If specified, this will override global llm config.""" """The name of the llm config to use. If specified, this will override global llm config."""
classpath: str | None = Field(default=None)
"""The classpath of the agent to use. To be used for custom agents that are not defined in the openhands.agenthub package."""
enable_browsing: bool = Field(default=True) enable_browsing: bool = Field(default=True)
"""Whether to enable browsing tool""" """Whether to enable browsing tool"""
enable_llm_editor: bool = Field(default=False) enable_llm_editor: bool = Field(default=False)

View File

@@ -28,6 +28,7 @@ from openhands.core.config.sandbox_config import SandboxConfig
from openhands.core.config.security_config import SecurityConfig from openhands.core.config.security_config import SecurityConfig
from openhands.storage import get_file_store from openhands.storage import get_file_store
from openhands.storage.files import FileStore from openhands.storage.files import FileStore
from openhands.utils.import_utils import get_impl
JWT_SECRET = '.jwt_secret' JWT_SECRET = '.jwt_secret'
load_dotenv() load_dotenv()
@@ -610,6 +611,30 @@ def parse_arguments() -> argparse.Namespace:
return args return args
def register_custom_agents(config: AppConfig) -> None:
"""Register custom agents from configuration.
This function is called after configuration is loaded to ensure all custom agents
specified in the config are properly imported and registered.
"""
# Import here to avoid circular dependency
from openhands.controller.agent import Agent
for agent_name, agent_config in config.agents.items():
if agent_config.classpath:
try:
agent_cls = get_impl(Agent, agent_config.classpath)
Agent.register(agent_name, agent_cls)
logger.openhands_logger.info(
f"Registered custom agent '{agent_name}' from {agent_config.classpath}"
)
except Exception as e:
logger.openhands_logger.error(
f"Failed to register agent '{agent_name}': {e}"
)
def load_app_config( def load_app_config(
set_logging_levels: bool = True, config_file: str = 'config.toml' set_logging_levels: bool = True, config_file: str = 'config.toml'
) -> AppConfig: ) -> AppConfig:
@@ -623,6 +648,7 @@ def load_app_config(
load_from_toml(config, config_file) load_from_toml(config, config_file)
load_from_env(config, os.environ) load_from_env(config, os.environ)
finalize_config(config) finalize_config(config)
register_custom_agents(config)
if set_logging_levels: if set_logging_levels:
logger.DEBUG = config.debug logger.DEBUG = config.debug
logger.DISABLE_COLOR_PRINTING = config.disable_color logger.DISABLE_COLOR_PRINTING = config.disable_color