Skip to main content

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: bool
  • conversation_stats: ConversationStats
  • id: UUID
  • is_confirmation_mode_active: bool Check if confirmation mode is active. Returns True if BOTH conditions are met:
    1. The conversation state has a security analyzer set (not None)
    2. 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 object
    • sender – 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

>>> from openhands.sdk import LLM, Agent, Conversation
>>> llm = LLM(model="claude-sonnet-4-20250514", api_key=SecretStr("key"))
>>> agent = Agent(llm=llm, tools=[])
>>> conversation = Conversation(agent=agent, workspace="./workspace")
>>> conversation.send_message("Hello!")
>>> conversation.run()

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: AgentBase
  • confirmation_policy: ConfirmationPolicyBase
  • env_observation_persistence_dir: str | None Directory for persisting environment observation files.
  • events: EventLog
  • execution_status: ConversationExecutionStatus
  • id: UUID
  • max_iterations: int
  • model_config: ClassVar[ConfigDict] = (configuration object) Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
  • persistence_dir: str | None
  • secret_registry: SecretRegistry
  • security_analyzer: SecurityAnalyzerBase | None
  • stats: ConversationStats
  • stuck_detection: bool
  • workspace: 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:
  1. Create a visualizer instance:
viz = MyVisualizer()
  1. Pass it to Conversation: conv = Conversation(agent, visualizer=viz)
  2. Conversation automatically calls viz.initialize(state) to attach the state
You can also pass the uninstantiated class if you don’t need extra args : for initialization, and Conversation will create it: : conv = Conversation(agent, visualizer=MyVisualizer) Conversation will then calls MyVisualizer() followed by initialize(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: AgentBase
  • id: UUID Get the unique ID of the conversation.
  • llm_registry: LLMRegistry
  • max_iteration_per_run: int
  • state: 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)
In normal mode:
  • Creates and executes actions immediately
Can be paused between steps

send_message()

Send a message to the agent.
  • Parameters:
    • message – Either a string (which will be converted to a user message) or a Message object
    • sender – 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: AgentBase
  • id: UUID
  • max_iteration_per_run: int
  • state: 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 object
    • sender – 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:
  1. Repeating action-observation cycles
  2. Repeating action-error cycles
  3. Agent monologue (repeated messages without user input)
  4. Repeating alternating action-observation patterns
  5. Context window errors indicating memory issues

Properties

Methods

init()

is_stuck()

Check if the agent is currently stuck.