CAMEL-24322: Add tool-calling support via AiToolRegistry - #25289
Conversation
Extend the camel-openai component to discover and execute Camel route tools registered via the shared AiToolRegistry, alongside existing MCP tools. This implements Step 6 of the unified AI tool abstraction design (CAMEL-23382). Changes: - Add camel-ai-tool compile dependency to camel-openai - Add 'tags' configuration parameter to OpenAIConfiguration for filtering tools by tag from the shared AiToolRegistry - Create AiToolSpecToOpenAI converter that transforms AiToolSpec into OpenAI ChatCompletionFunctionTool using parametersJsonSchema - Extend OpenAIProducer to discover Camel route tools and dispatch them via AiToolExecutor in the agentic loop, with exchange isolation - Extend OpenAIToolExecutionProducer similarly for manual tool loops - Add AiToolSpecToOpenAITest with 8 test cases covering full spec, no params, no description, default type, required arrays, empty schema, invalid schema, and additionalProperties:false - Update error messages to reference generic "tool source" instead of MCP-specific wording Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet
left a comment
There was a problem hiding this comment.
Well-structured integration of AiToolRegistry into the OpenAI component with good converter test coverage and correct backward compatibility. Five observations — two about code quality, three about documentation/security polish.
Additional observations (on lines not in the diff):
-
Stale descriptions in
OpenAIConfiguration.java:toolExecutionErrorStrategy(line 219) says "Strategy for handling exceptions thrown during MCP tool execution" but now also governs Camel route tool errors. Similarly,hallucinatedToolNameStrategy(line 230) says "tool not found in any MCP server" — the runtime error message was correctly updated to "tool source" but the annotations weren't. Both descriptions and the catalog JSON should be updated. -
Stale class Javadoc in
OpenAIToolExecutionProducer.java(line 48): Still says "Producer that executes MCP tool calls" — should be updated to reflect that this now handles both MCP and Camel route tools.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of @gnodet
|
|
||
| int maxIterations = config.getMaxToolIterations(); | ||
|
|
||
| Set<String> availableToolNames = new java.util.LinkedHashSet<>(); |
There was a problem hiding this comment.
FQCN violation: new java.util.LinkedHashSet<>() should use the simple class name with an import. The project convention states: "Do NOT use fully qualified class names in Java code." Note that OpenAIToolExecutionProducer in this same PR correctly imports java.util.LinkedHashSet.
| Set<String> availableToolNames = new java.util.LinkedHashSet<>(); | |
| Set<String> availableToolNames = new LinkedHashSet<>(); |
(Also add import java.util.LinkedHashSet; alongside the existing import java.util.LinkedHashMap;)
| @@ -633,6 +671,89 @@ private void processNonStreamingAgentic( | |||
| "Max tool iterations (%d) exceeded. Tools called: %s".formatted(maxIterations, toolCallsLog)); | |||
There was a problem hiding this comment.
Code duplication: discoverCamelRouteTools(), executeCamelRouteTool(), and the result-handling logic are duplicated nearly verbatim between OpenAIProducer and OpenAIToolExecutionProducer (~80 lines each). The duplication is slightly inconsistent — this class extracts result handling into handleCamelToolResult(), while OpenAIToolExecutionProducer inlines the same logic.
Consider extracting the shared code into a package-private helper class (similar to how AiToolSpecToOpenAI is already a shared utility).
| throw e; | ||
| } | ||
| LOG.warn("Camel route tool '{}' execution failed: {}", spec.getName(), e.getMessage(), e); | ||
| return "Error: Tool execution failed: " + e.getMessage(); |
There was a problem hiding this comment.
Security nit: The AiToolResult Javadoc warns: "Framework adapters MUST NOT return [ExecutionError.message()] verbatim to the LLM without sanitization." The handleCamelToolResult() method correctly returns the generic "Error: Tool execution failed" for ExecutionError, but this outer catch returns e.getMessage() which could include internal details. Consider using the same sanitized message:
| return "Error: Tool execution failed: " + e.getMessage(); | |
| return "Error: Tool execution failed"; |
The same pattern applies to OpenAIToolExecutionProducer at line 291.
Summary
Claude Code on behalf of gnodet
Extends the
camel-openaicomponent to discover and execute Camel route tools registered via the sharedAiToolRegistry, alongside existing MCP tools. This implements Step 6 of the unified AI tool abstraction design (CAMEL-23382).Route authors can now expose Camel routes as AI tools via
ai-tool:consumer endpoints and have them automatically available to OpenAI models during function-calling loops — no MCP server required.Changes
camel-ai-toolcompile dependency tocamel-openaitagsparameter toOpenAIConfigurationfor filtering tools by tag from the sharedAiToolRegistryAiToolSpecToOpenAIthat transformsAiToolSpecinto OpenAIChatCompletionFunctionToolusingparametersJsonSchema(follows the same pattern asMcpToolConverter)AiToolRegistry.getOrCreate(context), convert them to OpenAI function tools, and dispatch viaAiToolExecutor.execute()with exchange isolation (ExchangeHelper.createCopy)AiToolSpecToOpenAITestcovering full spec conversion, no parameters, no description, default type, required arrays, empty schema, invalid schema, andadditionalProperties:falseUsage Example
Test Plan
OpenAIToolErrorStrategyTest)AiToolSpecToOpenAITesttests passmvn formatter:format impsort:sort🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com