Federico Mariani created CAMEL-24767:
----------------------------------------
Summary: camel-ai-tool - reinstate tool search, shared by
langchain4j-agent, spring-ai-chat and openai
Key: CAMEL-24767
URL: https://issues.apache.org/jira/browse/CAMEL-24767
Project: Camel
Issue Type: Improvement
Reporter: Federico Mariani
h2. Context
CAMEL-22851 added a native tool-search-tool to {{camel-langchain4j-tools}}
(shipped in 4.18.0). It added an {{exposed}} URI option: with {{exposed=false}}
a tool was not sent to the LLM on every request but placed in a searchable
registry, and a {{toolSearchTool}} was auto-exposed so the LLM could discover
it on demand.
{{camel-langchain4j-tools}} was deprecated in 4.22 and removed in 4.23 (commit
2a2b0e1bb71c), replaced by {{camel-ai-tool}} for tool definition and
{{camel-langchain4j-agent}} for tool calling. The tool-search capability was
*not* ported: {{AiToolConfiguration}} has no {{exposed}}/searchable equivalent,
and none of the three AI producers that consume {{AiToolRegistry}} support tool
search today.
So the feature regressed out of the project as a side effect of the migration.
The 4.22 and 4.23 upgrade guides document the {{langchain4j-tools:}} ->
{{ai-tool:}} route migration but do not mention that {{exposed=false}} has no
equivalent.
h2. Why it matters
All three producers select tools by {{tags}} and serialise every matching
{{ai-tool:}} route into every request:
* {{camel-langchain4j-agent}} - via {{AiToolSpecToLangChain4j}} /
{{ToolProvider}}
* {{camel-spring-ai-chat}} - {{SpringAiChatProducer#applyRequestOptions}} puts
all tag-matched callbacks into {{ToolCallingChatOptions}}
* {{camel-openai}} - {{OpenAIEndpoint}} lines 283/366
With a broad tag over a large route catalogue this consumes a significant part
of the context window on every call, and tool-selection accuracy degrades well
before the context limit is reached.
h2. Proposal
Reinstate tool search in {{camel-ai-tool}}, which is the shared abstraction
({{AiToolRegistry}} / {{AiToolSpec}}), so the three consumers behave
consistently rather than each inheriting whatever its upstream framework does:
# Consumer side: an option on {{ai-tool:}} marking a tool searchable rather
than always-visible (the {{exposed}} option from CAMEL-22851, or a clearer
name).
# Producer side: a {{toolSearch}} option on {{langchain4j-agent}},
{{spring-ai-chat}} and {{openai}} enabling the search tool for that endpoint.
# A scoring/index implementation over {{AiToolSpec}} in {{camel-ai-tool}}, so
{{tags}} semantics and ranking are identical across the three.
# Upgrade-guide entry noting the capability was absent between the removal and
this change.
h2. Framework support now available
This did not exist when CAMEL-22851 was implemented (it was hand-rolled in
Camel). Both frameworks now ship it, at versions Camel already depends on:
* *LangChain4j 1.20.0* - {{dev.langchain4j.service.tool.search}}
({{@Experimental}}, since 1.12.0): {{ToolSearchStrategy}} with
{{SimpleToolSearchStrategy}} (keyword) and {{VectorToolSearchStrategy}}
(embeddings, needs only an {{EmbeddingModel}}), wired with
{{AiServices.toolSearchStrategy(...)}}. Tools supplied through a
{{ToolProvider}} - which is how Camel passes route tools - are searchable:
{{ToolService#createContext}} builds {{availableTools}} from static tools and
providers first, then applies the search service.
{{AbstractAgent#configureBuilder}} already sets sibling options
({{maxToolCallingRoundTrips}}, {{hallucinatedToolNameStrategy}}), so this is a
few lines. It is also reachable today without any Camel change through the
existing {{AgentConfiguration#withAiServicesCustomizer}} escape hatch, which
makes it easy to validate the behaviour before committing to an API.
* *Spring AI 2.0.1* - {{spring-ai-tool-search-tool}} and
{{spring-ai-tool-search-advisor}}: {{ToolIndex}} (regex, Lucene, vector store),
{{ToolSearchToolCallingAdvisor}} with {{maxResults}} and session-scoped LRU/TTL
eviction. Session scoping maps onto the existing
{{CamelSpringAiChatConversationId}} header. Note this advisor extends
{{ToolCallingAdvisor}}, which replaces the model-internal tool-calling loop -
that is the main design consideration on this side.
* *camel-openai* - no equivalent in the OpenAI Java SDK, but Camel owns the
agentic loop already ({{maxToolIterations}}), so the search tool has to be
driven directly. This is the strongest argument for putting the index in
{{camel-ai-tool}}: it gives the OpenAI component an implementation to reuse
instead of a bespoke one.
h2. Open questions
* Option naming, and whether searchable is opt-in on the tool
({{exposed=false}}, as in CAMEL-22851) or opt-in on the producer
({{toolSearch=true}}), or both.
* Keyword matching (as the original implementation did, by tag) versus
embedding-based semantic search, which both frameworks now offer.
* Whether to delegate to each framework's native implementation, or keep a
single Camel-owned index for consistent behaviour across the three components.
The frameworks differ in how discovered tools persist: LangChain4j accumulates
them through chat-memory message attributes, Spring AI through a session-scoped
index with eviction.
Prior art for the design is in commit 5ef1539bacbb (CAMEL-22851), in particular
{{ToolSearchTool}} and the searchable registry in {{CamelToolExecutorCache}}.
_Claude Code on behalf of Croway_
--
This message was sent by Atlassian Jira
(v8.20.10#820010)