Skip to content

feature: add A2A Protocol Client Support#6311

Open
rohan-patil2 wants to merge 3 commits intoFlowiseAI:mainfrom
rohan-patil2:feature/a2a-client-support
Open

feature: add A2A Protocol Client Support#6311
rohan-patil2 wants to merge 3 commits intoFlowiseAI:mainfrom
rohan-patil2:feature/a2a-client-support

Conversation

@rohan-patil2
Copy link
Copy Markdown
Contributor

Summary

This PR adds Agent-to-Agent (A2A) protocol client support to Flowise, enabling agentflows to discover, authenticate with, and invoke external A2A-compatible agents. This turns Flowise into an A2A protocol client that can orchestrate work across any A2A-compliant agent, regardless of framework, vendor, or hosting.

The implementation targets A2A Protocol Specification v0.3.0 (aligned with @a2a-js/sdk@0.3.x).

What's included

Component Description
A2A Client Wrapper Shared client layer wrapping @a2a-js/sdk with auth, timeouts, abort support, host allowlisting, SSRF protections, and error sanitization
A2A External Agent Node Agentflow v2 canvas node for invoking external A2A agents as first-class flow steps
A2A Agent Tool LangChain DynamicTool that lets Flowise Agent nodes call A2A agents as tools
A2A Agent Credential Credential type supporting API Key and Bearer Token auth for remote agents
UI Integration Node icon, theme color, and canvas registration for the A2A Remote Agent node

What's NOT included (out of scope)

  • A2A server (exposing Flowise agents as A2A endpoints)
  • File/binary artifact support (FilePart)
  • Push notification configuration
  • gRPC transport
  • Agent Card signing / JWS verification
Screenshot 2026-04-29 at 1 04 23 AM

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the A2A (Agent-to-Agent) remote agent integration, including new nodes for Agentflow and tools, a client SDK wrapper, and necessary configuration updates. The implementation includes security measures such as host allowlisting, URL scheme validation, and error message sanitization. My feedback focuses on improving the robustness of the custom fetch implementation, specifically regarding 304 response handling, memory management for abort signals, and refining label sanitization logic.

Comment thread packages/components/src/a2aClient.ts Outdated
// defeat the auth-header scoping above (Authorization/X-API-Key could
// be replayed to the redirect target) and reopen the SSRF surface by
// sending traffic to arbitrary hosts.
if (res.status >= 300 && res.status < 400) {
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

The check res.status >= 300 && res.status < 400 will throw an error for 304 Not Modified responses. While 304 is technically in the 3xx range, it is not a redirection and is a standard response for conditional requests (caching). This could cause unexpected failures if the remote server or a proxy returns a 304. It is safer to explicitly exclude 304 from the redirect block.

Suggested change
if (res.status >= 300 && res.status < 400) {
if (res.status >= 300 && res.status < 400 && res.status !== 304) {

Comment thread packages/components/src/a2aClient.ts Outdated
Comment on lines +290 to +298
const merged = new AbortController()
const onAbort = () => merged.abort()
if (active.aborted || callerSignal.aborted) {
merged.abort()
} else {
active.addEventListener('abort', onAbort, { once: true })
callerSignal.addEventListener('abort', onAbort, { once: true })
}
return merged.signal
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

The fallback implementation for AbortSignal.any attaches event listeners to active and callerSignal but never removes them. This can lead to memory leaks, especially if callerSignal (which may be the long-lived externalAbortSignal) accumulates listeners over many requests that complete successfully. Consider adding a cleanup mechanism to remove these listeners once the fetch operation settles.

}

const returnRole = returnResponseAs === 'assistantMessage' ? 'assistant' : 'user'
const nodeLabel = nodeData?.label ? nodeData.label.toLowerCase().replace(/\s/g, '_').trim() : nodeData?.id
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

The sanitization logic for nodeLabel is flawed because trim() is called after replace(), and it doesn't handle multiple consecutive spaces well. This can result in names starting or ending with underscores. Calling trim() first and using a regex that collapses multiple spaces is more robust and improves readability, aligning with the preference for clear, chained operations over complex logic.

Suggested change
const nodeLabel = nodeData?.label ? nodeData.label.toLowerCase().replace(/\s/g, '_').trim() : nodeData?.id
const nodeLabel = nodeData?.label ? nodeData.label.trim().toLowerCase().replace(/\s+/g, '_') : nodeData?.id
References
  1. Prioritize code readability and understandability over conciseness, favoring a series of simple, chained operations over single complex ones.

@HenryHengZJ
Copy link
Copy Markdown
Contributor

some tests from CI are failing, can you investigate why?

@rohan-patil2
Copy link
Copy Markdown
Contributor Author

some tests from CI are failing, can you investigate why?

Yes, working on them.

@rohan-patil2 rohan-patil2 force-pushed the feature/a2a-client-support branch from dc072a1 to e78de46 Compare May 2, 2026 05:17
@rohan-patil2 rohan-patil2 force-pushed the feature/a2a-client-support branch from e78de46 to 759009a Compare May 6, 2026 03:08
@rohan-patil2 rohan-patil2 marked this pull request as ready for review May 6, 2026 03:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants