You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Claus Ibsen (Jira)" <ji...@apache.org> on 2026/10/21 18:27:00 UTC

[jira] [Created] (CAMEL-25931) camel-a2a - an agent that calls another agent mixes their headers: the producer runs the operation of the consumer, and the reply takes the other agent's task

Claus Ibsen created CAMEL-25931:
-----------------------------------

             Summary: camel-a2a - an agent that calls another agent mixes their headers: the producer runs the operation of the consumer, and the reply takes the other agent's task
                 Key: CAMEL-25931
                 URL: https://issues.apache.org/jira/browse/CAMEL-25931
             Project: Camel
          Issue Type: Bug
          Components: camel-ai
    Affects Versions: 4.21.0, 4.22.0, 4.23.0
            Reporter: Claus Ibsen
             Fix For: 4.24.0


An agent route that calls another agent, as an orchestrator does, shares the {{CamelA2A*}} headers between its consumer and the producer, in both directions.

*1. The producer runs the operation of the consumer.* The consumer sets {{CamelA2AOperation}} on the exchange of the route to the method of the call: {{SendMessage}}, or {{SendStreamingMessage}} for a streaming call ({{MessageSendOperation.java:139}} and {{A2AConsumer.java:1508}} on main). The producer takes its operation from that header first, and uses its {{operation}} option only when the header is absent ({{A2AProducer.resolveOperation}}, {{A2AProducer.java:239-253}}):

{code:java}
String headerOp = exchange.getMessage().getHeader(A2AConstants.OPERATION, String.class);
if (headerOp != null) {
    // Try method name first
    A2AOperations operation = A2AOperations.fromMethodName(headerOp);
    if (operation != null) {
        return operation;
    }
{code}

So, in the route of an agent:
* {{to("a2a:...?operation=TASK_GET")}}, or any other operation, sends a SendMessage;
* a call with the default operation (MESSAGE_SEND) streams when the caller streamed, and the body is then an {{SseEventIterator}} instead of the text of the answer.

*2. The reply takes the task of the other agent.* The consumer puts the id of its own task in {{CamelA2ATaskId}} before the route ({{A2AConsumer.java:1202}} and {{:1506}}). A SendMessage that gets a Task back overwrites {{CamelA2ATaskId}}, {{CamelA2AContextId}}, {{CamelA2ATaskState}} and {{CamelA2AResponseType}} with the values of the other agent ({{MessageSendOperation.java:84-96}}). After the route, the consumer builds its reply from these headers ({{MessageSendOperation.buildResponse}}, {{:146-149}}), so the caller gets a Task with the id, the context and the state of the other agent's task.

Found by reading the code on 4.24.0-SNAPSHOT. It is so since the component was added (CAMEL-23063, 4.21.0).

*Proposed change*: keep what the consumer needs for its reply apart from the headers that steer a producer, for example in exchange properties, so a producer in the route neither reads the consumer's operation nor changes the consumer's task. Until then, the documentation can say to remove the {{CamelA2A*}} headers before calling another agent.

_Claude Code on behalf of davsclaus_



--
This message was sent by Atlassian Jira
(v8.20.10#820010)