Skip to content

Conversation

Ratish1
Copy link

@Ratish1 Ratish1 commented Aug 26, 2025

Description

Previously, passing a file path that contained multiple @tool decorated functions resulted in only one tool being loaded/registered. This made file-based tool loading inconsistent with directory/module scanning (which returns all decorated tools). This PR fixes that: the file-path loader now collects all decorated function tools and returns them; the registry is updated to register each tool individually. Unit tests and linters were updated and run locally.

Key Changes

  • Collect all DecoratedFunctionTool objects when loading a .py file and return a list when multiple exist.
  • Normalize loader results and register each AgentTool separately in the registry.
  • Add normalize_loaded_tools helper to src/strands/tools/tools.py.
  • Add unit test test_load_python_tool_path_multiple_function_based verifying multiple decorated tools are discovered when loading a file path.
  • Update callers/registry to iterate loaded tools and call mark_dynamic() + register_tool() per tool.

Related Issues

Closes #612

Documentation PR

N/A

Type of Change

Bug fix

Testing

How have you tested the change? Verify that the changes do not break functionality or introduce warnings in consuming repositories: agents-docs, agents-tools, agents-cli

  • I ran hatch run prepare
  • I ran formatters and linters locally:
    • hatch fmt --formatter → 170 files left unchanged
    • hatch fmt --linter → All checks passed
    • pre-commit run --all-files → Format: Passed; Lint: Passed; Type linting: Passed; Unit Tests: Passed
  • I ran the unit test(s) locally:
    • pytest -q tests/strands/tools/test_loader.py::test_load_python_tool_path_multiple_function_based1 passed in 0.16s
  • I ran hatch run test-integ locally.

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

…om file path

- Collect all DecoratedFunctionTool objects when loading a .py file and return list when multiple exist
- Normalize loader results and register each AgentTool separately in registry
- Add normalize_loaded_tools helper and test for multiple decorated tools
@@ -18,15 +18,17 @@ class ToolLoader:
"""Handles loading of tools from different sources."""

@staticmethod
def load_python_tool(tool_path: str, tool_name: str) -> AgentTool:
def load_python_tool(tool_path: str, tool_name: str) -> Union[AgentTool, List[AgentTool]]:
Copy link
Member

Choose a reason for hiding this comment

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

For backwards compatibility, we need to keep this signature as-is.

Let's add a new method, load_python_tools that does what you're doing here but always turns an array. Then load_python_tool can be updated to reference the new api, returning the first element in the array. Let's then document that load_python_tool is deprecated and emit a warning if it's invoked. We can then remove the method in 2.0

@zastrowm zastrowm self-assigned this Aug 29, 2025
Unshure and others added 12 commits August 30, 2025 22:03
Step 1/N for implementing typed-events; first just preserve the existing behaviors with no changes to the public api.

A follow-up change will update how we invoke callbacks and pass invocation_state around, while this one just adds typed classes for events internally.

---------

Co-authored-by: Mackenzie Zastrow <[email protected]>
…s#698)

* summarization manager - add summary prompt to messages

* summarize conversation - assistant to user role

* fix test

* add period
…s#755)

Move away from "callback" nested properties in the dict and explicitly passing invocation_state migrating to behaviors on the TypedEvent:

 - TypedEvent.is_callback_event for determining if an event should be yielded and or invoked in the callback
 - TypedEvent.prepare for taking in invocation_state

Customers still only get dictionaries, as we decided that this will remain an implementation detail for the time being, but this makes the events typed all the way up until *just* before we yield events back to the caller

---------

Co-authored-by: Mackenzie Zastrow <[email protected]>
* feat: add citations to document content

* feat: addes citation types

* chore: remove uv.lock

* test: add letter.pdf for test-integ

* feat: working bedrock citations feature

* feat: fail early for citations with incompatible models

* fix: validates model ids with cross region inference ids

* Apply suggestion from @Unshure

Co-authored-by: Nick Clegg <[email protected]>

* fix: addresses comments

* removes client exception handling
* moves citation into text elif
* puts relative imports back

* fix: tests failing

* Update src/strands/models/bedrock.py

Removes old comment

Co-authored-by: Nick Clegg <[email protected]>

* Update src/strands/models/bedrock.py

Removes old comment

Co-authored-by: Nick Clegg <[email protected]>

* Update imports in bedrock.py

Refactor imports in bedrock.py to include CitationsDelta.

* feat: typed citation events

---------

Co-authored-by: Nick Clegg <[email protected]>
It's been a customer ask and we don't have a pressing need to keep it restricted.

The primary concern is that because agent's state is manipulated between invocations (state is reset) hooks designed for a single agent may not work for multi-agents. With documentation, we can guide folks to be aware of what happens rather than restricting it outright.

---------

Co-authored-by: Mackenzie Zastrow <[email protected]>
…ts#767)

* fix: fix stop reason for bedrock model when stop_reason is end_turn in tool use response.

* change logger info to warning, optimize if condition

* fix: add unit tests

---------

Co-authored-by: Jack Yuan <[email protected]>
Expand the Unit Tests for the yielded event to verify actual tool calls - previous to this, the events were not being emitted because the test was bailing out due to mocked guard rails.  To better test the situation, we now have a much more extensive test for the successful tool call

Co-authored-by: Mackenzie Zastrow <[email protected]>
* fix: fix loading tools with same tool name

* simplify if condition

---------

Co-authored-by: Jack Yuan <[email protected]>
@Ratish1 Ratish1 requested a review from zastrowm August 30, 2025 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] Tools loaded by passing a file path only load the last defined tool in file
7 participants