Claus Ibsen created CAMEL-24832:
-----------------------------------
Summary: camel-openai, camel-spring-ai-chat - propagate the
calling exchange into ai-tool route invocations like langchain4j-agent
Key: CAMEL-24832
URL: https://issues.apache.org/jira/browse/CAMEL-24832
Project: Camel
Issue Type: Improvement
Components: camel-spring-ai, camel-openai
Reporter: Claus Ibsen
h2. Problem
The {{camel-ai-tool}} contract, as documented in the blog post "Authorizing
what an AI agent may do in Apache Camel", is that Camel copies the calling
exchange into each tool call, so context set before the agent runs - most
importantly the authenticated caller's identity kept as an exchange property -
reaches the tool route and the model cannot set it. That is only true for one
runtime:
* {{camel-langchain4j-agent}} copies the exchange:
{{ExchangeHelper.createCopy(exchange, true)}} in {{LangChain4jAgentProducer}}
(CAMEL-23944).
* {{camel-openai}} creates a fresh exchange:
{{spec.getConsumer().createExchange(false)}} in {{McpToolCallExecutor}} (route
tools exposed via the {{tags}} option).
* {{camel-spring-ai-chat}} creates a fresh exchange:
{{spec.getConsumer().getEndpoint().createExchange()}} in
{{AiToolSpecToSpringAi}}.
With camel-openai or spring-ai driving the loop, a tool route guarded on
{{exchangeProperty.subject}} sees {{null}} and denies every call (fail-closed,
but the pattern silently does not work), and any other context (correlation
ids, tenant, variables) is lost too. This bites the YAML DSL in particular:
{{openai:chat-completion?baseUrl=...&tags=support&systemMessage=...}} against
an OpenAI-compatible endpoint (e.g. Ollama) is the only agent loop that needs
no Java bean, and it is the one that drops the identity.
h2. Proposal
* In {{camel-openai}} and {{camel-spring-ai-chat}}, create the tool exchange as
a copy of the calling exchange (properties and variables included), isolating
headers, body and exceptions the same way CAMEL-23944 did for langchain4j-agent.
* State the contract once in the {{camel-ai-tool}} documentation: every runtime
that executes route tools passes the caller's exchange context through, and
which parts are isolated.
* Consider a shared helper in {{camel-ai-tool}} (next to {{AiToolExecutor}})
that builds the tool exchange, so the runtimes cannot drift again.
The MCP server bridge ({{McpServerBridge}}) also creates a fresh exchange, but
there is no calling exchange there; carrying the MCP caller's identity into an
exchange property is tracked with CAMEL-24831.
Related: CAMEL-23944, CAMEL-24831.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)