> ## Documentation Index
> Fetch the complete documentation index at: https://docs.openhands.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# openhands.sdk.agent

> API reference for openhands.sdk.agent module

### class Agent

Bases: `CriticMixin`, [`AgentBase`](#class-agentbase)

Main agent implementation for OpenHands.

The Agent class provides the core functionality for running AI agents that can
interact with tools, process messages, and execute actions. It inherits from
AgentBase and implements the agent execution logic. Critic-related functionality
is provided by CriticMixin.

#### Example

```pycon theme={null}
>>> from openhands.sdk import LLM, Agent, Tool
>>> llm = LLM(model="claude-sonnet-4-20250514", api_key=SecretStr("key"))
>>> tools = [Tool(name="TerminalTool"), Tool(name="FileEditorTool")]
>>> agent = Agent(llm=llm, tools=tools)
```

#### Properties

* `model_config`: = (configuration object)
  Configuration for the model, should be a dictionary conforming to \[ConfigDict]\[pydantic.config.ConfigDict].

#### Methods

#### init\_state()

Initialize conversation state.

Invariants enforced by this method:

* If a SystemPromptEvent is already present, it must be within the first 3

  events (index 0 or 1 in practice; index 2 is included in the scan window
  to detect a user message appearing before the system prompt).
* A user MessageEvent should not appear before the SystemPromptEvent.

These invariants keep event ordering predictable for downstream components
(condenser, UI, etc.) and also prevent accidentally materializing the full
event history during initialization.

#### model\_post\_init()

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

* Parameters:
  * `self` – The BaseModel instance.
  * `context` – The context.

#### step()

Taking a step in the conversation.

Typically this involves:

1. Making a LLM call
2. Executing the tool
3. Updating the conversation state with

LLM calls (role=”assistant”) and tool results (role=”tool”)

4.1 If conversation is finished, set state.execution\_status to FINISHED
4.2 Otherwise, just return, Conversation will kick off the next step

If the underlying LLM supports streaming, partial deltas are forwarded to
`on_token` before the full response is returned.

NOTE: state will be mutated in-place.

### class AgentBase

Bases: `DiscriminatedUnionMixin`, `ABC`

Abstract base class for OpenHands agents.

Agents are stateless and should be fully defined by their configuration.
This base class provides the common interface and functionality that all
agent implementations must follow.

#### Properties

* `agent_context`: AgentContext | None
* `condenser`: CondenserBase | None
* `critic`: CriticBase | None
* `dynamic_context`: str | None
  Get the dynamic per-conversation context.
  This returns the context that varies between conversations, such as:
  * Repository information and skills
  * Runtime information (hosts, working directory)
  * User-specific secrets and settings
  * Conversation instructions
    This content should NOT be included in the cached system prompt to enable
    cross-conversation cache sharing. Instead, it is sent as a second content
    block (without a cache marker) inside the system message.
  - Returns:
    The dynamic context string, or None if no context is configured.
* `filter_tools_regex`: str | None
* `include_default_tools`: list\[str]
* `llm`: LLM
* `mcp_config`: dict\[str, Any]
* `model_config`: = (configuration object)
  Configuration for the model, should be a dictionary conforming to \[ConfigDict]\[pydantic.config.ConfigDict].
* `name`: str
  Returns the name of the Agent.
* `prompt_dir`: str
  Returns the directory where this class’s module file is located.
* `security_policy_filename`: str
* `static_system_message`: str
  Compute the static portion of the system message.
  This returns only the base system prompt template without any dynamic
  per-conversation context. This static portion can be cached and reused
  across conversations for better prompt caching efficiency.
  * Returns:
    The rendered system prompt template without dynamic context.
* `system_message`: str
  Return the combined system message (static + dynamic).
* `system_prompt_filename`: str
* `system_prompt_kwargs`: dict\[str, object]
* `tools`: list\[Tool]
* `tools_map`: dictstr, \[ToolDefinition]
  Get the initialized tools map.
  :raises RuntimeError: If the agent has not been initialized.

#### Methods

#### get\_all\_llms()

Recursively yield unique base-class LLM objects reachable from self.

* Returns actual object references (not copies).
* De-dupes by id(LLM).
* Cycle-safe via a visited set for all traversed objects.
* Only yields objects whose type is exactly LLM (no subclasses).
* Does not handle dataclasses.

#### init\_state()

Initialize the empty conversation state to prepare the agent for user
messages.

Typically this involves adding system message

NOTE: state will be mutated in-place.

#### model\_dump\_succint()

Like model\_dump, but excludes None fields by default.

#### model\_post\_init()

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

* Parameters:
  * `self` – The BaseModel instance.
  * `context` – The context.

#### abstractmethod step()

Taking a step in the conversation.

Typically this involves:

1. Making a LLM call
2. Executing the tool
3. Updating the conversation state with

LLM calls (role=”assistant”) and tool results (role=”tool”)

4.1 If conversation is finished, set state.execution\_status to FINISHED
4.2 Otherwise, just return, Conversation will kick off the next step

If the underlying LLM supports streaming, partial deltas are forwarded to
`on_token` before the full response is returned.

NOTE: state will be mutated in-place.

#### Deprecated

Deprecated since version 1.11.0: Use [`static_system_message`](#class-static_system_message) for the cacheable system prompt and
[`dynamic_context`](#class-dynamic_context) for per-conversation content. This separation
enables cross-conversation prompt caching. Will be removed in 1.16.0.

#### WARNING

Using this property DISABLES cross-conversation prompt caching because
it combines static and dynamic content into a single string. Use
[`static_system_message`](#class-static_system_message) and [`dynamic_context`](#class-dynamic_context) separately
to enable caching.

#### Deprecated

Deprecated since version 1.11.0: This will be removed in 1.16.0. Use static\_system\_message for the cacheable system prompt and dynamic\_context for per-conversation content. Using system\_message DISABLES cross-conversation prompt caching because it combines static and dynamic content into a single string.

#### verify()

Verify that we can resume this agent from persisted state.

We do not merge configuration between persisted and runtime Agent
instances. Instead, we verify compatibility requirements and then
continue with the runtime-provided Agent.

Compatibility requirements:

* Agent class/type must match.
* Tools must match exactly (same tool names).

Tools are part of the system prompt and cannot be changed mid-conversation.
To use different tools, start a new conversation or use conversation forking
(see [https://github.com/OpenHands/OpenHands/issues/8560](https://github.com/OpenHands/OpenHands/issues/8560)).

All other configuration (LLM, agent\_context, condenser, etc.) can be
freely changed between sessions.

* Parameters:
  * `persisted` – The agent loaded from persisted state.
  * `events` – Unused, kept for API compatibility.
* Returns:
  This runtime agent (self) if verification passes.
* Raises:
  `ValueError` – If agent class or tools don’t match.
