This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch feature/CAMEL-23860-token-usage-headers
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 5f59c3785b16cb3846d8d82904d5974ddae46402
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Jul 1 09:56:57 2026 +0200

    CAMEL-23860: Add token usage and finish reason headers to langchain4j chat 
and tools
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../camel/catalog/components/langchain4j-chat.json |  6 +-
 .../catalog/components/langchain4j-tools.json      |  6 ++
 .../langchain4j/chat/langchain4j-chat.json         |  6 +-
 .../langchain4j/chat/LangChain4jChatHeaders.java   | 12 ++++
 .../langchain4j/chat/LangChain4jChatProducer.java  | 25 ++++++-
 .../langchain4j/tools/langchain4j-tools.json       |  6 ++
 .../tools/LangChain4jToolsEndpoint.java            |  3 +-
 .../tools/LangChain4jToolsHeaders.java}            | 19 ++++--
 .../tools/LangChain4jToolsProducer.java            | 56 +++++++++++++---
 .../builder/endpoint/EndpointHeaderBuilders.java   | 13 ++++
 .../dsl/LangChain4jChatEndpointBuilderFactory.java | 52 +++++++++++++++
 .../LangChain4jToolsEndpointBuilderFactory.java    | 76 ++++++++++++++++++++++
 12 files changed, 260 insertions(+), 20 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-chat.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-chat.json
index c0c6529cfcee..904654d2fc07 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-chat.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-chat.json
@@ -32,7 +32,11 @@
   },
   "headers": {
     "CamelLangChain4jChatPromptTemplate": { "index": 0, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The prompt Template.", "constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#PROMPT_TEMPLATE"
 },
-    "CamelLangChain4jChatAugmentedData": { "index": 1, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Augmented Data for RAG", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#AUGMENTED_DATA"
 }
+    "CamelLangChain4jChatAugmentedData": { "index": 1, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Augmented Data for RAG", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#AUGMENTED_DATA"
 },
+    "CamelLangChain4jChatFinishReason": { "index": 2, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "dev.langchain4j.model.output.FinishReason", "enum": [ "STOP", 
"LENGTH", "TOOL_EXECUTION", "CONTENT_FILTER", "OTHER" ], "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
Finish Reason.", "constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#FINISH_REASON"
 },
+    "CamelLangChain4jChatInputTokenCount": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Input Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#INPUT_TOKEN_COUNT"
 },
+    "CamelLangChain4jChatOutputTokenCount": { "index": 4, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Output Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#OUTPUT_TOKEN_COUNT"
 },
