class BaseConversation
Bases:ABC
Abstract base class for conversation implementations.
This class defines the interface that all conversation implementations must follow.
Conversations manage the interaction between users and agents, handling message
exchange, execution control, and state management.
Properties
confirmation_policy_active: boolconversation_stats: ConversationStatsid: UUIDis_confirmation_mode_active: bool Check if confirmation mode is active. Returns True if BOTH conditions are met:- The conversation state has a security analyzer set (not None)
- The confirmation policy is active
state: ConversationStateProtocol
Methods
init()
Initialize the base conversation with span tracking.abstractmethod ask_agent()
Ask the agent a simple, stateless question and get a direct LLM response. This bypasses the normal conversation flow and does not modify, persist, or become part of the conversation state. The request is not remembered by the main agent, no events are recorded, and execution status is untouched. It is also thread-safe and may be called while conversation.run() is executing in another thread.- Parameters:
question– A simple string question to ask the agent - Returns: A string response from the agent
abstractmethod close()
static compose_callbacks()
Compose multiple callbacks into a single callback function.- Parameters:
callbacks– An iterable of callback functions - Returns: A single callback function that calls all provided callbacks
abstractmethod generate_title()
Generate a title for the conversation based on the first user message.- Parameters:
llm– Optional LLM to use for title generation. If not provided, uses the agent’s LLM.max_length– Maximum length of the generated title.
- Returns: A generated title for the conversation.
- Raises:
ValueError– If no user messages are found in the conversation.
static get_persistence_dir()
Get the persistence directory for the conversation.- Parameters:
persistence_base_dir– Base directory for persistence. Can be a string path or Path object.conversation_id– Unique conversation ID.
- Returns: String path to the conversation-specific persistence directory. Always returns a normalized string path even if a Path was provided.
abstractmethod pause()
abstractmethod reject_pending_actions()
abstractmethod run()
Execute the agent to process messages and perform actions. This method runs the agent until it finishes processing the current message or reaches the maximum iteration limit.abstractmethod send_message()
Send a message to the agent.- Parameters:
message– Either a string (which will be converted to a user message) or a Message objectsender– Optional identifier of the sender. Can be used to track message origin in multi-agent scenarios. For example, when one agent delegates to another, the sender can be set to identify which agent is sending the message.
abstractmethod set_confirmation_policy()
Set the confirmation policy for the conversation.abstractmethod update_secrets()
class Conversation
class Conversation
Bases:object
Factory class for creating conversation instances with OpenHands agents.
This factory automatically creates either a LocalConversation or RemoteConversation
based on the workspace type provided. LocalConversation runs the agent locally,
while RemoteConversation connects to a remote agent server.
- Returns: LocalConversation if workspace is local, RemoteConversation if workspace is remote.
Example
class ConversationExecutionStatus
Bases:str, Enum
Enum representing the current execution state of the conversation.
Methods
ERROR = ‘error’
FINISHED = ‘finished’
IDLE = ‘idle’
PAUSED = ‘paused’
RUNNING = ‘running’
STUCK = ‘stuck’
WAITING_FOR_CONFIRMATION = ‘waiting_for_confirmation’
class ConversationState
Bases:OpenHandsModel
Properties
activated_knowledge_skills: list[str]agent: AgentBaseconfirmation_policy: ConfirmationPolicyBaseenv_observation_persistence_dir: str | None Directory for persisting environment observation files.events: EventLogexecution_status: ConversationExecutionStatusid: UUIDmax_iterations: intmodel_config: ClassVar[ConfigDict] = (configuration object) Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].persistence_dir: str | Nonesecret_registry: SecretRegistrysecurity_analyzer: SecurityAnalyzerBase | Nonestats: ConversationStatsstuck_detection: boolworkspace: BaseWorkspace
Methods
acquire()
Acquire the lock.- Parameters:
blocking– If True, block until lock is acquired. If False, return immediately.timeout– Maximum time to wait for lock (ignored if blocking=False). -1 means wait indefinitely.
- Returns: True if lock was acquired, False otherwise.
classmethod create()
If base_state.json exists: resume (attach EventLog, : reconcile agent, enforce id). Else: create fresh (agent required), persist base, and return.static get_unmatched_actions()
Find actions in the event history that don’t have matching observations. This method identifies ActionEvents that don’t have corresponding ObservationEvents or UserRejectObservations, which typically indicates actions that are pending confirmation or execution.- Parameters:
events– List of events to search through - Returns: List of ActionEvent objects that don’t have corresponding observations, in chronological order
locked()
Return True if the lock is currently held by any thread.model_post_init()
Override this method to perform additional initialization after init and model_construct. This is useful if you want to do some validation that requires the entire model to be initialized.owned()
Return True if the lock is currently held by the calling thread.release()
Release the lock.- Raises:
RuntimeError– If the current thread doesn’t own the lock.
set_on_state_change()
Set a callback to be called when state changes.- Parameters:
callback– A function that takes an Event (ConversationStateUpdateEvent) or None to remove the callback
class ConversationVisualizerBase
Bases:ABC
Base class for conversation visualizers.
This abstract base class defines the interface that all conversation visualizers
must implement. Visualizers can be created before the Conversation is initialized
and will be configured with the conversation state automatically.
The typical usage pattern:
- Create a visualizer instance:
- Pass it to Conversation: conv = Conversation(agent, visualizer=viz)
- Conversation automatically calls viz.initialize(state) to attach the state
Properties
conversation_stats: ConversationStats | None Get conversation stats from the state.
Methods
init()
Initialize the visualizer base.initialize()
Initialize the visualizer with conversation state. This method is called by Conversation after the state is created, allowing the visualizer to access conversation stats and other state information. Subclasses should not override this method, to ensure the state is set.- Parameters:
state– The conversation state object
abstractmethod on_event()
Handle a conversation event. This method is called for each event in the conversation and should implement the visualization logic.- Parameters:
event– The event to visualize
class DefaultConversationVisualizer
Bases:ConversationVisualizerBase
Handles visualization of conversation events with Rich formatting.
Provides Rich-formatted output with semantic dividers and complete content display.
Methods
init()
Initialize the visualizer.- Parameters:
highlight_regex– Dictionary mapping regex patterns to Rich color styles for highlighting keywords in the visualizer. For example: (configuration object)skip_user_messages– If True, skip displaying user messages. Useful for scenarios where user input is not relevant to show.
on_event()
Main event handler that displays events with Rich formatting.class EventLog
Bases:EventsListBase
Methods
init()
append()
Add a new event to the list.get_id()
Return the event_id for a given index.get_index()
Return the integer index for a given event_id.class EventsListBase
Bases:Sequence[Event], ABC
Abstract base class for event lists that can be appended to.
This provides a common interface for both local EventLog and remote
RemoteEventsList implementations, avoiding circular imports in protocols.
Methods
abstractmethod append()
Add a new event to the list.class LocalConversation
Bases:BaseConversation
Properties
agent: AgentBaseid: UUID Get the unique ID of the conversation.llm_registry: LLMRegistrymax_iteration_per_run: intstate: ConversationState Get the conversation state. It returns a protocol that has a subset of ConversationState methods and properties. We will have the ability to access the same properties of ConversationState on a remote conversation object. But we won’t be able to access methods that mutate the state.stuck_detector: StuckDetector | None Get the stuck detector instance if enabled.workspace: LocalWorkspace
Methods
init()
Initialize the conversation.- Parameters:
-
agent– The agent to use for the conversation -
workspace– Working directory for agent operations and tool execution. Can be a string path, Path object, or LocalWorkspace instance. -
persistence_dir– Directory for persisting conversation state and events. Can be a string path or Path object. -
conversation_id– Optional ID for the conversation. If provided, will be used to identify the conversation. The user might want to suffix their persistent filestore with this ID. -
callbacks– Optional list of callback functions to handle events -
token_callbacks– Optional list of callbacks invoked for streaming deltas -
max_iteration_per_run– Maximum number of iterations per run -
visualizer– Visualization configuration. Can be:- ConversationVisualizerBase subclass: Class to instantiate
(default: ConversationVisualizer)
- ConversationVisualizerBase instance: Use custom visualizer
- None: No visualization
-
stuck_detection– Whether to enable stuck detection
-
ask_agent()
Ask the agent a simple, stateless question and get a direct LLM response. This bypasses the normal conversation flow and does not modify, persist, or become part of the conversation state. The request is not remembered by the main agent, no events are recorded, and execution status is untouched. It is also thread-safe and may be called while conversation.run() is executing in another thread.- Parameters:
question– A simple string question to ask the agent - Returns: A string response from the agent
close()
Close the conversation and clean up all tool executors.property conversation_stats
generate_title()
Generate a title for the conversation based on the first user message.- Parameters:
llm– Optional LLM to use for title generation. If not provided, uses self.agent.llm.max_length– Maximum length of the generated title.
- Returns: A generated title for the conversation.
- Raises:
ValueError– If no user messages are found in the conversation.
pause()
Pause agent execution. This method can be called from any thread to request that the agent pause execution. The pause will take effect at the next iteration of the run loop (between agent steps). Note: If called during an LLM completion, the pause will not take effect until the current LLM call completes.reject_pending_actions()
Reject all pending actions from the agent. This is a non-invasive method to reject actions between run() calls. Also clears the agent_waiting_for_confirmation flag.run()
Runs the conversation until the agent finishes. In confirmation mode:- First call: creates actions but doesn’t execute them, stops and waits
- Second call: executes pending actions (implicit confirmation)
- Creates and executes actions immediately
send_message()
Send a message to the agent.- Parameters:
message– Either a string (which will be converted to a user message) or a Message objectsender– Optional identifier of the sender. Can be used to track message origin in multi-agent scenarios. For example, when one agent delegates to another, the sender can be set to identify which agent is sending the message.
set_confirmation_policy()
Set the confirmation policy and store it in conversation state.set_security_analyzer()
Set the security analyzer for the conversation.update_secrets()
Add secrets to the conversation.- Parameters:
secrets– Dictionary mapping secret keys to values or no-arg callables. SecretValue = str | Callable[[], str]. Callables are invoked lazily when a command references the secret key.
class RemoteConversation
Bases:BaseConversation
Properties
agent: AgentBaseid: UUIDmax_iteration_per_run: intstate: RemoteState Access to remote conversation state.workspace: RemoteWorkspace
Methods
init()
Remote conversation proxy that talks to an agent server.- Parameters:
-
agent– Agent configuration (will be sent to the server) -
workspace– The working directory for agent operations and tool execution. -
conversation_id– Optional existing conversation id to attach to -
callbacks– Optional callbacks to receive events (not yet streamed) -
max_iteration_per_run– Max iterations configured on server -
stuck_detection– Whether to enable stuck detection on server -
visualizer– Visualization configuration. Can be:- ConversationVisualizerBase subclass: Class to instantiate
(default: ConversationVisualizer)
- ConversationVisualizerBase instance: Use custom visualizer
- None: No visualization
-
secrets– Optional secrets to initialize the conversation with
-
ask_agent()
Ask the agent a simple, stateless question and get a direct LLM response. This bypasses the normal conversation flow and does not modify, persist, or become part of the conversation state. The request is not remembered by the main agent, no events are recorded, and execution status is untouched. It is also thread-safe and may be called while conversation.run() is executing in another thread.- Parameters:
question– A simple string question to ask the agent - Returns: A string response from the agent
close()
Close the conversation and clean up resources. Note: We don’t close self._client here because it’s shared with the workspace. The workspace owns the client and will close it during its own cleanup. Closing it here would prevent the workspace from making cleanup API calls.property conversation_stats
generate_title()
Generate a title for the conversation based on the first user message.- Parameters:
llm– Optional LLM to use for title generation. If provided, its usage_id will be sent to the server. If not provided, uses the agent’s LLM.max_length– Maximum length of the generated title.
- Returns: A generated title for the conversation.
pause()
reject_pending_actions()
run()
Execute the agent to process messages and perform actions. This method runs the agent until it finishes processing the current message or reaches the maximum iteration limit.send_message()
Send a message to the agent.- Parameters:
message– Either a string (which will be converted to a user message) or a Message objectsender– Optional identifier of the sender. Can be used to track message origin in multi-agent scenarios. For example, when one agent delegates to another, the sender can be set to identify which agent is sending the message.
set_confirmation_policy()
Set the confirmation policy for the conversation.set_security_analyzer()
Set the security analyzer for the remote conversation.property stuck_detector
Stuck detector for compatibility. Not implemented for remote conversations.update_secrets()
class SecretRegistry
Bases:OpenHandsModel
Manages secrets and injects them into bash commands when needed.
The secret registry stores a mapping of secret keys to SecretSources
that retrieve the actual secret values. When a bash command is about to be
executed, it scans the command for any secret keys and injects the corresponding
environment variables.
Secret sources will redact / encrypt their sensitive values as appropriate when
serializing, depending on the content of the context. If a context is present
and contains a ‘cipher’ object, this is used for encryption. If it contains a
boolean ‘expose_secrets’ flag set to True, secrets are dunped in plain text.
Otherwise secrets are redacted.
Additionally, it tracks the latest exported values to enable consistent masking
even when callable secrets fail on subsequent calls.
Properties
model_config: ClassVar[ConfigDict] = (configuration object) Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].secret_sources: dict[str, SecretSource]
Methods
find_secrets_in_text()
Find all secret keys mentioned in the given text.- Parameters:
text– The text to search for secret keys - Returns: Set of secret keys found in the text
get_secrets_as_env_vars()
Get secrets that should be exported as environment variables for a command.- Parameters:
command– The bash command to check for secret references - Returns: Dictionary of environment variables to export (key -> value)
mask_secrets_in_output()
Mask secret values in the given text. This method uses both the current exported values and attempts to get fresh values from callables to ensure comprehensive masking.- Parameters:
text– The text to mask secrets in - Returns:
Text with secret values replaced by
<secret-hidden>
model_post_init()
Override this method to perform additional initialization after init and model_construct. This is useful if you want to do some validation that requires the entire model to be initialized.update_secrets()
Add or update secrets in the manager.- Parameters:
secrets– Dictionary mapping secret keys to either string values or callable functions that return string values
class StuckDetector
Bases:object
Detects when an agent is stuck in repetitive or unproductive patterns.
This detector analyzes the conversation history to identify various stuck patterns:
- Repeating action-observation cycles
- Repeating action-error cycles
- Agent monologue (repeated messages without user input)
- Repeating alternating action-observation patterns
- Context window errors indicating memory issues
Properties
state: ConversationState

