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

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 985d04084726 CAMEL-24330: Add LLM integration guide for AI component 
documentation
985d04084726 is described below

commit 985d04084726a04181ce14daf3cd7a7a6e12990c
Author: Omar Atie <[email protected]>
AuthorDate: Mon Aug 3 22:07:00 2026 -0700

    CAMEL-24330: Add LLM integration guide for AI component documentation
    
    Add ai-llm-integration-guide.adoc covering component selection (OpenAI vs
    LangChain4j Chat vs Agent), structured output, temperature tuning, 
streaming/SSE,
    dynamic prompts, and prompt management. Enhance openai-component.adoc with
    production tips, dynamic prompt examples, and chat generation parameters.
    Cross-link from ai-summary, OpenAI, and LangChain4j Chat docs.
    
    Closes #25313
    
    Co-authored-by: Cursor <[email protected]>
---
 .../catalog/docs/langchain4j-chat-component.adoc   |   2 +
 .../camel/catalog/docs/openai-component.adoc       | 241 ++++++++++++++-
 .../src/main/docs/langchain4j-chat-component.adoc  |   2 +
 .../src/main/docs/openai-component.adoc            | 241 ++++++++++++++-
 .../src/main/docs/ai-llm-integration-guide.adoc    | 340 +++++++++++++++++++++
 components/camel-ai/src/main/docs/ai-summary.adoc  |  51 ++++
 docs/components/modules/ROOT/nav.adoc              |   1 +
 .../ROOT/pages/ai-llm-integration-guide.adoc       |   1 +
 .../maven/packaging/PrepareDocSymlinksMojo.java    |   6 +-
 9 files changed, 881 insertions(+), 4 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/langchain4j-chat-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/langchain4j-chat-component.adoc
index 50f9812ae7bb..c71b3d6e9d5d 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/langchain4j-chat-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/langchain4j-chat-component.adoc
@@ -16,6 +16,8 @@
 
 The LangChain4j Chat Component allows you to integrate with any Large Language 
Model (LLM) supported by 
https://github.com/langchain4j/langchain4j[LangChain4j].
 
+TIP: Not sure whether to use this component or 
xref:openai-component.adoc[OpenAI]? See the 
xref:ai-llm-integration-guide.adoc[LLM Integration Guide] decision matrix. If 
you need streaming responses, structured output (`outputClass` / `jsonSchema`), 
or MCP tool calling, see the xref:openai-component.adoc[OpenAI] component.
+
 Maven users will need to add the following dependency to their `pom.xml`
 for this component:
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/openai-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/openai-component.adoc
index d95cf54ce139..d2961f939c95 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/openai-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/openai-component.adoc
@@ -165,6 +165,8 @@ YAML::
 ----
 ====
 
+TIP: For component selection, structured extraction, streaming, and prompt 
management patterns, see the xref:ai-llm-integration-guide.adoc[LLM Integration 
Guide].
+
 === Basic Chat Completion with String Input
 
 [tabs]
@@ -210,6 +212,71 @@ YAML::
 ----
 ====
 
+=== Dynamic prompts per exchange
+
+The user prompt can change on every exchange. Set the body to the prompt text, 
or override with the `CamelOpenAIUserMessage` header (Simple expressions work):
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:score")
+    .setHeader("CamelOpenAIUserMessage", simple("Rate 1-10 for ${header.role}: 
${body}"))
+    .to("openai:chat-completion?model=gpt-4o-mini&temperature=0.2")
+    .log("${body}");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:score
+      steps:
+        - setHeader:
+            name: CamelOpenAIUserMessage
+            simple: "Rate 1-10 for ${header.role}: ${body}"
+        - to:
+            uri: openai:chat-completion
+            parameters:
+              model: gpt-4o-mini
+              temperature: 0.2
+----
+====
+
+=== Chat generation parameters
+
+Control randomness for chat completions with `temperature` (0.0–2.0) and 
`topP` (0.0–1.0). Low temperature (for example `0.1`) is recommended for 
structured JSON extraction.
+
+[tabs]
+====
+YAML::
++
+[source,yaml]
+----
+- to:
+    uri: openai:chat-completion
+    parameters:
+      model: gpt-4o-mini
+      temperature: 0.1
+      topP: 1.0
+----
+
+Java::
++
+[source,java]
+----
+.to("openai:chat-completion?model=gpt-4o-mini&temperature=0.1")
+----
+====
+
+Per-exchange overrides use headers: `CamelOpenAITemperature`, 
`CamelOpenAITopP`.
+
+For provider-specific request fields not exposed as URI options, use 
`additionalBodyProperty` (see 
xref:others:openai-providers.adoc[OpenAI-Compatible Providers]).
+
 === File-Backed Prompt with Text File
 
 [tabs]
@@ -395,7 +462,9 @@ When using image input, the userMessage is required. 
Supported image formats are
 
 === Streaming Response
 
-When `streaming=true`, the component returns an 
`Iterator<ChatCompletionChunk>` in the message body. You can consume this 
iterator using Camel's streaming EIPs or process it directly:
+When `streaming=true`, the component returns an 
`Iterator<ChatCompletionChunk>` in the message body. You can consume this 
iterator using Camel's streaming EIPs or process it directly.
+
+For Server-Sent Events to web clients (platform-http), structured extraction 
pipelines, and when to stream through Camel vs. a dedicated handler, see 
xref:ai-llm-integration-guide.adoc#_streaming_responses[LLM Integration Guide — 
Streaming responses].
 
 .Usage example:
 [source,yaml]
@@ -433,6 +502,8 @@ When `streaming=true`, the component returns an 
`Iterator<ChatCompletionChunk>`
 
 === Structured Output with outputClass
 
+TIP: For extraction tasks (resumes, invoices, classification), prefer 
`jsonSchema` or `outputClass` instead of hand-written JSON parsing. Use low 
`temperature` (0.0–0.2). See 
xref:ai-llm-integration-guide.adoc#_structured_output_recommended_for_extraction[LLM
 Integration Guide — Structured output].
