{"id":34253660,"url":"https://github.com/spring-ai-community/spring-ai-tool-search-tool","last_synced_at":"2026-03-10T20:36:34.439Z","repository":{"id":328217026,"uuid":"1113501118","full_name":"spring-ai-community/spring-ai-tool-search-tool","owner":"spring-ai-community","description":"Dynamic tool discovery and selection for Spring AI, enabling LLMs to work efficiently with large tool libraries by discovering tools on-demand instead of loading all definitions upfront.","archived":false,"fork":false,"pushed_at":"2026-01-26T12:34:07.000Z","size":430,"stargazers_count":37,"open_issues_count":0,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-27T01:18:21.877Z","etag":null,"topics":["agentic-ai","spring-ai","tool-calling"],"latest_commit_sha":null,"homepage":"https://spring.io/blog/2025/12/11/spring-ai-tool-search-tools-tzolov","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spring-ai-community.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-10T04:16:21.000Z","updated_at":"2026-01-26T12:34:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/spring-ai-community/spring-ai-tool-search-tool","commit_stats":null,"previous_names":["spring-ai-community/spring-ai-tool-search-tool"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/spring-ai-community/spring-ai-tool-search-tool","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-ai-community%2Fspring-ai-tool-search-tool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-ai-community%2Fspring-ai-tool-search-tool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-ai-community%2Fspring-ai-tool-search-tool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-ai-community%2Fspring-ai-tool-search-tool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spring-ai-community","download_url":"https://codeload.github.com/spring-ai-community/spring-ai-tool-search-tool/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-ai-community%2Fspring-ai-tool-search-tool/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30352932,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T15:55:29.454Z","status":"ssl_error","status_checked_at":"2026-03-10T15:54:58.440Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-ai","spring-ai","tool-calling"],"created_at":"2025-12-16T11:49:21.520Z","updated_at":"2026-03-10T20:36:34.431Z","avatar_url":"https://github.com/spring-ai-community.png","language":"Java","funding_links":[],"categories":["⚰️ Graveyard"],"sub_categories":["Or hire a skeleton"],"readme":"# Tool Search Tool for Spring AI [![build status](https://github.com/spring-ai-community/spring-ai-tool-search-tool/actions/workflows/publish-snapshot.yml/badge.svg)](https://github.com/spring-ai-community/spring-ai-tool-search-tool/actions/workflows/publish-snapshot.yml) [![Maven Central](https://img.shields.io/maven-central/v/org.springaicommunity/tool-search-tool?label=Maven%20Central\u0026versionPrefix=2)](https://central.sonatype.com/artifact/org.springaicommunity/tool-search-tool) [![Java Version](https://img.shields.io/badge/Java-17%2B-orange)](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)\n\n\u003e _**NOTE:** This is Spring AI 2.x / Boot 4 compatibible version._\n\u003e _For Spring AI 1.1.x / Boot 3 support switch to: [Tool Search Tool - v1.0.x](https://github.com/spring-ai-community/spring-ai-tool-search-tool/tree/1.0.x)_\n\nDynamic tool discovery and selection for Spring AI, enabling LLMs to work efficiently with large tool libraries by discovering tools on-demand instead of loading all definitions upfront. **Itroduction blog:** [Smart Tool Selection: Achieving 34-64% Token Savings with Spring AI's Dynamic Tool Discovery](https://spring.io/blog/2025/12/11/spring-ai-tool-search-tools-tzolov)\n\n### The Problem\n\nAs AI agents connect to more services—Slack, GitHub, Jira, MCP servers—tool libraries grow rapidly. A typical multi-server setup can easily have 50+ tools consuming **55,000+ tokens** before any conversation starts. Tool selection accuracy also degrades when models face 30+ similarly-named tools.\n\n\n### The Solution\n\n\u003cimg style=\"fdisplay: block; margin: 0px auto; padding: 20px;\" src=\"https://github.com/spring-io/spring-io-static/blob/main/blog/tzolov/20251208/spring-ai-tool-search-tool-calling-flow.png?raw=true\" width=\"300\" align=\"left\"/\u003e\n\nThis project implements the **[Tool Search Tool](https://www.anthropic.com/engineering/advanced-tool-use)** pattern for Spring AI:\n- Model receives only a search tool initially (minimal tokens)\n- When capabilities are needed, model searches for relevant tools\n- Matching tool definitions are dynamically expanded into context\n- Model invokes discovered tools to complete the task\n\n**Result:** Significant token savings while maintaining access to thousands of tools.\n\n\n   \n\n\n## Project Structure\n\n```\nspring-ai-tool-search-tool/\n├── tool-search-tool/           # Core advisor implementation\n├── tool-searchers/             # Pluggable search strategies\n│   ├── tool-searcher-vectorstore/   # Semantic search (embeddings)\n│   ├── tool-searcher-lucene/        # Keyword search (full-text)\n│   └── tool-searcher-regex/         # Pattern matching\n├── tool-search-tool-bom/       # Bill of Materials\n└── examples/\n    ├── tool-search-tool-demo/  # Recommended approach\n    └── pre-select-tool-demo/   # Alternative approach\n```\n\n## Quick Start\n\n### 1. Add Dependencies\n\nThen add the dependencies:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.springaicommunity\u003c/groupId\u003e\n    \u003cartifactId\u003etool-search-tool\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003c!-- Choose a search strategy --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.springaicommunity\u003c/groupId\u003e\n    \u003cartifactId\u003etool-searcher-lucene\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nFor snapshot versions add the snapshot repository to your `pom.xml`:\n\n```xml\n\u003crepositories\u003e\n    \u003crepository\u003e\n        \u003cid\u003ecentral-snapshots\u003c/id\u003e\n        \u003curl\u003ehttps://central.sonatype.com/repository/maven-snapshots/\u003c/url\u003e\n        \u003csnapshots\u003e\n            \u003cenabled\u003etrue\u003c/enabled\u003e\n        \u003c/snapshots\u003e\n    \u003c/repository\u003e\n\u003c/repositories\u003e\n```\n\n### 2. Configure the Advisor\n\n```java\n@Bean\nToolSearcher toolSearcher() {\n    return new LuceneToolSearcher(0.4f);\n}\n\n@Bean\nCommandLineRunner demo(ChatClient.Builder builder, ToolSearcher toolSearcher) {\n    return args -\u003e {\n        var advisor = ToolSearchToolCallAdvisor.builder()\n            .toolSearcher(toolSearcher)\n            .build();\n\n        ChatClient chatClient = builder\n            .defaultTools(new MyTools())  // 100s of tools - NOT sent to LLM initially\n            .defaultAdvisors(advisor)\n            .build();\n\n        String answer = chatClient\n            .prompt(\"What's the weather in Amsterdam?\")\n            .call()\n            .content();\n    };\n}\n```\n\n## Search Strategies\n\n| Strategy | Module | Best For |\n|----------|--------|----------|\n| **Semantic** | `tool-searcher-vectorstore` | Natural language queries, fuzzy matching |\n| **Keyword** | `tool-searcher-lucene` | Exact term matching, known tool names |\n| **Regex** | `tool-searcher-regex` | Tool name patterns (`get_*`, `*_api`) |\n\nSee [Tool Searchers README](tool-searchers/README.md) for detailed documentation.\n\n## How It Works\n\n1. **Indexing**: Tools are indexed in the `ToolSearcher` (not sent to LLM)\n2. **Initial Request**: Only `toolSearchTool` definition is sent to LLM\n3. **Discovery**: LLM calls `toolSearchTool(query=\"weather\")` to find relevant tools\n4. **Expansion**: Discovered tools are added to next request\n5. **Execution**: LLM calls discovered tools to complete the task\n6. **Response**: Final answer generated\n\nSee [Tool Search Tool README](tool-search-tool/README.md) for detailed documentation.\n\n## Examples\n\n### Tool Search Tool Demo (Recommended)\n\nLLM actively discovers tools on-demand:\n\n```bash\ncd examples/tool-search-tool-demo\nmvn spring-boot:run\n```\n\nSee [example README](examples/tool-search-tool-demo/README.md).\n\n### Pre-Select Tool Demo (Alternative)\n\nPre-selects tools based on conversation context:\n\n```bash\ncd examples/pre-select-tool-demo\nmvn spring-boot:run\n```\n\nSee [example README](examples/pre-select-tool-demo/README.md).\n\n## Building\n\n```bash\nmvn clean install\n```\n\n## Requirements\n\n- Java 17+\n- Spring AI 2.0.0-M2+\n- Maven 3.6+\n\n## Key Benefits\n\n- **Token efficiency** - Reduced context windows (80-90% savings)\n- **Better accuracy** - Models select the right tool when focused on fewer options\n- **Portable** - Works with any LLM supported by Spring AI\n- **Flexible** - Swap search strategies based on your use case\n- **Observable** - Leverages Spring AI's advisor chain for logging and monitoring\n\n## Related Resources\n\n- [Anthropic's Tool Search Tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool)\n- [Anthropic's Advanced Tool Use Blog](https://www.anthropic.com/engineering/advanced-tool-use)\n- [Spring AI Tool Calling](https://docs.spring.io/spring-ai/reference/api/tools.html)\n- [Spring AI Recursive Advisors](https://docs.spring.io/spring-ai/reference/api/advisors-recursive.html)\n\n## License\n\nApache License 2.0 - See [LICENSE.txt](LICENSE.txt)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspring-ai-community%2Fspring-ai-tool-search-tool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspring-ai-community%2Fspring-ai-tool-search-tool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspring-ai-community%2Fspring-ai-tool-search-tool/lists"}