+    "CamelLangChain4jChatTotalTokenCount": { "index": 5, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Total Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#TOTAL_TOKEN_COUNT"
 }
   },
   "properties": {
     "chatId": { "index": 0, "kind": "path", "displayName": "Chat Id", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The id" },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-tools.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-tools.json
index 8d877c5db54f..6cb564042d3d 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-tools.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-tools.json
@@ -30,6 +30,12 @@
     "autowiredEnabled": { "index": 3, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
     "chatModel": { "index": 4, "kind": "property", "displayName": "Chat 
Model", "group": "advanced", "label": "advanced", "required": false, "type": 
"object", "javaType": "dev.langchain4j.model.chat.ChatModel", "deprecated": 
false, "deprecationNote": "", "autowired": true, "secret": false, 
"configurationClass": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsConfiguration", 
"configurationField": "configuration", "description": "Chat Model of type 
dev.langchain4j.model.chat. [...]
   },
+  "headers": {
+    "CamelLangChain4jToolsFinishReason": { "index": 0, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "dev.langchain4j.model.output.FinishReason", "enum": [ "STOP", 
"LENGTH", "TOOL_EXECUTION", "CONTENT_FILTER", "OTHER" ], "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
Finish Reason.", "constantName": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#FINISH_REASON"
 },
+    "CamelLangChain4jToolsInputTokenCount": { "index": 1, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Input Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#INPUT_TOKEN_COUNT"
 },
+    "CamelLangChain4jToolsOutputTokenCount": { "index": 2, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Output Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#OUTPUT_TOKEN_COUNT"
 },
+    "CamelLangChain4jToolsTotalTokenCount": { "index": 3, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Total Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#TOTAL_TOKEN_COUNT"
 }
+  },
   "properties": {
     "toolId": { "index": 0, "kind": "path", "displayName": "Tool Id", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The tool id" },
     "tags": { "index": 1, "kind": "parameter", "displayName": "Tags", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The tags for the tools" },
diff --git 
a/components/camel-ai/camel-langchain4j-chat/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/chat/langchain4j-chat.json
 
b/components/camel-ai/camel-langchain4j-chat/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/chat/langchain4j-chat.json
index c0c6529cfcee..904654d2fc07 100644
--- 
a/components/camel-ai/camel-langchain4j-chat/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/chat/langchain4j-chat.json
+++ 
b/components/camel-ai/camel-langchain4j-chat/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/chat/langchain4j-chat.json
@@ -32,7 +32,11 @@
   },
   "headers": {
     "CamelLangChain4jChatPromptTemplate": { "index": 0, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The prompt Template.", "constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#PROMPT_TEMPLATE"
 },
-    "CamelLangChain4jChatAugmentedData": { "index": 1, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Augmented Data for RAG", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#AUGMENTED_DATA"
 }
+    "CamelLangChain4jChatAugmentedData": { "index": 1, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Augmented Data for RAG", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#AUGMENTED_DATA"
 },
+    "CamelLangChain4jChatFinishReason": { "index": 2, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "dev.langchain4j.model.output.FinishReason", "enum": [ "STOP", 
"LENGTH", "TOOL_EXECUTION", "CONTENT_FILTER", "OTHER" ], "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
Finish Reason.", "constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#FINISH_REASON"
 },
+    "CamelLangChain4jChatInputTokenCount": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Input Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#INPUT_TOKEN_COUNT"
 },
+    "CamelLangChain4jChatOutputTokenCount": { "index": 4, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Output Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#OUTPUT_TOKEN_COUNT"
 },
+    "CamelLangChain4jChatTotalTokenCount": { "index": 5, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Total Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#TOTAL_TOKEN_COUNT"
 }
   },
   "properties": {
     "chatId": { "index": 0, "kind": "path", "displayName": "Chat Id", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The id" },
diff --git 
a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatHeaders.java
 
b/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatHeaders.java
index 18082bc4cebe..cf4a556f3854 100644
--- 
a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatHeaders.java
+++ 
b/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatHeaders.java
@@ -24,4 +24,16 @@ public class LangChain4jChatHeaders {
 
     @Metadata(description = "Augmented Data for RAG", javaType = "String")
     public static final String AUGMENTED_DATA = 
"CamelLangChain4jChatAugmentedData";
+
+    @Metadata(description = "The Finish Reason.", javaType = 
"dev.langchain4j.model.output.FinishReason")
+    public static final String FINISH_REASON = 
"CamelLangChain4jChatFinishReason";
+
+    @Metadata(description = "The Input Token Count.", javaType = "int")
+    public static final String INPUT_TOKEN_COUNT = 
"CamelLangChain4jChatInputTokenCount";
+
+    @Metadata(description = "The Output Token Count.", javaType = "int")
+    public static final String OUTPUT_TOKEN_COUNT = 
"CamelLangChain4jChatOutputTokenCount";
+
+    @Metadata(description = "The Total Token Count.", javaType = "int")
+    public static final String TOTAL_TOKEN_COUNT = 
"CamelLangChain4jChatTotalTokenCount";
 }
diff --git 
a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatProducer.java
 
b/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatProducer.java
index 05f786937df5..5a66fd569add 100644
--- 
a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatProducer.java
+++ 
b/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatProducer.java
@@ -24,6 +24,7 @@ import dev.langchain4j.data.message.AiMessage;
 import dev.langchain4j.data.message.ChatMessage;
 import dev.langchain4j.data.message.UserMessage;
 import dev.langchain4j.model.chat.ChatModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
 import dev.langchain4j.model.input.Prompt;
 import dev.langchain4j.model.input.PromptTemplate;
 import dev.langchain4j.rag.content.Content;
@@ -31,6 +32,7 @@ import dev.langchain4j.rag.content.injector.ContentInjector;
 import dev.langchain4j.rag.content.injector.DefaultContentInjector;
 import org.apache.camel.Exchange;
 import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.Message;
 import org.apache.camel.NoSuchHeaderException;
 import org.apache.camel.support.DefaultProducer;
 import org.apache.camel.util.ObjectHelper;
@@ -110,6 +112,20 @@ public class LangChain4jChatProducer extends 
DefaultProducer {
         exchange.getMessage().setBody(response);
     }
 
+    private void populateTokenUsageHeaders(ChatResponse chatResponse, Exchange 
exchange) {
+        Message message = exchange.getMessage();
+
+        if (chatResponse.finishReason() != null) {
+            message.setHeader(LangChain4jChatHeaders.FINISH_REASON, 
chatResponse.finishReason());
+        }
+
+        if (chatResponse.tokenUsage() != null) {
+            message.setHeader(LangChain4jChatHeaders.INPUT_TOKEN_COUNT, 
chatResponse.tokenUsage().inputTokenCount());
+            message.setHeader(LangChain4jChatHeaders.OUTPUT_TOKEN_COUNT, 
chatResponse.tokenUsage().outputTokenCount());
+            message.setHeader(LangChain4jChatHeaders.TOTAL_TOKEN_COUNT, 
chatResponse.tokenUsage().totalTokenCount());
+        }
+    }
+
     /**
      * Send a ChatMessage
      *
@@ -119,8 +135,9 @@ public class LangChain4jChatProducer extends 
DefaultProducer {
     private String sendChatMessage(ChatMessage chatMessage, Exchange exchange) 
{
         var augmentedChatMessage = addAugmentedData(chatMessage, exchange);
 
-        AiMessage response = 
this.chatModel.chat(augmentedChatMessage).aiMessage();
-        return extractAiResponse(response);
+        ChatResponse chatResponse = this.chatModel.chat(augmentedChatMessage);
+        populateTokenUsageHeaders(chatResponse, exchange);
+        return extractAiResponse(chatResponse.aiMessage());
     }
 
     /**
@@ -165,7 +182,9 @@ public class LangChain4jChatProducer extends 
DefaultProducer {
 
         }
 
-        response = this.chatModel.chat(chatMessages).aiMessage();
+        ChatResponse chatResponse = this.chatModel.chat(chatMessages);
+        populateTokenUsageHeaders(chatResponse, exchange);
+        response = chatResponse.aiMessage();
         return extractAiResponse(response);
     }
 
diff --git 
a/components/camel-ai/camel-langchain4j-tools/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/tools/langchain4j-tools.json
 
b/components/camel-ai/camel-langchain4j-tools/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/tools/langchain4j-tools.json
index 8d877c5db54f..6cb564042d3d 100644
--- 
a/components/camel-ai/camel-langchain4j-tools/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/tools/langchain4j-tools.json
+++ 
b/components/camel-ai/camel-langchain4j-tools/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/tools/langchain4j-tools.json
@@ -30,6 +30,12 @@
     "autowiredEnabled": { "index": 3, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
     "chatModel": { "index": 4, "kind": "property", "displayName": "Chat 
Model", "group": "advanced", "label": "advanced", "required": false, "type": 
"object", "javaType": "dev.langchain4j.model.chat.ChatModel", "deprecated": 
false, "deprecationNote": "", "autowired": true, "secret": false, 
"configurationClass": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsConfiguration", 
"configurationField": "configuration", "description": "Chat Model of type 
dev.langchain4j.model.chat. [...]
   },
+  "headers": {
+    "CamelLangChain4jToolsFinishReason": { "index": 0, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "dev.langchain4j.model.output.FinishReason", "enum": [ "STOP", 
"LENGTH", "TOOL_EXECUTION", "CONTENT_FILTER", "OTHER" ], "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
Finish Reason.", "constantName": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#FINISH_REASON"
 },
+    "CamelLangChain4jToolsInputTokenCount": { "index": 1, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Input Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#INPUT_TOKEN_COUNT"
 },
+    "CamelLangChain4jToolsOutputTokenCount": { "index": 2, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Output Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#OUTPUT_TOKEN_COUNT"
 },
+    "CamelLangChain4jToolsTotalTokenCount": { "index": 3, "kind": "header", 
"displayName": "", "group": "common", "label": "", "required": false, 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Total Token Count.", 
"constantName": 
"org.apache.camel.component.langchain4j.tools.LangChain4jToolsHeaders#TOTAL_TOKEN_COUNT"
 }
+  },
   "properties": {
     "toolId": { "index": 0, "kind": "path", "displayName": "Tool Id", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The tool id" },
     "tags": { "index": 1, "kind": "parameter", "displayName": "Tags", "group": 
"common", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The tags for the tools" },
diff --git 
a/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsEndpoint.java
 
b/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsEndpoint.java
index e2e4cbd68146..70e4ba176255 100644
--- 
a/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsEndpoint.java
+++ 
b/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsEndpoint.java
@@ -51,7 +51,8 @@ import static 
org.apache.camel.component.langchain4j.tools.LangChain4jTools.SCHE
 @UriEndpoint(firstVersion = "4.8.0", scheme = SCHEME,
              title = "LangChain4j Tools",
              syntax = "langchain4j-tools:toolId",
-             category = { Category.AI })
+             category = { Category.AI },
+             headersClass = LangChain4jToolsHeaders.class)
 public class LangChain4jToolsEndpoint extends DefaultEndpoint {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(LangChain4jToolsEndpoint.class);
diff --git 
a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatHeaders.java
 
b/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsHeaders.java
similarity index 52%
copy from 
components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatHeaders.java
copy to 
components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsHeaders.java
index 18082bc4cebe..0c691ef2a4a9 100644
--- 
a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatHeaders.java
+++ 
b/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsHeaders.java
@@ -14,14 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.component.langchain4j.chat;
+package org.apache.camel.component.langchain4j.tools;
 
 import org.apache.camel.spi.Metadata;
 
-public class LangChain4jChatHeaders {
-    @Metadata(description = "The prompt Template.", javaType = "String")
-    public static final String PROMPT_TEMPLATE = 
"CamelLangChain4jChatPromptTemplate";
+public class LangChain4jToolsHeaders {
 
-    @Metadata(description = "Augmented Data for RAG", javaType = "String")
-    public static final String AUGMENTED_DATA = 
"CamelLangChain4jChatAugmentedData";
+    @Metadata(description = "The Finish Reason.", javaType = 
"dev.langchain4j.model.output.FinishReason")
+    public static final String FINISH_REASON = 
"CamelLangChain4jToolsFinishReason";
+
+    @Metadata(description = "The Input Token Count.", javaType = "int")
+    public static final String INPUT_TOKEN_COUNT = 
"CamelLangChain4jToolsInputTokenCount";
+
+    @Metadata(description = "The Output Token Count.", javaType = "int")
+    public static final String OUTPUT_TOKEN_COUNT = 
"CamelLangChain4jToolsOutputTokenCount";
+
+    @Metadata(description = "The Total Token Count.", javaType = "int")
+    public static final String TOTAL_TOKEN_COUNT = 
"CamelLangChain4jToolsTotalTokenCount";
 }
diff --git 
a/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsProducer.java
 
b/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsProducer.java
index f49ac949559c..b921fe4c5370 100644
--- 
a/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsProducer.java
+++ 
b/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsProducer.java
@@ -40,8 +40,10 @@ import 
dev.langchain4j.model.chat.request.json.JsonStringSchema;
 import dev.langchain4j.model.chat.response.ChatResponse;
 import dev.langchain4j.model.output.FinishReason;
 import dev.langchain4j.model.output.Response;
+import dev.langchain4j.model.output.TokenUsage;
 import org.apache.camel.Exchange;
 import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.Message;
 import org.apache.camel.TypeConverter;
 import 
org.apache.camel.component.langchain4j.tools.spec.CamelToolExecutorCache;
 import 
org.apache.camel.component.langchain4j.tools.spec.CamelToolSpecification;
@@ -122,12 +124,37 @@ public class LangChain4jToolsProducer extends 
DefaultProducer {
 
         final Exchange baseline = ExchangeHelper.createCopy(exchange, true);
 
+        int totalInputTokens = 0;
+        int totalOutputTokens = 0;
+        int totalTokens = 0;
+        FinishReason lastFinishReason = null;
+
         // First talk to the model to get the tools to be called
         int i = 0;
         do {
             LOG.debug("Starting iteration {}", i);
-            final Response<AiMessage> response = chatWithLLM(chatMessages, 
toolPair, exchange);
+            final ChatResponse chatResponse = chatWithLLM(chatMessages, 
toolPair, exchange);
+
+            // Accumulate token usage across iterations
+            if (chatResponse.tokenUsage() != null) {
+                TokenUsage usage = chatResponse.tokenUsage();
+                if (usage.inputTokenCount() != null) {
+                    totalInputTokens += usage.inputTokenCount();
+                }
+                if (usage.outputTokenCount() != null) {
+                    totalOutputTokens += usage.outputTokenCount();
+                }
+                if (usage.totalTokenCount() != null) {
+                    totalTokens += usage.totalTokenCount();
+                }
+            }
+            if (chatResponse.finishReason() != null) {
+                lastFinishReason = chatResponse.finishReason();
+            }
+
+            final Response<AiMessage> response = 
Response.from(chatResponse.aiMessage());
             if (isDoneExecuting(response)) {
+                populateTokenUsageHeaders(lastFinishReason, totalInputTokens, 
totalOutputTokens, totalTokens, exchange);
                 return extractAiResponse(response);
             }
 
@@ -138,6 +165,21 @@ public class LangChain4jToolsProducer extends 
DefaultProducer {
         } while (true);
     }
 
+    private void populateTokenUsageHeaders(
+            FinishReason finishReason, int inputTokens, int outputTokens, int 
totalTokens, Exchange exchange) {
+        Message message = exchange.getMessage();
+
+        if (finishReason != null) {
+            message.setHeader(LangChain4jToolsHeaders.FINISH_REASON, 
finishReason);
+        }
+
+        if (inputTokens > 0 || outputTokens > 0 || totalTokens > 0) {
+            message.setHeader(LangChain4jToolsHeaders.INPUT_TOKEN_COUNT, 
inputTokens);
+            message.setHeader(LangChain4jToolsHeaders.OUTPUT_TOKEN_COUNT, 
outputTokens);
+            message.setHeader(LangChain4jToolsHeaders.TOTAL_TOKEN_COUNT, 
totalTokens);
+        }
+    }
+
     private boolean isDoneExecuting(Response<AiMessage> response) {
         if (!response.content().hasToolExecutionRequests()) {
             LOG.info("Finished executing tools because of there are no more 
execution requests");
@@ -297,7 +339,7 @@ public class LangChain4jToolsProducer extends 
DefaultProducer {
      * @param  toolPair     the toolPair containing the available tools to be 
called
      * @return              the response provided by the model
      */
-    private Response<AiMessage> chatWithLLM(List<ChatMessage> chatMessages, 
ToolPair toolPair, Exchange exchange) {
+    private ChatResponse chatWithLLM(List<ChatMessage> chatMessages, ToolPair 
toolPair, Exchange exchange) {
 
         ChatRequest.Builder requestBuilder = ChatRequest.builder()
                 .messages(chatMessages);
@@ -313,17 +355,15 @@ public class LangChain4jToolsProducer extends 
DefaultProducer {
         // generate response
         ChatResponse chatResponse = this.chatModel.chat(chatRequest);
 
-        // Convert ChatResponse to Response<AiMessage> for compatibility
         AiMessage aiMessage = chatResponse.aiMessage();
-        Response<AiMessage> response = Response.from(aiMessage);
 
-        if (!response.content().hasToolExecutionRequests()) {
+        if (!aiMessage.hasToolExecutionRequests()) {
             
exchange.getMessage().setHeader(LangChain4jTools.NO_TOOLS_CALLED_HEADER, 
Boolean.TRUE);
-            return response;
+            return chatResponse;
         }
 
-        chatMessages.add(response.content());
-        return response;
+        chatMessages.add(aiMessage);
+        return chatResponse;
     }
 
     /**
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
index 23b20b4a5056..9478d6a92b8b 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
@@ -2573,6 +2573,19 @@ public class EndpointHeaderBuilders {
     public static 
LangChain4jEmbeddingStoreEndpointBuilderFactory.LangChain4jEmbeddingStoreHeaderNameBuilder
 langchain4jEmbeddingstore() {
         return 
LangChain4jEmbeddingStoreEndpointBuilderFactory.LangChain4jEmbeddingStoreHeaderNameBuilder.INSTANCE;
     }
+    /**
+     * LangChain4j Tools (camel-langchain4j-tools)
+     * LangChain4j Tools and Function Calling Features
+     * 
+     * Category: ai
+     * Since: 4.8
+     * Maven coordinates: org.apache.camel:camel-langchain4j-tools
+     * 
+     * @return the dsl builder for the headers' name.
+     */
+    public static 
LangChain4jToolsEndpointBuilderFactory.LangChain4jToolsHeaderNameBuilder 
langchain4jTools() {
+        return 
LangChain4jToolsEndpointBuilderFactory.LangChain4jToolsHeaderNameBuilder.INSTANCE;
+    }
     /**
      * Language (camel-language)
      * Execute scripts in any of the languages supported by Camel.
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jChatEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jChatEndpointBuilderFactory.java
index ac2e93dad51e..6a3aa17f05de 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jChatEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jChatEndpointBuilderFactory.java
@@ -262,6 +262,58 @@ public interface LangChain4jChatEndpointBuilderFactory {
         public String langChain4jChatAugmentedData() {
             return "CamelLangChain4jChatAugmentedData";
         }
+        /**
+         * The Finish Reason.
+         * 
+         * The option is a: {@code dev.langchain4j.model.output.FinishReason}
+         * type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code LangChain4jChatFinishReason}.
+         */
+        public String langChain4jChatFinishReason() {
+            return "CamelLangChain4jChatFinishReason";
+        }
+        /**
+         * The Input Token Count.
+         * 
+         * The option is a: {@code int} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code
+         * LangChain4jChatInputTokenCount}.
+         */
+        public String langChain4jChatInputTokenCount() {
+            return "CamelLangChain4jChatInputTokenCount";
+        }
+        /**
+         * The Output Token Count.
+         * 
+         * The option is a: {@code int} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code
+         * LangChain4jChatOutputTokenCount}.
+         */
+        public String langChain4jChatOutputTokenCount() {
+            return "CamelLangChain4jChatOutputTokenCount";
+        }
+        /**
+         * The Total Token Count.
+         * 
+         * The option is a: {@code int} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code
+         * LangChain4jChatTotalTokenCount}.
+         */
+        public String langChain4jChatTotalTokenCount() {
+            return "CamelLangChain4jChatTotalTokenCount";
+        }
     }
     static LangChain4jChatEndpointBuilder endpointBuilder(String 
componentName, String path) {
         class LangChain4jChatEndpointBuilderImpl extends 
AbstractEndpointBuilder implements LangChain4jChatEndpointBuilder, 
AdvancedLangChain4jChatEndpointBuilder {
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jToolsEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jToolsEndpointBuilderFactory.java
index 969d5c8d49bd..f53dd7e54b32 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jToolsEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jToolsEndpointBuilderFactory.java
@@ -546,6 +546,19 @@ public interface LangChain4jToolsEndpointBuilderFactory {
     }
 
     public interface LangChain4jToolsBuilders {
+        /**
+         * LangChain4j Tools (camel-langchain4j-tools)
+         * LangChain4j Tools and Function Calling Features
+         * 
+         * Category: ai
+         * Since: 4.8
+         * Maven coordinates: org.apache.camel:camel-langchain4j-tools
+         * 
+         * @return the dsl builder for the headers' name.
+         */
+        default LangChain4jToolsHeaderNameBuilder langchain4jTools() {
+            return LangChain4jToolsHeaderNameBuilder.INSTANCE;
+        }
         /**
          * LangChain4j Tools (camel-langchain4j-tools)
          * LangChain4j Tools and Function Calling Features
@@ -588,6 +601,69 @@ public interface LangChain4jToolsEndpointBuilderFactory {
         }
 
     }
+    /**
+     * The builder of headers' name for the LangChain4j Tools component.
+     */
+    public static class LangChain4jToolsHeaderNameBuilder {
+        /**
+         * The internal instance of the builder used to access to all the
+         * methods representing the name of headers.
+         */
+        public static final LangChain4jToolsHeaderNameBuilder INSTANCE = new 
LangChain4jToolsHeaderNameBuilder();
+
+        /**
+         * The Finish Reason.
+         * 
+         * The option is a: {@code dev.langchain4j.model.output.FinishReason}
+         * type.
+         * 
+         * Group: common
+         * 
+         * @return the name of the header {@code LangChain4jToolsFinishReason}.
+         */
+        public String langChain4jToolsFinishReason() {
+            return "CamelLangChain4jToolsFinishReason";
+        }
+        /**
+         * The Input Token Count.
+         * 
+         * The option is a: {@code int} type.
+         * 
+         * Group: common
+         * 
+         * @return the name of the header {@code
+         * LangChain4jToolsInputTokenCount}.
+         */
+        public String langChain4jToolsInputTokenCount() {
+            return "CamelLangChain4jToolsInputTokenCount";
+        }
+        /**
+         * The Output Token Count.
+         * 
+         * The option is a: {@code int} type.
+         * 
+         * Group: common
+         * 
+         * @return the name of the header {@code
+         * LangChain4jToolsOutputTokenCount}.
+         */
+        public String langChain4jToolsOutputTokenCount() {
+            return "CamelLangChain4jToolsOutputTokenCount";
+        }
+        /**
+         * The Total Token Count.
+         * 
+         * The option is a: {@code int} type.
+         * 
+         * Group: common
+         * 
+         * @return the name of the header {@code
+         * LangChain4jToolsTotalTokenCount}.
+         */
+        public String langChain4jToolsTotalTokenCount() {
+            return "CamelLangChain4jToolsTotalTokenCount";
+        }
+    }
     static LangChain4jToolsEndpointBuilder endpointBuilder(String 
componentName, String path) {
         class LangChain4jToolsEndpointBuilderImpl extends 
AbstractEndpointBuilder implements LangChain4jToolsEndpointBuilder, 
AdvancedLangChain4jToolsEndpointBuilder {
             public LangChain4jToolsEndpointBuilderImpl(String path) {


Reply via email to