+
 .When `outputClass` is set, the model is instructed to produce JSON matching 
the given class, but the component returns the raw String. Deserialize the body 
yourself (e.g., with Camel's Jackson) if you need a typed object.
 
 ._Java-only: uses Java class definition for `outputClass` schema_
@@ -1008,10 +1079,178 @@ String-valued fields are set directly. Non-string 
fields (numbers, booleans, obj
 
 NOTE: This maps fields from the response message's additional properties 
(fields not part of the standard schema). Standard response fields like 
`content`, `role`, and `tool_calls` are not accessible through this option.
 
+== Tips for Production Use
+
+This section covers practical advice for production routes. For component 
selection, streaming to browsers, and prompt management at scale, see the 
xref:ai-llm-integration-guide.adoc[LLM Integration Guide].
+
+=== Temperature and Model Parameters
+
+The `temperature` endpoint option controls how deterministic the model's 
output is. Lower values produce more consistent, predictable responses; higher 
values produce more varied, creative output.
+
+For structured extraction tasks (JSON parsing, data extraction, 
classification), use a low temperature such as `0.1` to reduce the chance of 
the model adding unexpected commentary or formatting around the structured 
output:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:extract-skills")
+    
.to("openai:chat-completion?temperature=0.1&outputClass=com.example.SkillList")
+    .log("Extracted: ${body}");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:extract-skills
+      steps:
+        - to:
+            uri: openai:chat-completion
+            parameters:
+              temperature: 0.1
+              outputClass: com.example.SkillList
+        - log:
+            message: "Extracted: ${body}"
+----
+====
+
+Temperature can also be set per-exchange via the `CamelOpenAITemperature` 
header. Other tuning options include `topP` (nucleus sampling) and `maxTokens` 
(response length limit).
+
+=== Dynamic Prompts
+
+The `CamelOpenAIUserMessage` header is evaluated per-exchange, so you can 
construct prompts dynamically using Camel's Simple language or any other 
expression:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:summarize")
+    .setHeader("CamelOpenAIUserMessage",
+        simple("Summarize this ${header.documentType} in 3 bullet points: 
${body}"))
+    .to("openai:chat-completion")
+    .log("Summary: ${body}");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:summarize
+      steps:
+        - setHeader:
+            name: CamelOpenAIUserMessage
+            simple: "Summarize this ${header.documentType} in 3 bullet points: 
${body}"
+        - to:
+            uri: openai:chat-completion
+        - log:
+            message: "Summary: ${body}"
+----
+====
+
+This is useful when chaining multiple enrichment steps where each step needs a 
different instruction based on the current exchange state.
+
+=== Use Structured Output for JSON Extraction
+
+When you need the model to return structured data (JSON objects, arrays, typed 
fields), prefer the built-in `outputClass` or `jsonSchema` options over 
manually parsing the model's text output. These options instruct the model to 
produce valid JSON matching your schema, which significantly reduces parsing 
failures:
+
+[source,java]
+----
+// Recommended — structured output handles JSON formatting:
+from("direct:extract")
+    .to("openai:chat-completion?outputClass=com.example.Skills")
+    .log("${body}");
+
+// Avoid — manual JSON parsing is fragile:
+from("direct:extract")
+    .setHeader("CamelOpenAIUserMessage",
+        constant("Extract skills as a JSON array. Respond with valid JSON 
only."))
+    .to("openai:chat-completion")
+    .process(exchange -> {
+        // This breaks when the model adds commentary around the JSON
+        String json = exchange.getIn().getBody(String.class);
+        List<String> skills = objectMapper.readValue(json, new 
TypeReference<>() {});
+        exchange.getIn().setBody(skills);
+    });
+----
+
+See <<_structured_output_with_outputclass>> and 
<<_structured_output_with_json_schema>> above for full examples. For additional 
validation, pipe the response through the 
xref:json-validator-component.adoc[JSON Validator] component.
+
+=== Handling Model Output Errors
+
+A successful HTTP 200 response from the model does not guarantee the content 
is usable. The model may ignore formatting instructions, return truncated 
output, or produce content that does not match your expected shape. These are 
not Camel exceptions — they appear as downstream parsing failures in your own 
processors.
+
+For production routes, add a lightweight validation step after the model call:
+
+[source,java]
+----
+from("direct:extract")
+    .to("openai:chat-completion?outputClass=com.example.Result")
+    .process(exchange -> {
+        String response = exchange.getIn().getBody(String.class);
+        if (response == null || response.isBlank()) {
+            throw new IllegalStateException("Empty model response");
+        }
+    })
+    .to("direct:downstream");
+----
+
+Using `outputClass` or `jsonSchema` already reduces this risk substantially by 
constraining the model's output format at the API level.
+
+=== Prompt Management
+
+When your project grows beyond a few routes, keeping prompt strings inline in 
route definitions becomes hard to maintain. Consider these approaches:
+
+*Load prompts from resource files:*
+
+[source,java]
+----
+from("direct:analyze")
+    .setHeader("CamelOpenAISystemMessage",
+        constant("resource:classpath:prompts/system-analyst.txt"))
+    .to("openai:chat-completion");
+----
+
+*Use Camel property placeholders for reusable fragments:*
+
+[source,properties]
+----
+# application.properties
+prompt.system.analyst=You are a technical analyst. Be concise and factual.
+prompt.output.json=Respond with valid JSON only, no commentary.
+----
+
+[source,java]
+----
+from("direct:analyze")
+    .setHeader("CamelOpenAISystemMessage", 
constant("{{prompt.system.analyst}}"))
+    .setHeader("CamelOpenAIUserMessage",
+        simple("{{prompt.output.json}} Analyze: ${body}"))
+    .to("openai:chat-completion");
+----
+
+TIP: For prompt templates with named variables (e.g., pass:c[`{{dishType}}`]), 
the xref:langchain4j-chat-component.adoc[LangChain4j Chat] component offers 
built-in template support via the `CHAT_SINGLE_MESSAGE_WITH_PROMPT` operation.
+
+=== Streaming Considerations
+
+The `streaming=true` option returns an `Iterator<ChatCompletionChunk>` that 
can be consumed with Camel's Split EIP (see <<_streaming_response>> above). 
This works well for pipeline-style processing where each chunk is handled as 
part of a longer integration flow.
+
+For user-facing scenarios that require Server-Sent Events (SSE) or WebSocket 
delivery to a browser, see 
xref:ai-llm-integration-guide.adoc#_streaming_responses[LLM Integration Guide — 
Streaming responses] for platform-http patterns and when to stream through 
Camel vs. a dedicated handler.
+
+NOTE: When MCP tools with `autoToolExecution` are active, streaming 
automatically falls back to non-streaming to allow the agentic tool-calling 
loop to function. See xref:others:openai-mcp.adoc[MCP Tool Calling] for details.
+
 == Sub-Pages
 
 For more details on specific features, see:
 
+* xref:ai-llm-integration-guide.adoc[LLM Integration Guide] - Choosing 
components, structured output, streaming, dynamic prompts
 * xref:others:openai-responses.adoc[Responses API operation] - OpenAI 
Responses API, hosted tools, and server-side conversation state
 * xref:others:openai-mcp.adoc[MCP Tool Calling] - Model Context Protocol 
server configuration, agentic loop, streaming, and connection recovery
 * xref:others:openai-providers.adoc[OpenAI-Compatible Providers] - Using 
Ollama, LM Studio, vLLM, and OpenRouter as alternative backends
diff --git 
a/components/camel-ai/camel-langchain4j-chat/src/main/docs/langchain4j-chat-component.adoc
 
b/components/camel-ai/camel-langchain4j-chat/src/main/docs/langchain4j-chat-component.adoc
index 50f9812ae7bb..c71b3d6e9d5d 100644
--- 
a/components/camel-ai/camel-langchain4j-chat/src/main/docs/langchain4j-chat-component.adoc
+++ 
b/components/camel-ai/camel-langchain4j-chat/src/main/docs/langchain4j-chat-component.adoc
@@ -16,6 +16,8 @@
 
 The LangChain4j Chat Component allows you to integrate with any Large Language 
Model (LLM) supported by 
https://github.com/langchain4j/langchain4j[LangChain4j].
 
+TIP: Not sure whether to use this component or 
xref:openai-component.adoc[OpenAI]? See the 
xref:ai-llm-integration-guide.adoc[LLM Integration Guide] decision matrix. If 
you need streaming responses, structured output (`outputClass` / `jsonSchema`), 
or MCP tool calling, see the xref:openai-component.adoc[OpenAI] component.
+
 Maven users will need to add the following dependency to their `pom.xml`
 for this component:
 
diff --git 
a/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc 
b/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc
index d95cf54ce139..d2961f939c95 100644
--- a/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc
+++ b/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc
@@ -165,6 +165,8 @@ YAML::
 ----
 ====
 
+TIP: For component selection, structured extraction, streaming, and prompt 
management patterns, see the xref:ai-llm-integration-guide.adoc[LLM Integration 
Guide].
+
 === Basic Chat Completion with String Input
 
 [tabs]
@@ -210,6 +212,71 @@ YAML::
 ----
 ====
 
+=== Dynamic prompts per exchange
+
+The user prompt can change on every exchange. Set the body to the prompt text, 
or override with the `CamelOpenAIUserMessage` header (Simple expressions work):
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:score")
+    .setHeader("CamelOpenAIUserMessage", simple("Rate 1-10 for ${header.role}: 
${body}"))
+    .to("openai:chat-completion?model=gpt-4o-mini&temperature=0.2")
+    .log("${body}");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:score
+      steps:
+        - setHeader:
+            name: CamelOpenAIUserMessage
+            simple: "Rate 1-10 for ${header.role}: ${body}"
+        - to:
+            uri: openai:chat-completion
+            parameters:
+              model: gpt-4o-mini
+              temperature: 0.2
+----
+====
+
+=== Chat generation parameters
+
+Control randomness for chat completions with `temperature` (0.0–2.0) and 
`topP` (0.0–1.0). Low temperature (for example `0.1`) is recommended for 
structured JSON extraction.
+
+[tabs]
+====
+YAML::
++
+[source,yaml]
+----
+- to:
+    uri: openai:chat-completion
+    parameters:
+      model: gpt-4o-mini
+      temperature: 0.1
+      topP: 1.0
+----
+
+Java::
++
+[source,java]
+----
+.to("openai:chat-completion?model=gpt-4o-mini&temperature=0.1")
+----
+====
+
+Per-exchange overrides use headers: `CamelOpenAITemperature`, 
`CamelOpenAITopP`.
+
+For provider-specific request fields not exposed as URI options, use 
`additionalBodyProperty` (see 
xref:others:openai-providers.adoc[OpenAI-Compatible Providers]).
+
 === File-Backed Prompt with Text File
 
 [tabs]
@@ -395,7 +462,9 @@ When using image input, the userMessage is required. 
Supported image formats are
 
 === Streaming Response
 
-When `streaming=true`, the component returns an 
`Iterator<ChatCompletionChunk>` in the message body. You can consume this 
iterator using Camel's streaming EIPs or process it directly:
+When `streaming=true`, the component returns an 
`Iterator<ChatCompletionChunk>` in the message body. You can consume this 
iterator using Camel's streaming EIPs or process it directly.
+
+For Server-Sent Events to web clients (platform-http), structured extraction 
pipelines, and when to stream through Camel vs. a dedicated handler, see 
xref:ai-llm-integration-guide.adoc#_streaming_responses[LLM Integration Guide — 
Streaming responses].
 
 .Usage example:
 [source,yaml]
@@ -433,6 +502,8 @@ When `streaming=true`, the component returns an 
`Iterator<ChatCompletionChunk>`
 
 === Structured Output with outputClass
 
+TIP: For extraction tasks (resumes, invoices, classification), prefer 
`jsonSchema` or `outputClass` instead of hand-written JSON parsing. Use low 
`temperature` (0.0–0.2). See 
xref:ai-llm-integration-guide.adoc#_structured_output_recommended_for_extraction[LLM
 Integration Guide — Structured output].
+
 .When `outputClass` is set, the model is instructed to produce JSON matching 
the given class, but the component returns the raw String. Deserialize the body 
yourself (e.g., with Camel's Jackson) if you need a typed object.
 
 ._Java-only: uses Java class definition for `outputClass` schema_
@@ -1008,10 +1079,178 @@ String-valued fields are set directly. Non-string 
fields (numbers, booleans, obj
 
 NOTE: This maps fields from the response message's additional properties 
(fields not part of the standard schema). Standard response fields like 
`content`, `role`, and `tool_calls` are not accessible through this option.
 
+== Tips for Production Use
+
+This section covers practical advice for production routes. For component 
selection, streaming to browsers, and prompt management at scale, see the 
xref:ai-llm-integration-guide.adoc[LLM Integration Guide].
+
+=== Temperature and Model Parameters
+
+The `temperature` endpoint option controls how deterministic the model's 
output is. Lower values produce more consistent, predictable responses; higher 
values produce more varied, creative output.
+
+For structured extraction tasks (JSON parsing, data extraction, 
classification), use a low temperature such as `0.1` to reduce the chance of 
the model adding unexpected commentary or formatting around the structured 
output:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:extract-skills")
+    
.to("openai:chat-completion?temperature=0.1&outputClass=com.example.SkillList")
+    .log("Extracted: ${body}");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:extract-skills
+      steps:
+        - to:
+            uri: openai:chat-completion
+            parameters:
+              temperature: 0.1
+              outputClass: com.example.SkillList
+        - log:
+            message: "Extracted: ${body}"
+----
+====
+
+Temperature can also be set per-exchange via the `CamelOpenAITemperature` 
header. Other tuning options include `topP` (nucleus sampling) and `maxTokens` 
(response length limit).
+
+=== Dynamic Prompts
+
+The `CamelOpenAIUserMessage` header is evaluated per-exchange, so you can 
construct prompts dynamically using Camel's Simple language or any other 
expression:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:summarize")
+    .setHeader("CamelOpenAIUserMessage",
+        simple("Summarize this ${header.documentType} in 3 bullet points: 
${body}"))
+    .to("openai:chat-completion")
+    .log("Summary: ${body}");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:summarize
+      steps:
+        - setHeader:
+            name: CamelOpenAIUserMessage
+            simple: "Summarize this ${header.documentType} in 3 bullet points: 
${body}"
+        - to:
+            uri: openai:chat-completion
+        - log:
+            message: "Summary: ${body}"
+----
+====
+
+This is useful when chaining multiple enrichment steps where each step needs a 
different instruction based on the current exchange state.
+
+=== Use Structured Output for JSON Extraction
+
+When you need the model to return structured data (JSON objects, arrays, typed 
fields), prefer the built-in `outputClass` or `jsonSchema` options over 
manually parsing the model's text output. These options instruct the model to 
produce valid JSON matching your schema, which significantly reduces parsing 
failures:
+
+[source,java]
+----
+// Recommended — structured output handles JSON formatting:
+from("direct:extract")
+    .to("openai:chat-completion?outputClass=com.example.Skills")
+    .log("${body}");
+
+// Avoid — manual JSON parsing is fragile:
+from("direct:extract")
+    .setHeader("CamelOpenAIUserMessage",
+        constant("Extract skills as a JSON array. Respond with valid JSON 
only."))
+    .to("openai:chat-completion")
+    .process(exchange -> {
+        // This breaks when the model adds commentary around the JSON
+        String json = exchange.getIn().getBody(String.class);
+        List<String> skills = objectMapper.readValue(json, new 
TypeReference<>() {});
+        exchange.getIn().setBody(skills);
+    });
+----
+
+See <<_structured_output_with_outputclass>> and 
<<_structured_output_with_json_schema>> above for full examples. For additional 
validation, pipe the response through the 
xref:json-validator-component.adoc[JSON Validator] component.
+
+=== Handling Model Output Errors
+
+A successful HTTP 200 response from the model does not guarantee the content 
is usable. The model may ignore formatting instructions, return truncated 
output, or produce content that does not match your expected shape. These are 
not Camel exceptions — they appear as downstream parsing failures in your own 
processors.
+
+For production routes, add a lightweight validation step after the model call:
+
+[source,java]
+----
+from("direct:extract")
+    .to("openai:chat-completion?outputClass=com.example.Result")
+    .process(exchange -> {
+        String response = exchange.getIn().getBody(String.class);
+        if (response == null || response.isBlank()) {
+            throw new IllegalStateException("Empty model response");
+        }
+    })
+    .to("direct:downstream");
+----
+
+Using `outputClass` or `jsonSchema` already reduces this risk substantially by 
constraining the model's output format at the API level.
+
+=== Prompt Management
+
+When your project grows beyond a few routes, keeping prompt strings inline in 
route definitions becomes hard to maintain. Consider these approaches:
+
+*Load prompts from resource files:*
+
+[source,java]
+----
+from("direct:analyze")
+    .setHeader("CamelOpenAISystemMessage",
+        constant("resource:classpath:prompts/system-analyst.txt"))
+    .to("openai:chat-completion");
+----
+
+*Use Camel property placeholders for reusable fragments:*
+
+[source,properties]
+----
+# application.properties
+prompt.system.analyst=You are a technical analyst. Be concise and factual.
+prompt.output.json=Respond with valid JSON only, no commentary.
+----
+
+[source,java]
+----
+from("direct:analyze")
+    .setHeader("CamelOpenAISystemMessage", 
constant("{{prompt.system.analyst}}"))
+    .setHeader("CamelOpenAIUserMessage",
+        simple("{{prompt.output.json}} Analyze: ${body}"))
+    .to("openai:chat-completion");
+----
+
+TIP: For prompt templates with named variables (e.g., pass:c[`{{dishType}}`]), 
the xref:langchain4j-chat-component.adoc[LangChain4j Chat] component offers 
built-in template support via the `CHAT_SINGLE_MESSAGE_WITH_PROMPT` operation.
+
+=== Streaming Considerations
+
+The `streaming=true` option returns an `Iterator<ChatCompletionChunk>` that 
can be consumed with Camel's Split EIP (see <<_streaming_response>> above). 
This works well for pipeline-style processing where each chunk is handled as 
part of a longer integration flow.
+
+For user-facing scenarios that require Server-Sent Events (SSE) or WebSocket 
delivery to a browser, see 
xref:ai-llm-integration-guide.adoc#_streaming_responses[LLM Integration Guide — 
Streaming responses] for platform-http patterns and when to stream through 
Camel vs. a dedicated handler.
+
+NOTE: When MCP tools with `autoToolExecution` are active, streaming 
automatically falls back to non-streaming to allow the agentic tool-calling 
loop to function. See xref:others:openai-mcp.adoc[MCP Tool Calling] for details.
+
 == Sub-Pages
 
 For more details on specific features, see:
 
+* xref:ai-llm-integration-guide.adoc[LLM Integration Guide] - Choosing 
components, structured output, streaming, dynamic prompts
 * xref:others:openai-responses.adoc[Responses API operation] - OpenAI 
Responses API, hosted tools, and server-side conversation state
 * xref:others:openai-mcp.adoc[MCP Tool Calling] - Model Context Protocol 
server configuration, agentic loop, streaming, and connection recovery
 * xref:others:openai-providers.adoc[OpenAI-Compatible Providers] - Using 
Ollama, LM Studio, vLLM, and OpenRouter as alternative backends
diff --git a/components/camel-ai/src/main/docs/ai-llm-integration-guide.adoc 
b/components/camel-ai/src/main/docs/ai-llm-integration-guide.adoc
new file mode 100644
index 000000000000..bc34d6ac43c4
--- /dev/null
+++ b/components/camel-ai/src/main/docs/ai-llm-integration-guide.adoc
@@ -0,0 +1,340 @@
+= LLM Integration Guide
+:doctitle: LLM Integration Guide
+:group: AI
+
+This guide helps you choose the right Camel AI component and apply common LLM 
integration patterns in production routes. It addresses practical gaps reported 
by users building document-processing and chat pipelines — structured 
extraction, streaming to browsers, dynamic prompts, and prompt management at 
scale.
+
+TIP: For a catalog of all AI components, start at xref:ai-summary.adoc[AI 
Components]. For coding-agent context about Camel itself, see 
https://camel.apache.org/llms.txt[llms.txt].
+
+== Choosing an AI component
+
+Camel ships several AI components. Each documents itself well in isolation, 
but picking the wrong one early leads to provider lock-in or missing features 
you need later.
+
+=== Decision matrix
+
+[cols="2,3,3",options="header"]
+|===
+| Use case | Recommended component | Why
+
+| OpenAI or OpenAI-compatible chat (Ollama, vLLM, LM Studio, OpenRouter, Azure 
OpenAI)
+| xref:openai-component.adoc[OpenAI]
+| Native OpenAI SDK integration, MCP tool calling, agentic loops, embeddings, 
audio, structured JSON output via `jsonSchema` / `outputClass`
+
+| Multi-provider chat without tying routes to one vendor
+| xref:langchain4j-chat-component.adoc[LangChain4j Chat]
+| Provider-agnostic `ChatModel` beans (OpenAI, Anthropic, Ollama, Vertex, and 
more via LangChain4j). Strong fit for RAG pipelines with 
xref:langchain4j-embeddingstore-component.adoc[Embedding Store] and content 
enricher
+
+| Autonomous agents with Camel route tools and/or MCP servers
+| xref:langchain4j-agent-component.adoc[LangChain4j Agent]
+| Multi-turn tool calling, guardrails, memory, concurrent tool execution. 
Complements xref:others:openai-mcp.adoc[MCP Tool Calling] for OpenAI-native 
agentic loops
+
+| Spring Boot + Spring AI stack
+| xref:spring-ai-chat-component.adoc[Spring AI Chat]
+| When the application already standardizes on Spring AI beans
+
+| Vector search / semantic retrieval only
+| xref:others:openai-operations.adoc[OpenAI embeddings] or 
xref:langchain4j-embeddings-component.adoc[LangChain4j Embeddings]
+| Generate embeddings, then store/query via 
xref:pgvector-component.adoc[PGVector], xref:milvus-component.adoc[Milvus], etc.
+|===
+
+=== OpenAI vs LangChain4j Chat — quick comparison
+
+*Choose xref:openai-component.adoc[OpenAI] when:*
+
+* You target the OpenAI API (or a compatible proxy) and want first-class MCP, 
Responses API, embeddings, and audio in one component
+* You need built-in conversation memory on the exchange, agentic tool loops, 
or OpenAI-specific response headers
+* Your team prefers configuring everything through Camel URI options and 
headers
+
+*Choose xref:langchain4j-chat-component.adoc[LangChain4j Chat] when:*
+
+* You may switch LLM providers (OpenAI today, Anthropic or local Ollama 
tomorrow) without rewriting routes
+* You orchestrate RAG with Camel EIPs (content enricher, split, aggregate) and 
LangChain4j `ChatModel` / `EmbeddingModel` beans
+* You use prompt templates with pass:c[`{{variable}}`] substitution (see 
<<prompt-templates>>)
+
+Both components can call the same underlying models. The difference is 
abstraction level and which advanced features (MCP, agent guardrails, Spring 
Boot starters) you need around the chat call.
+
+== Structured output (recommended for extraction)
+
+For tasks like resume parsing, invoice extraction, or classification, **do not 
hand-roll JSON parsing** in a follow-up processor unless you have a specific 
reason. The OpenAI component can constrain the model to return JSON matching a 
schema.
+
+=== JSON Schema (works in Java, XML, and YAML routes)
+
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:extract-resume
+      steps:
+        - setBody:
+            simple: "${body}"
+        - to:
+            uri: openai:chat-completion
+            parameters:
+              model: gpt-4o-mini
+              temperature: 0.1
+              jsonSchema: resource:classpath:schemas/resume.schema.json
+        - unmarshal:
+            json:
+              library: Jackson
+              unmarshalType: com.example.Resume
+----
+
+The `jsonSchema` option (or `CamelOpenAIJsonSchema` header) tells the model to 
emit JSON conforming to your schema. The response body is a JSON **string** — 
use Camel's Jackson data format or `json-validator` if you need typed objects 
or strict validation.
+
+See xref:openai-component.adoc#_structured_output_with_json_schema[Structured 
Output with JSON Schema] for header-based and inline schema examples.
+
+=== Java classes (Java DSL only)
+
+When running Java routes, `outputClass` derives the schema from a POJO:
+
+[source,java]
+----
+from("direct:extract-person")
+    .setBody(constant("Generate a software engineer profile"))
+    .to("openai:chat-completion?outputClass=com.example.Person")
+    .unmarshal().json(JsonLibrary.Jackson, Person.class);
+----
+
+=== Tips for reliable structured extraction
+
+* Set a **low temperature** (0.0–0.2) — see <<generation-parameters>>
+* Keep schemas focused; split large documents into steps (extract sections, 
then merge)
+* Validate with xref:json-validator-component.adoc[JSON Validator] when 
compliance matters
+* For LangChain4j agents, see 
xref:langchain4j-agent-component.adoc[LangChain4j Agent] — structured output 
guardrails avoid prompt-engineering response formats
+
+== Generation parameters (temperature and more)
+
+=== Chat temperature on OpenAI
+
+The OpenAI component exposes `temperature` (0.0–2.0) and `topP` as endpoint 
options. You can also set them per exchange via headers:
+
+[cols="2,3",options="header"]
+|===
+| Option / header | Purpose
+
+| `temperature` URI parameter
+| Default sampling temperature for the endpoint
+
+| `CamelOpenAITemperature` header
+| Override temperature for a single exchange
+
+| `topP` / `CamelOpenAITopP`
+| Nucleus sampling alternative to temperature
+|===
+
+[source,yaml]
+----
+- to:
+    uri: openai:chat-completion
+    parameters:
+      model: gpt-4o-mini
+      temperature: 0.1
+----
+
+For provider-specific parameters not exposed as first-class options, use 
`additionalBodyProperty`:
+
+[source,yaml]
+----
+- to:
+    uri: openai:chat-completion
+    parameters:
+      model: gpt-4o-mini
+      additionalBodyProperty.seed: "42"
+----
+
+NOTE: Prefer first-class URI options when available — they are clearer and 
validated by the component. Use `additionalBodyProperty` for vendor-specific 
knobs without a dedicated option (for example `seed` for reproducible sampling).
+
+=== LangChain4j Chat
+
+Configure temperature on the `ChatModel` bean (Spring Boot properties or 
programmatic builder). See 
xref:langchain4j-chat-component.adoc#_using_a_specific_chat_model[LangChain4j 
Chat — Using a specific Chat Model].
+
+== Dynamic prompts per exchange
+
+Prompts can change on every message using Camel's expression languages — no 
static `userMessage` URI option required.
+
+=== Body as prompt
+
+The message body is the user prompt when no header overrides it:
+
+[source,yaml]
+----
+- from:
+    uri: direct:ask
+    steps:
+      - to:
+          uri: openai:chat-completion
+          parameters:
+            model: gpt-4o-mini
+----
+
+Send `"Summarize this CV: ..."` as the exchange body.
+
+=== Header override with Simple
+
+Use `CamelOpenAIUserMessage` to build prompts from exchange data:
+
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:score-candidate
+      steps:
+        - setHeader:
+            name: CamelOpenAIUserMessage
+            simple: "Rate this candidate 1-10 for role ${header.jobTitle}. CV: 
${body}"
+        - to:
+            uri: openai:chat-completion
+            parameters:
+              model: gpt-4o-mini
+              temperature: 0.2
+----
+
+This pattern works well when the body carries a document (file, JSON, text) 
and the header carries instructions.
+
+[[prompt-templates]]
+== Prompt templates and management at scale
+
+Inline prompt strings in every route become hard to maintain. Common patterns:
+
+=== External prompt files
+
+Load prompts from the classpath or file system and pass them as the body or 
via a processor:
+
+[source,yaml]
+----
+- from:
+    uri: file:prompts/extract-resume.txt?noop=true
+    steps:
+      - setHeader:
+          name: CamelOpenAIUserMessage
+          simple: "${body}\n\nDocument to 
parse:\n${exchangeProperty.documentText}"
+      - to: 
openai:chat-completion?jsonSchema=resource:classpath:schemas/resume.schema.json
+----
+
+See xref:openai-component.adoc#_basic_chat_completion_with_string_input[OpenAI 
— file-based prompts].
+
+=== Property placeholders
+
+Store reusable prompt fragments in `application.properties` or Kubernetes 
ConfigMaps:
+
+[source,properties]
+----
+resume.system.prompt=You are a recruiter assistant. Extract only facts present 
in the document.
+resume.user.template=Extract structured data from this resume:\n\n{{body}}
+----
+
+Reference with Camel property placeholders in URI options or 
pass:c[`{{property.name}}`] in YAML routes.
+
+=== LangChain4j template variables
+
+For LangChain4j Chat, use `CHAT_SINGLE_MESSAGE_WITH_PROMPT` with 
pass:c[`{{variable}}`] placeholders — see 
xref:langchain4j-chat-component.adoc#_send_a_prompt_with_variables[Send a 
prompt with variables].
+
+=== Organization tips
+
+* One schema file + one prompt file per extraction task
+* Version prompts alongside routes (Git) or in external config for 
non-developer edits
+* Keep system instructions in `CamelOpenAISystemMessage` (OpenAI) or 
`AiAgentBody.systemMessage` (LangChain4j Agent) separate from user content
+
+== Streaming responses
+
+With `streaming=true`, the OpenAI component returns an 
`Iterator<ChatCompletionChunk>` in the message body. Process it with Camel 
streaming EIPs (`split` + `streaming()`).
+
+=== In-route streaming (log, transform, aggregate)
+
+[source,yaml]
+----
+- from:
+    uri: direct:stream-chat
+    steps:
+      - to:
+          uri: openai:chat-completion
+          parameters:
+            userMessage: Explain Apache Camel in one paragraph
+            streaming: true
+      - split:
+          streaming: true
+          simple: ${body}
+          steps:
+            - log:
+                message: "chunk: ${body}"
+----
+
+IMPORTANT: Conversation memory is **not** updated for streaming responses. Use 
non-streaming mode when you need multi-turn history on the same exchange.
+
+=== Streaming to a browser (SSE)
+
+For web clients, combine OpenAI streaming with 
xref:platform-http-component.adoc[Platform HTTP] and Server-Sent Events. Add 
`camel-platform-http-vertx` (or another platform-http implementation) to the 
classpath.
+
+._Java example — extract text deltas and emit SSE frames_
+[source,java]
+----
+from("platform-http:/chat/stream?httpMethodRestrict=POST")
+    .setHeader("CamelOpenAIUserMessage", simple("${body}"))
+    .to("openai:chat-completion?streaming=true")
+    .setHeader(Exchange.CONTENT_TYPE, constant("text/event-stream"))
+    .split(body()).streaming()
+        .process(exchange -> {
+            ChatCompletionChunk chunk = 
exchange.getMessage().getBody(ChatCompletionChunk.class);
+            String delta = chunk.choices().isEmpty()
+                    ? ""
+                    : chunk.choices().get(0).delta().content().orElse("");
+            exchange.getMessage().setBody("data: " + delta + "\n\n");
+        })
+    .end();
+----
+
+Enable `useStreaming=true` on the platform-http endpoint when passing large 
streamed bodies (supported on Vert.x).
+
+=== When to stream through Camel vs. bypass it
+
+[cols="2,3",options="header"]
+|===
+| Stream through Camel | Use a dedicated async handler
+
+| You already orchestrate auth, enrichment, logging, and routing in Camel
+| You need minimum latency token delivery and already have a reactive Web layer
+
+| You want one integration path for batch and interactive modes
+| You only proxy an upstream SSE stream verbatim (consider 
xref:others:a2a-producer.adoc#_raw_passthrough_raw_mode[A2A RAW passthrough])
+
+| Moderate throughput chat UI backed by integration logic
+| High-concurrency fan-out where Camel adds little value between HTTP and the 
LLM SDK
+|===
+
+== End-to-end example: document extraction pipeline
+
+A typical resume-processing pipeline (the use case from community feedback):
+
+[source,yaml]
+----
+- route:
+    id: resume-extraction
+    from:
+      uri: direct:process-resume
+      steps:
+        # 1. Optional: extract text upstream (docling, tika, etc.)
+        - setProperty:
+            name: documentText
+            simple: "${body}"
+        # 2. Structured LLM extraction — no manual JSON parsing
+        - setHeader:
+            name: CamelOpenAIUserMessage
+            simple: "Extract candidate fields from this 
resume:\n\n${exchangeProperty.documentText}"
+        - to:
+            uri: openai:chat-completion
+            parameters:
+              model: gpt-4o-mini
+              temperature: 0.1
+              jsonSchema: resource:classpath:schemas/resume.schema.json
+        # 3. Optional: validate then route to HR system
+        - to: 
json-validator:validate?schema=resource:classpath:schemas/resume.schema.json
+        - to: direct:store-candidate
+----
+
+== Related documentation
+
+* xref:openai-component.adoc[OpenAI Component] — chat, MCP, embeddings, audio, 
structured output
+* xref:langchain4j-chat-component.adoc[LangChain4j Chat] — multi-provider chat 
and RAG
+* xref:langchain4j-agent-component.adoc[LangChain4j Agent] — agents, tools, 
guardrails
+* xref:others:openai-providers.adoc[OpenAI-Compatible Providers] — Ollama, 
vLLM, local LLMs
+* xref:others:openai-mcp.adoc[MCP Tool Calling] — agentic tool loops on OpenAI
diff --git a/components/camel-ai/src/main/docs/ai-summary.adoc 
b/components/camel-ai/src/main/docs/ai-summary.adoc
index 678447db0eba..978d0df061ec 100644
--- a/components/camel-ai/src/main/docs/ai-summary.adoc
+++ b/components/camel-ai/src/main/docs/ai-summary.adoc
@@ -4,6 +4,57 @@
 The Camel AI components are a group of components for applying Apache Camel to
 various AI-related technologies.
 
+== Getting started with LLMs
+
+New to Camel AI? Start with the xref:ai-llm-integration-guide.adoc[LLM 
Integration Guide] — it explains when to use xref:openai-component.adoc[OpenAI] 
vs xref:langchain4j-chat-component.adoc[LangChain4j Chat], structured JSON 
extraction, streaming to browsers, dynamic prompts, and prompt management 
patterns.
+
+== Choosing the Right AI Component
+
+Camel offers two main paths for integrating Large Language Models (LLMs) into 
routes:
+
+* **xref:openai-component.adoc[OpenAI]** — talks directly to OpenAI and any 
OpenAI-compatible API (OpenRouter, Ollama, vLLM, LM Studio). Native support for 
streaming, structured output (`outputClass` / `jsonSchema`), MCP tool calling, 
conversation memory, and the Responses API. Best when you are committed to the 
OpenAI ecosystem or using an OpenAI-compatible gateway.
+
+* **xref:langchain4j-chat-component.adoc[LangChain4j Chat]** — abstracts 
through https://github.com/langchain4j/langchain4j[LangChain4j] so you can 
switch LLM providers (OpenAI, Anthropic, Google Gemini, Mistral, Ollama, and 
others) by swapping a dependency. Also provides prompt templates with 
variables, RAG integration via the Content Enricher pattern, and multi-message 
conversation history.
+
+[cols="2,1,1"]
+|===
+| Need | camel-openai | camel-langchain4j-chat
+
+| OpenAI or compatible API (OpenRouter, Ollama, vLLM)
+| Yes
+| Via LangChain4j provider
+
+| Switch providers without code changes
+| No (OpenAI-compatible only)
+| Yes
+
+| MCP tool calling / agentic loops
+| Yes
+| No (use xref:langchain4j-tools-component.adoc[langchain4j-tools] instead)
+
+| Streaming responses
+| Yes
+| Manual (via `StreamingChatLanguageModel`)
+
+| Structured output (JSON schema)
+| Yes (`outputClass`, `jsonSchema`)
+| No
+
+| Prompt templates with variables
+| No (use Simple expressions)
+| Yes (built-in pass:c[`{{variable}}`] syntax)
+
+| RAG pipelines
+| Manual
+| Yes (with `LangChain4jRagAggregatorStrategy`)
+
+| Embeddings
+| Yes
+| Via 
xref:langchain4j-embeddingstore-component.adoc[langchain4j-embeddingstore]
+|===
+
+TIP: If you already use an OpenAI-compatible API and want the richest feature 
set (streaming, MCP, structured output), start with `camel-openai`. If 
multi-provider flexibility is a hard requirement, use `camel-langchain4j-chat`. 
Both can coexist in the same project. For end-to-end pipeline examples, see the 
xref:ai-llm-integration-guide.adoc[LLM Integration Guide].
+
 == {doctitle} components
 
 See the following for usage of each component:
diff --git a/docs/components/modules/ROOT/nav.adoc 
b/docs/components/modules/ROOT/nav.adoc
index b6b9abfa92cb..9f63cc2a0978 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -18,6 +18,7 @@
 *** xref:langchain4j-embeddings-component.adoc[LangChain4j Embeddings]
 *** xref:langchain4j-tools-component.adoc[LangChain4j Tools]
 *** xref:langchain4j-web-search-component.adoc[LangChain4j Web Search]
+*** xref:ai-llm-integration-guide.adoc[LLM Integration Guide]
 *** xref:milvus-component.adoc[Milvus]
 *** xref:neo4j-component.adoc[Neo4j]
 *** xref:openai-component.adoc[OpenAI]
diff --git a/docs/components/modules/ROOT/pages/ai-llm-integration-guide.adoc 
b/docs/components/modules/ROOT/pages/ai-llm-integration-guide.adoc
new file mode 120000
index 000000000000..f5c3b1748db4
--- /dev/null
+++ b/docs/components/modules/ROOT/pages/ai-llm-integration-guide.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-ai/src/main/docs/ai-llm-integration-guide.adoc
\ No newline at end of file
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojo.java
index 79662c5330b3..e44ea4b16ce6 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareDocSymlinksMojo.java
@@ -634,7 +634,8 @@ public class PrepareDocSymlinksMojo extends AbstractMojo {
                 "core/camel-main/src/main/docs/*.adoc",
                 "components/{*,*/*,*/*/*}/src/main/docs/*.adoc");
         List<String> nonComponentSuffixExcludes = List.of(
-                "**/*-component.adoc", "**/*-language.adoc", 
"**/*-dataformat.adoc", "**/*-summary.adoc");
+                "**/*-component.adoc", "**/*-language.adoc", 
"**/*-dataformat.adoc", "**/*-summary.adoc",
+                "**/*-guide.adoc");
         List<String> componentJsonIncludes = List.of(
                 
"components/{*,*/*,*/*/*}/src/generated/resources/META-INF/org/apache/camel/{,**/}*.json");
 
@@ -644,7 +645,8 @@ public class PrepareDocSymlinksMojo extends AbstractMojo {
         components.asciidoc = new KindSpec(
                 List.of("core/camel-base/src/main/docs/*-component.adoc",
                         
"components/{*,*/*,*/*/*}/src/main/docs/*-component.adoc",
-                        "components/{*,*/*}/src/main/docs/*-summary.adoc"),
+                        "components/{*,*/*}/src/main/docs/*-summary.adoc",
+                        "components/{*,*/*}/src/main/docs/*-guide.adoc"),
                 null, "docs/components/modules/ROOT/pages", null, null, null);
         components.image = new KindSpec(
                 List.of("components/{*,*/*}/src/main/docs/*.png"),

Reply via email to