Skip to content

CAMEL-23063: Add camel-a2a component for Agent-to-Agent (A2A) protoco…#23711

Open
luigidemasi wants to merge 1 commit into
apache:mainfrom
luigidemasi:CAMEL-23063
Open

CAMEL-23063: Add camel-a2a component for Agent-to-Agent (A2A) protoco…#23711
luigidemasi wants to merge 1 commit into
apache:mainfrom
luigidemasi:CAMEL-23063

Conversation

@luigidemasi
Copy link
Copy Markdown
Contributor

…l integration

Adds the camel-a2a component implementing the A2A (Agent-to-Agent) protocol for Apache Camel. The component provides both producer and consumer support, enabling Camel
routes to participate in standardized agent-to-agent communication.

Features

  • Consumer — exposes a Camel route as an A2A server with automatic agent card serving at /.well-known/agent-card.json
  • Producer — sends A2A messages (MESSAGE_SEND, MESSAGE_STREAM, TASK_GET, TASK_CANCEL, etc.) to remote agents
  • Protocol bindings — REST and JSON-RPC 2.0
  • Streaming — Server-Sent Events (SSE) for real-time task updates
  • Authentication — API key, Bearer token, OAuth 2.0, OpenID Connect
  • Task management — in-memory task store with TTL, push notifications, subscriber management
  • Agent card — discovery, resolution (file < bean < URI params), and auto-serving
  • Type converters — Message/Task to String, plus Simple DSL functions (a2aText(), a2aData(), a2aFile())
  • Progress APIA2AProgress.emit() for status updates from any route

Demo

A multi-agent demo showcasing camel-a2a in action is available at:

https://github.com/luigidemasi/camel-a2a-morning-routine

@luigidemasi luigidemasi requested a review from davsclaus June 2, 2026 15:34
"description": "Camel A2A component for Agent-to-Agent protocol communication",
"deprecated": false,
"firstVersion": "4.21.0",
"label": "ai,a2a",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for the a2a label? Plan to have several agent to agents components?

What about ai and agent labels? maybe we will have some components acting as agents or doing agent to something else communication?

return "oauth2";
}
if (configuration.getBearerToken() != null) {
return "http";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it for both http and https?

Comment on lines +56 to +58
.artifacts(task.artifacts != null ? new ArrayList<>(task.artifacts) : null)
.history(task.history != null ? new ArrayList<>(task.history) : null)
.metadata(task.metadata != null ? new HashMap<>(task.metadata) : null);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about providing empty List or Map instead of null?

it avoids having to check for nullness

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

Copy link
Copy Markdown
Contributor

@davsclaus davsclaus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this substantial contribution — the A2A component is well-structured, follows Camel conventions, and has impressive test coverage. I have one blocking security finding and a few additional items.

Positive observations

  • Good security defaults: followRedirects=false, agent card loader blocks redirects, WebhookUrlValidator has SSRF protection with private IP/IPv6 checks
  • Comprehensive test coverage across operations, protocols, streaming, auth, and push notifications
  • Proper MojoHelper registration, SimpleFunctionDispatcher integration, secret = true annotations on sensitive params
  • No new external dependencies beyond Jackson (already managed by parent BOM)

General (non-inline) findings

  • Missing upgrade guide entry — per project conventions, new user-visible features should be documented in docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
  • Dead code — the private method executeStreamProcessing in A2AConsumer (line ~1077) appears unused and should be removed
  • CI — one CI check ("build") is currently failing; the three matrix builds pass, so this may be infrastructure, but worth confirming

Note: This review evaluates the PR against Apache Camel's project rules and conventions. It does not replace specialized review tools (CodeRabbit, Sourcery) or static analysis (SonarCloud).

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

String lower = entry.getKey().toLowerCase(Locale.ENGLISH);
return lower.startsWith("camela2a") || lower.startsWith("org.apache.camel.");
});
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Blocking — Security] This filter only strips CamelA2A* and org.apache.camel.* headers but does not strip all Camel* headers. Per the project's security model and the committer review checklist, consumers exposed to untrusted input must block Camel* / camel* / org.apache.camel.* case-insensitively.

The current filter leaves headers like CamelBeanMethodName, CamelExecCommandExecutable, etc. unfiltered — this is the exact attack vector from CVE-2025-27636 and five follow-on CVEs.

Suggested change
}
return lower.startsWith("camel") || lower.startsWith("org.apache.camel.");

this.maxRetries = maxRetries;
this.initialBackoffMs = initialBackoffMs;
this.executor = Executors.newScheduledThreadPool(4, r -> {
Thread t = new Thread(r, "A2APushDispatcher");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Medium] This creates a ScheduledExecutorService via Executors.newScheduledThreadPool() directly, bypassing Camel's ExecutorServiceManager. The threads won't be tracked by JMX/monitoring, won't participate in graceful shutdown, and won't respect Camel's thread pool profile.

The HttpClient executor in A2AEndpoint.doStart() correctly uses getCamelContext().getExecutorServiceManager() — this should follow the same pattern. Since PushNotificationDispatcher doesn't have access to CamelContext, consider passing in a ScheduledExecutorService created by the endpoint instead.

String contextId = exchange.getMessage().getHeader(A2AConstants.LIST_CONTEXT_ID, String.class);

filterInboundHeaders(exchange);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Low] pageSize and contextId are read from exchange headers before filterInboundHeaders is called (lines 734-735). An untrusted HTTP client could inject CamelA2AListPageSize and CamelA2AListContextId headers. While the impact is low (pageSize is capped at 100, contextId is just a filter key), the filter should run before any header reads — consistent with all other handlers in this class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants