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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
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
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 ###################################
# Configuration for the sandbox
##############################################################################

View File

@ -10,6 +10,8 @@ from openhands.core.logger import openhands_logger as logger
class AgentConfig(BaseModel):
llm_config: str | None = Field(default=None)
"""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)
"""Whether to enable browsing tool"""
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.storage import get_file_store
from openhands.storage.files import FileStore
from openhands.utils.import_utils import get_impl
JWT_SECRET = '.jwt_secret'
load_dotenv()
@ -610,6 +611,30 @@ def parse_arguments() -> argparse.Namespace:
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(
set_logging_levels: bool = True, config_file: str = 'config.toml'
) -> AppConfig:
@ -623,6 +648,7 @@ def load_app_config(
load_from_toml(config, config_file)
load_from_env(config, os.environ)
finalize_config(config)
register_custom_agents(config)
if set_logging_levels:
logger.DEBUG = config.debug
logger.DISABLE_COLOR_PRINTING = config.disable_color