agent.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. from abc import ABC, abstractmethod
  2. from typing import TYPE_CHECKING, Type
  3. if TYPE_CHECKING:
  4. from openhands.controller.state.state import State
  5. from openhands.core.config import AgentConfig
  6. from openhands.events.action import Action
  7. from openhands.core.exceptions import (
  8. AgentAlreadyRegisteredError,
  9. AgentNotRegisteredError,
  10. )
  11. from openhands.llm.llm import LLM
  12. from openhands.runtime.plugins import PluginRequirement
  13. from openhands.utils.prompt import PromptManager
  14. class Agent(ABC):
  15. DEPRECATED = False
  16. """
  17. This abstract base class is an general interface for an agent dedicated to
  18. executing a specific instruction and allowing human interaction with the
  19. agent during execution.
  20. It tracks the execution status and maintains a history of interactions.
  21. """
  22. _registry: dict[str, Type['Agent']] = {}
  23. sandbox_plugins: list[PluginRequirement] = []
  24. def __init__(
  25. self,
  26. llm: LLM,
  27. config: 'AgentConfig',
  28. ):
  29. self.llm = llm
  30. self.config = config
  31. self._complete = False
  32. self.prompt_manager: PromptManager | None = None
  33. @property
  34. def complete(self) -> bool:
  35. """Indicates whether the current instruction execution is complete.
  36. Returns:
  37. - complete (bool): True if execution is complete; False otherwise.
  38. """
  39. return self._complete
  40. @abstractmethod
  41. def step(self, state: 'State') -> 'Action':
  42. """Starts the execution of the assigned instruction. This method should
  43. be implemented by subclasses to define the specific execution logic.
  44. """
  45. pass
  46. def reset(self) -> None:
  47. """Resets the agent's execution status and clears the history. This method can be used
  48. to prepare the agent for restarting the instruction or cleaning up before destruction.
  49. """
  50. # TODO clear history
  51. self._complete = False
  52. if self.llm:
  53. self.llm.reset()
  54. @property
  55. def name(self):
  56. return self.__class__.__name__
  57. @classmethod
  58. def register(cls, name: str, agent_cls: Type['Agent']):
  59. """Registers an agent class in the registry.
  60. Parameters:
  61. - name (str): The name to register the class under.
  62. - agent_cls (Type['Agent']): The class to register.
  63. Raises:
  64. - AgentAlreadyRegisteredError: If name already registered
  65. """
  66. if name in cls._registry:
  67. raise AgentAlreadyRegisteredError(name)
  68. cls._registry[name] = agent_cls
  69. @classmethod
  70. def get_cls(cls, name: str) -> Type['Agent']:
  71. """Retrieves an agent class from the registry.
  72. Parameters:
  73. - name (str): The name of the class to retrieve
  74. Returns:
  75. - agent_cls (Type['Agent']): The class registered under the specified name.
  76. Raises:
  77. - AgentNotRegisteredError: If name not registered
  78. """
  79. if name not in cls._registry:
  80. raise AgentNotRegisteredError(name)
  81. return cls._registry[name]
  82. @classmethod
  83. def list_agents(cls) -> list[str]:
  84. """Retrieves the list of all agent names from the registry.
  85. Raises:
  86. - AgentNotRegisteredError: If no agent is registered
  87. """
  88. if not bool(cls._registry):
  89. raise AgentNotRegisteredError()
  90. return list(cls._registry.keys())