Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions client/base/src/main/java/io/a2a/client/AbstractClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -390,17 +390,41 @@ public abstract void resubscribe(@NonNull TaskIdParams request,
* @throws A2AClientException if retrieving the extended agent card fails for any reason
*/
public AgentCard getExtendedAgentCard() throws A2AClientException {
return getExtendedAgentCard(null);
return getExtendedAgentCard(null, null);
}

/**
* Retrieve the extended AgentCard.
*
* @param tenant Optional tenant
* @return the extended AgentCard
* @throws A2AClientException if retrieving the extended agent card fails for any reason
*/
public AgentCard getExtendedAgentCard(@Nullable String tenant) throws A2AClientException {
return getExtendedAgentCard(tenant, null);
}

/**
* Retrieve the extended AgentCard.
*
* @param context optional client call context for the request (may be {@code null})
* @return the extended AgentCard
* @throws A2AClientException if retrieving the extended agent card fails for any reason
*/
public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException {
return getExtendedAgentCard(null, context);
}

/**
* Retrieve the extended AgentCard.
*
* @param tenant Optional tenant
* @param context optional client call context for the request (may be {@code null})
* @return the extended AgentCard
* @throws A2AClientException if retrieving the extended agent card fails for any reason
*/
public abstract AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException;
public abstract AgentCard getExtendedAgentCard(@Nullable String tenant,
@Nullable ClientCallContext context) throws A2AClientException;

/**
* Close the transport and release any associated resources.
Expand Down
9 changes: 6 additions & 3 deletions client/base/src/main/java/io/a2a/client/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import io.a2a.spec.AgentCard;
import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
import io.a2a.spec.EventKind;
import io.a2a.spec.GetExtendedAgentCardParams;
import io.a2a.spec.GetTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigResult;
Expand Down Expand Up @@ -601,19 +602,21 @@ public void resubscribe(@NonNull TaskIdParams request,
* <p>
* Example:
* <pre>{@code
* AgentCard updatedCard = client.getExtendedAgentCard(null);
* AgentCard updatedCard = client.getExtendedAgentCard();
* System.out.println("Agent version: " + updatedCard.version());
* System.out.println("Skills: " + updatedCard.skills().size());
* }</pre>
*
* @param tenant Optional tenant
* @param context custom call context for request interceptors (optional)
* @return the agent's extended agent card
* @throws A2AClientException if the extended agent card cannot be retrieved
* @see AgentCard
*/
@Override
public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException {
agentCard = clientTransport.getExtendedAgentCard(context);
public AgentCard getExtendedAgentCard(@Nullable String tenant, @Nullable ClientCallContext context) throws A2AClientException {
GetExtendedAgentCardParams params = new GetExtendedAgentCardParams(tenant);
agentCard = clientTransport.getExtendedAgentCard(params, context);
return agentCard;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.a2a.spec.AgentCard;
import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
import io.a2a.spec.EventKind;
import io.a2a.spec.GetExtendedAgentCardParams;
import io.a2a.spec.GetTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigResult;
Expand Down Expand Up @@ -350,9 +351,12 @@ private MessageSendParams createRequestWithTenant(MessageSendParams request) {
}

@Override
public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException {
GetExtendedAgentCardRequest request = GetExtendedAgentCardRequest.newBuilder()
.build();
public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullable ClientCallContext context) throws A2AClientException {
GetExtendedAgentCardRequest.Builder builder = GetExtendedAgentCardRequest.newBuilder();
if (params.tenant() != null) {
builder.setTenant(params.tenant());
}
GetExtendedAgentCardRequest request = builder.build();
PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, request, agentCard, context);

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import io.a2a.spec.AgentInterface;
import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
import io.a2a.spec.EventKind;
import io.a2a.spec.GetExtendedAgentCardParams;
import io.a2a.spec.GetTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigResult;
Expand Down Expand Up @@ -284,13 +285,13 @@ public void resubscribe(TaskIdParams request, Consumer<StreamingEventKind> event
}

@Override
public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException {
public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullable ClientCallContext context) throws A2AClientException {
try {
PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD,
ProtoUtils.ToProto.extendedAgentCard(), agentCard, context);
ProtoUtils.ToProto.extendedAgentCard(params), agentCard, context);

try {
String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, ""), payloadAndHeaders, GET_EXTENDED_AGENT_CARD_METHOD);
String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, params.tenant()), payloadAndHeaders, GET_EXTENDED_AGENT_CARD_METHOD);
GetExtendedAgentCardResponse response = unmarshalResponse(httpResponseBody, GET_EXTENDED_AGENT_CARD_METHOD);
return response.getResult();
} catch (IOException | InterruptedException | JsonProcessingException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.a2a.client.transport.jsonrpc;

import static io.a2a.client.transport.jsonrpc.JsonMessages.AGENT_CARD;
import static io.a2a.client.transport.jsonrpc.JsonMessages.AGENT_CARD_SUPPORTS_EXTENDED;
import static io.a2a.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_REQUEST;
import static io.a2a.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_RESPONSE;
import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST;
Expand Down Expand Up @@ -43,7 +41,6 @@
import io.a2a.spec.AgentCard;
import io.a2a.spec.ExtensionSupportRequiredError;
import io.a2a.spec.VersionNotSupportedError;
import io.a2a.spec.AgentInterface;
import io.a2a.spec.AgentSkill;
import io.a2a.spec.Artifact;
import io.a2a.spec.AuthenticationInfo;
Expand All @@ -53,6 +50,7 @@
import io.a2a.spec.FilePart;
import io.a2a.spec.FileWithBytes;
import io.a2a.spec.FileWithUri;
import io.a2a.spec.GetExtendedAgentCardParams;
import io.a2a.spec.GetTaskPushNotificationConfigParams;
import io.a2a.spec.Message;
import io.a2a.spec.MessageSendConfiguration;
Expand All @@ -67,7 +65,6 @@
import io.a2a.spec.TaskQueryParams;
import io.a2a.spec.TaskState;
import io.a2a.spec.TextPart;
import io.a2a.spec.TransportProtocol;
import io.a2a.util.Utils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -368,7 +365,8 @@ public void testA2AClientGetExtendedAgentCard() throws Exception {
);

JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001");
AgentCard agentCard = client.getExtendedAgentCard(null);
GetExtendedAgentCardParams params = new GetExtendedAgentCardParams(null);
AgentCard agentCard = client.getExtendedAgentCard(params, null);
assertEquals("GeoSpatial Route Planner Agent Extended", agentCard.name());
assertEquals("Extended description", agentCard.description());
assertEquals("https://georoute-agent.example.com/a2a/v1", Utils.getFavoriteInterface(agentCard).url());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageOrBuilder;
import com.google.protobuf.util.JsonFormat;
import io.a2a.client.http.A2ACardResolver;

import io.a2a.client.http.A2AHttpClient;
import io.a2a.client.http.A2AHttpClientFactory;
import io.a2a.client.http.A2AHttpResponse;
Expand All @@ -46,6 +46,7 @@
import io.a2a.spec.AgentInterface;
import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
import io.a2a.spec.EventKind;
import io.a2a.spec.GetExtendedAgentCardParams;
import io.a2a.spec.GetTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigResult;
Expand Down Expand Up @@ -415,15 +416,13 @@ public void resubscribe(TaskIdParams request, Consumer<StreamingEventKind> event
}

@Override
public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException {
public AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullable ClientCallContext context) throws A2AClientException {
try {
PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, null, agentCard, context);
String url = Utils.buildBaseUrl(agentInterface, "") + "/extendedAgentCard";
String url = Utils.buildBaseUrl(agentInterface, params.tenant()) + "/extendedAgentCard";
A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url);
if (payloadAndHeaders.getHeaders() != null) {
for (Map.Entry<String, String> entry : payloadAndHeaders.getHeaders().entrySet()) {
for (Map.Entry<String, String> entry : payloadAndHeaders.getHeaders().entrySet()) {
getBuilder.addHeader(entry.getKey(), entry.getValue());
}
}
A2AHttpResponse response = getBuilder.get();
if (!response.success()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.a2a.spec.AgentCard;
import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
import io.a2a.spec.EventKind;
import io.a2a.spec.GetExtendedAgentCardParams;
import io.a2a.spec.GetTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigParams;
import io.a2a.spec.ListTaskPushNotificationConfigResult;
Expand Down Expand Up @@ -139,11 +140,12 @@ void resubscribe(TaskIdParams request, Consumer<StreamingEventKind> eventConsume
/**
* Retrieve the extended AgentCard.
*
* @param params the parameters to get the extended agent card.
* @param context optional client call context for the request (may be {@code null})
* @return the extended agent card
* @throws A2AClientException if retrieving the agent card fails for any reason
*/
AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException;
AgentCard getExtendedAgentCard(GetExtendedAgentCardParams params, @Nullable ClientCallContext context) throws A2AClientException;

/**
* Close the transport and release any associated resources.
Expand Down
9 changes: 7 additions & 2 deletions spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.a2a.spec.AgentCard;
import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
import io.a2a.spec.EventKind;
import io.a2a.spec.GetExtendedAgentCardParams;
import io.a2a.spec.GetTaskPushNotificationConfigParams;
import io.a2a.spec.InvalidParamsError;
import io.a2a.spec.ListTaskPushNotificationConfigParams;
Expand Down Expand Up @@ -55,8 +56,12 @@ public static io.a2a.grpc.AgentCard agentCard(AgentCard agentCard) {
return AgentCardMapper.INSTANCE.toProto(agentCard);
}

public static io.a2a.grpc.GetExtendedAgentCardRequest extendedAgentCard() {
return GetExtendedAgentCardRequest.newBuilder().build();
public static io.a2a.grpc.GetExtendedAgentCardRequest extendedAgentCard(GetExtendedAgentCardParams params) {
GetExtendedAgentCardRequest.Builder builder = GetExtendedAgentCardRequest.newBuilder();
if (params.tenant() != null) {
builder.setTenant(params.tenant());
}
return builder.build();
}

public static io.a2a.grpc.GetTaskRequest getTaskRequest(TaskQueryParams params) {
Expand Down
12 changes: 12 additions & 0 deletions spec/src/main/java/io/a2a/spec/GetExtendedAgentCardParams.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.a2a.spec;

import org.jspecify.annotations.Nullable;

/**
* Parameters to get the extended agent card.
*
* @param tenant optional tenant, provided as a path parameter.
* @see <a href="https://a2a-protocol.org/latest/">A2A Protocol Specification</a>
*/
public record GetExtendedAgentCardParams(@Nullable String tenant) {
}