davsclaus commented on code in PR #28295:
URL: https://github.com/apache/camel/pull/28295#discussion_r4348906047


##########
components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolExecutor.java:
##########
@@ -99,6 +116,7 @@ public static AiToolResult execute(AiToolSpec spec, 
Map<String, Object> argument
 
         // Defensive copy so callers cannot mutate arguments during route 
execution
         Map<String, Object> argsCopy = arguments != null ? new 
HashMap<>(arguments) : new HashMap<>();
+        Map<String, Object> bodyArguments = new HashMap<>(argsCopy);

Review Comment:
   (point 2) This copy is taken before the undeclared-argument filter, so the 
body gets arguments the schema forbids (`additionalProperties: false`) and the 
docs say are allowlisted away. Please build the body from `argsCopy` after 
filtering.



##########
components/camel-ai/camel-ai-tool/src/main/docs/ai-tool-component.adoc:
##########
@@ -289,6 +289,58 @@ Supported options: `title`, `readOnlyHint`, 
`destructiveHint`, `idempotentHint`,
 
 The `title` option maps to the MCP tool's top-level `title` field (not 
`ToolAnnotations.title`). Boolean hint options use nullable configuration: when 
unset, Camel omits them from the published MCP tool even though the component 
catalog may list `defaultValue: false` for documentation tooling.
 
+=== Tool Arguments in the Body
+
+By default, tool arguments are exposed as individual headers and the message 
body is left unchanged.
+Set `argumentsAsBody=true` to also populate the body with a JSON string 
containing the tool-call arguments.
+This is useful when mapping a complete JSON document, for example with Kaoto 
Data Mapper.
+
+[source,yaml]
+----
+- route:
+    from:
+      uri: ai-tool:place_order
+      parameters:
+        description: Place a merchandise order
+        argSchema: classpath:place-order.args.schema.json
+        argumentsAsBody: true
+      steps:
+        - to:
+            uri: direct:mapOrder
+----
+
+For a tool call with a customer name and two items, `direct:mapOrder` receives 
this JSON-string body:
+
+[source,json]
+----
+{
+  "customerName": "Alice",
+  "items": [
+    { "sku": "TSHIRT", "quantity": 2 },
+    { "sku": "MUG", "quantity": 1 }
+  ]
+}
+----
+
+Nested objects, arrays and JSON value types are preserved. A call with no 
arguments produces `{}`.
+The body includes undeclared arguments supplied by the model; individual 
headers still include only declared arguments.

Review Comment:
   (point 2) This conflicts with line 199 ("Camel always allowlists top-level 
property names when invoking the tool route") and with the JIRA's "accepted 
arguments".



##########
components/camel-ai/camel-langchain4j-agent/src/main/java/org/apache/camel/component/langchain4j/agent/LangChain4jAgentProducer.java:
##########
@@ -450,7 +450,8 @@ private void addToolToResult(
             // not leak into the calling producer exchange, while the caller's 
context (properties/variables) reaches
             // the tool route. Shared across the route-tool runtimes so they 
cannot drift (CAMEL-24832, CAMEL-23944).
             Exchange toolExchange = 
AiToolExecutor.createToolExchange(exchange);
-            AiToolResult result = AiToolExecutor.execute(spec, arguments, 
toolExchange);
+            AiToolResult result = AiToolExecutor.execute(spec, arguments, 
toolExchange,
+                    toolExecutionRequest.id(), memoryId != null ? 
memoryId.toString() : null);

Review Comment:
   (point 1) `memoryId` is `"default"` here, not null, when the agent has no 
memory: LangChain4j falls back to `ChatMemoryService.DEFAULT` when there is no 
`@MemoryId` parameter. Pass `null` unless the agent was built with memory. 
Comparing with `"default"` is not enough, because a user can pick that id on 
purpose.



##########
components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/McpToolCallExecutor.java:
##########
@@ -288,7 +288,7 @@ private ToolResult executeRouteTool(
             // exchange property) reaches the tool route; this is not a pooled 
consumer exchange, so it is not released
             // here (CAMEL-24832)
             Exchange toolExchange = 
AiToolExecutor.createToolExchange(callingExchange);
-            AiToolResult result = AiToolExecutor.execute(spec, argsMap, 
toolExchange);
+            AiToolResult result = AiToolExecutor.execute(spec, argsMap, 
toolExchange, toolCall.asFunction().id(), null);

Review Comment:
   (point 4, not blocking) The Responses API path through this executor has a 
conversation id (`CamelOpenAIConversationId` or the `conversationId` option). 
It could be passed here instead of `null`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to