Skip to content

Conversation

@xingyaoww
Copy link
Collaborator

@xingyaoww xingyaoww commented Jan 5, 2026

Summary

This PR adds a new include_default_tools field to AgentBase that allows users to control which default tools (FinishTool, ThinkTool) are automatically added to the agent.

This addresses the issue where users want to create custom versions of the finish or think tools but cannot exclude the built-in versions.

Changes

  1. New field include_default_tools: list[str] - A list of default tool class names to include. By default, includes all built-in tools (["FinishTool", "ThinkTool"]). Set to an empty list to disable all default tools, or provide a subset to include only specific ones.

  2. Updated _initialize() method - Now only adds tools that are in the include_default_tools list.

  3. Added _initialized flag - Needed to properly track initialization state since an empty tools dict is now valid when all default tools are disabled.

  4. Dynamic BUILT_IN_TOOL_CLASSES generation - The mapping of tool class names to classes is now generated dynamically from BUILT_IN_TOOLS in openhands/sdk/tool/builtins/__init__.py, making it easier to add new built-in tools in the future.

Usage Examples

# Include only the finish tool (exclude think)
agent = Agent(llm=llm, tools=[], include_default_tools=["FinishTool"])

# Include only the think tool (exclude finish) and provide a custom finish
agent = Agent(
    llm=llm,
    tools=[Tool(name="custom_finish")],
    include_default_tools=["ThinkTool"],
)

# Disable all default tools
agent = Agent(llm=llm, tools=[], include_default_tools=[])

# Default behavior - include all default tools
agent = Agent(llm=llm, tools=[])  # includes FinishTool and ThinkTool

Fixes #1592

Checklist

  • If the PR is changing/adding functionality, are there tests to reflect this?
  • If there is an example, have you run the example to make sure that it works?
  • If there are instructions on how to run the code, have you followed the instructions and made sure that it works?
  • If the feature is significant enough to require documentation, is there a PR open on the OpenHands/docs repository with the same branch name?
  • Is the github CI passing?

Agent Server images for this PR

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.12-nodejs22 Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:7f46298-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-7f46298-python \
  ghcr.io/openhands/agent-server:7f46298-python

All tags pushed for this build

ghcr.io/openhands/agent-server:7f46298-golang-amd64
ghcr.io/openhands/agent-server:7f46298-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:7f46298-golang-arm64
ghcr.io/openhands/agent-server:7f46298-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:7f46298-java-amd64
ghcr.io/openhands/agent-server:7f46298-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:7f46298-java-arm64
ghcr.io/openhands/agent-server:7f46298-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:7f46298-python-amd64
ghcr.io/openhands/agent-server:7f46298-nikolaik_s_python-nodejs_tag_python3.12-nodejs22-amd64
ghcr.io/openhands/agent-server:7f46298-python-arm64
ghcr.io/openhands/agent-server:7f46298-nikolaik_s_python-nodejs_tag_python3.12-nodejs22-arm64
ghcr.io/openhands/agent-server:7f46298-golang
ghcr.io/openhands/agent-server:7f46298-java
ghcr.io/openhands/agent-server:7f46298-python

About Multi-Architecture Support

  • Each variant tag (e.g., 7f46298-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 7f46298-python-amd64) are also available if needed

This change adds a new 'disable_default_tools' field to AgentBase that
allows users to exclude specific default tools (finish, think) from
being automatically added to the agent.

This enables users to:
- Disable the think tool if not needed
- Disable the finish tool to provide a custom implementation
- Replace built-in tools with custom versions that have different
  behavior or output formats

The implementation:
- Adds 'disable_default_tools: list[str]' field to AgentBase
- Updates _initialize() to skip tools whose names are in the list
- Adds '_initialized' flag to properly track initialization state
  (needed because empty tools dict is now valid)
- Adds tests for disabling individual tools, all tools, and replacing
  with custom implementations

Fixes #1592

Co-authored-by: openhands <[email protected]>
@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-sdk/openhands/sdk/agent
   base.py1762585%187, 193, 261–262, 273–275, 285, 295, 303–304, 399–400, 402–406, 408–409, 420, 457–458, 468–469
TOTAL14925714152% 

Copy link
Contributor

@neubig neubig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty good to me, but do we want to use a list of classes as opposed to a list of strings? That might be more typo-proof.

@xingyaoww
Copy link
Collaborator Author

@OpenHands can you address this comment #1594 (review)?

@openhands-ai
Copy link

openhands-ai bot commented Jan 5, 2026

Uh oh! There was an unexpected error starting the job :(

@xingyaoww
Copy link
Collaborator Author

@OpenHands can you address this comment #1594 (review)?

@openhands-ai
Copy link

openhands-ai bot commented Jan 5, 2026

I'm on it! xingyaoww can track my progress at all-hands.dev

Changed disable_default_tools from list[str] to list[type[ToolDefinition]]
to make the API more typo-proof. Users now pass tool classes directly
(e.g., [ThinkTool, FinishTool]) instead of string names.

Added serializer/validator to handle JSON serialization by converting
classes to/from their class names.

Co-authored-by: openhands <[email protected]>
@openhands-ai
Copy link

openhands-ai bot commented Jan 5, 2026

I've addressed the PR review comment from @neubig requesting to use tool classes instead of strings for disable_default_tools to make the API more typo-proof.

Changes Made

  1. Changed disable_default_tools type from list[str] to list[type[ToolDefinition]]

    • Users now pass tool classes directly (e.g., [ThinkTool, FinishTool]) instead of string names
  2. Added serializer/validator for JSON serialization support:

    • _ser_disable_default_tools: Converts tool classes to their class names for JSON storage
    • _val_disable_default_tools: Converts class names back to tool classes during deserialization
  3. Updated tests to use tool classes instead of strings

Usage Examples (Updated)

from openhands.sdk.tool import ThinkTool, FinishTool

# Disable the think tool
agent = Agent(llm=llm, tools=[], disable_default_tools=[ThinkTool])

# Disable the finish tool and provide a custom implementation
agent = Agent(
    llm=llm,
    tools=[Tool(name="custom_finish")],
    disable_default_tools=[FinishTool],
)

# Disable all default tools
agent = Agent(llm=llm, tools=[], disable_default_tools=[FinishTool, ThinkTool])

The changes have been pushed to the PR branch: #1594

View full conversation

@xingyaoww xingyaoww added the review-this This label triggers a PR review by OpenHands label Jan 6, 2026
Change the field from disable_default_tools to include_default_tools with
BUILT_IN_TOOLS as the default value. This maintains backward compatibility
since the default behavior includes all default tools.

Users can now:
- Set include_default_tools=[] to disable all default tools
- Set include_default_tools=[FinishTool] to only include FinishTool
- Set include_default_tools=[ThinkTool] to only include ThinkTool

Co-authored-by: openhands <[email protected]>
@xingyaoww
Copy link
Collaborator Author

@OpenHands please fix the failing actions on PR #1594 at branch openhands/disable-default-tools

@openhands-ai
Copy link

openhands-ai bot commented Jan 7, 2026

I'm on it! xingyaoww can track my progress at all-hands.dev

…neration

The previous implementation used list[type[ToolDefinition]] which caused
FastAPI's OpenAPI schema generation to fail because Pydantic couldn't
generate a schema for the ToolExecutor type (used in ToolDefinition).

This change:
- Changes the field type from list[type[ToolDefinition]] to list[str]
- Stores tool class names as strings instead of class references
- Keeps backward compatibility by accepting both strings and tool classes
  in the validator (tool classes are converted to their names)
- Resolves tool class names to actual classes at initialization time

The API remains backward compatible - users can still pass tool classes
like [FinishTool, ThinkTool] and they will be converted to strings.

Co-authored-by: openhands <[email protected]>
Update tests to use string tool names instead of tool classes to match
the new type annotation. The validator still accepts both strings and
tool classes for backward compatibility, but the type annotation is
list[str] to ensure proper OpenAPI schema generation.

Co-authored-by: openhands <[email protected]>
Replace ToolDefinition.resolve_kind() with an explicit BUILT_IN_TOOL_CLASSES
mapping for deserializing include_default_tools. This is more reliable as
resolve_kind() depends on subclass discovery which may fail if classes
haven't been imported.

Also add comprehensive tests for include_default_tools serialization and
deserialization to ensure round-trip works correctly.

Co-authored-by: openhands <[email protected]>
@xingyaoww xingyaoww added review-this This label triggers a PR review by OpenHands and removed review-this This label triggers a PR review by OpenHands labels Jan 8, 2026
@openhands-ai
Copy link

openhands-ai bot commented Jan 8, 2026

Looks like there are a few issues preventing this PR from being merged!

  • GitHub Actions are failing:
    • PR Review by OpenHands

If you'd like me to help, just leave a comment, like

@OpenHands please fix the failing actions on PR #1594 at branch `openhands/disable-default-tools`

Feel free to include any additional details that might help me get this PR into a better state.

You can manage your notification settings

AgentBase is a frozen Pydantic model, so agent_context cannot be set
after the agent is created. This fix passes agent_context directly
to the Agent constructor instead of setting it as an attribute.

Co-authored-by: openhands <[email protected]>
@xingyaoww xingyaoww marked this pull request as ready for review January 8, 2026 17:43
@xingyaoww xingyaoww marked this pull request as draft January 8, 2026 17:45
Move BUILT_IN_TOOL_CLASSES definition to the same location as BUILT_IN_TOOLS
in openhands/sdk/tool/builtins/__init__.py and generate it dynamically using
a dict comprehension instead of hardcoding the mapping.

Co-authored-by: openhands <[email protected]>
Remove the field validator for include_default_tools to simplify the code.
Validation of tool names is already done at initialization time in _initialize().

Also remove the related tests that depended on the validator behavior.

Co-authored-by: openhands <[email protected]>
@xingyaoww xingyaoww changed the title feat: Add disable_default_tools option to exclude built-in tools feat: Add include_default_tools option to control built-in tools Jan 8, 2026
@xingyaoww xingyaoww marked this pull request as ready for review January 8, 2026 17:55
@xingyaoww xingyaoww requested review from enyst and neubig January 8, 2026 17:55
@xingyaoww xingyaoww enabled auto-merge (squash) January 8, 2026 17:57
@xingyaoww xingyaoww merged commit ad0802d into main Jan 8, 2026
23 checks passed
@xingyaoww xingyaoww deleted the openhands/disable-default-tools branch January 8, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-this This label triggers a PR review by OpenHands

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a way to exclude built in tools

4 participants