feat(core): implement HTTP authentication support for A2A remote agents (#20510)

Co-authored-by: Adam Weidman <adamfweidman@google.com>
This commit is contained in:
Sandy Tao
2026-03-02 11:59:48 -08:00
committed by GitHub
parent 48412a068e
commit 446a4316c4
11 changed files with 565 additions and 27 deletions
+26 -2
View File
@@ -24,6 +24,7 @@ import type { AuthenticationHandler } from '@a2a-js/sdk/client';
import { debugLogger } from '../utils/debugLogger.js';
import type { AnsiOutput } from '../utils/terminalSerializer.js';
import type { SendMessageResult } from './a2a-client-manager.js';
import { A2AAuthProviderFactory } from './auth-provider/factory.js';
/**
* Authentication handler implementation using Google Application Default Credentials (ADC).
@@ -79,7 +80,7 @@ export class RemoteAgentInvocation extends BaseToolInvocation<
// TODO: See if we can reuse the singleton from AppContainer or similar, but for now use getInstance directly
// as per the current pattern in the codebase.
private readonly clientManager = A2AClientManager.getInstance();
private readonly authHandler = new ADCHandler();
private authHandler: AuthenticationHandler | undefined;
constructor(
private readonly definition: RemoteAgentDefinition,
@@ -107,6 +108,27 @@ export class RemoteAgentInvocation extends BaseToolInvocation<
return `Calling remote agent ${this.definition.displayName ?? this.definition.name}`;
}
private async getAuthHandler(): Promise<AuthenticationHandler | undefined> {
if (this.authHandler) {
return this.authHandler;
}
if (this.definition.auth) {
const provider = await A2AAuthProviderFactory.create({
authConfig: this.definition.auth,
agentName: this.definition.name,
});
if (!provider) {
throw new Error(
`Failed to create auth provider for agent '${this.definition.name}'`,
);
}
this.authHandler = provider;
}
return this.authHandler;
}
protected override async getConfirmationDetails(
_abortSignal: AbortSignal,
): Promise<ToolCallConfirmationDetails | false> {
@@ -138,11 +160,13 @@ export class RemoteAgentInvocation extends BaseToolInvocation<
this.taskId = priorState.taskId;
}
const authHandler = await this.getAuthHandler();
if (!this.clientManager.getClient(this.definition.name)) {
await this.clientManager.loadAgent(
this.definition.name,
this.definition.agentCardUrl,
this.authHandler,
authHandler,
);
}