diff --git a/.gitignore b/.gitignore index 5cdc43db..cf9e0a40 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ __pycache__* .ruff_cache *.bak .vscode -dist \ No newline at end of file +dist +.idea \ No newline at end of file diff --git a/src/strands/agent/conversation_manager/sliding_window_conversation_manager.py b/src/strands/agent/conversation_manager/sliding_window_conversation_manager.py index 683cb52f..53ac374f 100644 --- a/src/strands/agent/conversation_manager/sliding_window_conversation_manager.py +++ b/src/strands/agent/conversation_manager/sliding_window_conversation_manager.py @@ -140,7 +140,7 @@ def reduce_context(self, agent: "Agent", e: Optional[Exception] = None) -> None: if results_truncated: logger.debug("message_index=<%s> | tool results truncated", last_message_idx_with_tool_results) return - + # Try to trim index id when tool result cannot be truncated anymore # If the number of messages is less than the window_size, then we default to 2, otherwise, trim to window size trim_index = 2 if len(messages) <= self.window_size else len(messages) - self.window_size diff --git a/src/strands/tools/registry.py b/src/strands/tools/registry.py index e56ee999..8827b992 100644 --- a/src/strands/tools/registry.py +++ b/src/strands/tools/registry.py @@ -92,8 +92,8 @@ def process_tools(self, tools: List[Any]) -> List[str]: if not function_tools: logger.warning("tool_name=<%s>, module_path=<%s> | invalid agent tool", tool_name, module_path) - # Case 5: Function decorated with @tool - elif inspect.isfunction(tool) and hasattr(tool, "TOOL_SPEC"): + # Case 5: Function or Method decorated with @tool + elif (inspect.isfunction(tool) or inspect.ismethod(tool)) and hasattr(tool, "TOOL_SPEC"): try: function_tool = FunctionTool(tool) logger.debug("tool_name=<%s> | registering function tool", function_tool.tool_name) diff --git a/tests-integ/test_mcp_client.py b/tests-integ/test_mcp_client.py index f0669284..8b1dade3 100644 --- a/tests-integ/test_mcp_client.py +++ b/tests-integ/test_mcp_client.py @@ -104,8 +104,8 @@ def test_can_reuse_mcp_client(): @pytest.mark.skipif( - condition=os.environ.get("GITHUB_ACTIONS") == 'true', - reason="streamable transport is failing in GitHub actions, debugging if linux compatibility issue" + condition=os.environ.get("GITHUB_ACTIONS") == "true", + reason="streamable transport is failing in GitHub actions, debugging if linux compatibility issue", ) def test_streamable_http_mcp_client(): server_thread = threading.Thread( diff --git a/tests-integ/test_method_tools.py b/tests-integ/test_method_tools.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/strands/tools/test_registry.py b/tests/strands/tools/test_registry.py index 1b274f46..9059dccd 100644 --- a/tests/strands/tools/test_registry.py +++ b/tests/strands/tools/test_registry.py @@ -6,6 +6,7 @@ import pytest +from strands import tool from strands.tools import PythonAgentTool from strands.tools.registry import ToolRegistry @@ -43,3 +44,25 @@ def test_register_tool_with_similar_name_raises(): str(err.value) == "Tool name 'tool_like_this' already exists as 'tool-like-this'. " "Cannot add a duplicate tool which differs by a '-' or '_'" ) + + +@pytest.fixture +def test_agent(): + class TestAgent: + @tool + def word_counter(self, text: str) -> str: + """Count words in text""" + return f"Word count: {len(text.split())}" + + return TestAgent() + + +@pytest.fixture +def tool_registry(): + return ToolRegistry() + + +def test_class_method_register_tool(test_agent, tool_registry): + registered_tool_names = tool_registry.process_tools([test_agent.word_counter]) + assert len(registered_tool_names) == 1 + assert registered_tool_names[0] == "word_counter"