Skip to content

Potential NullPointerException in RemoteA2AAgent when AgentCard.capabilities() is null #1008

@Harishvishwa01

Description

@Harishvishwa01

Description

this.streaming = this.agentCard.capabilities().streaming();

If an AgentCard implementation returns null for capabilities(), this will result in a NullPointerException.


Location

RemoteA2AAgent constructor

Title:
Potential NullPointerException in RemoteA2AAgent when AgentCard.capabilities() is null


Description

In the RemoteA2AAgent constructor, the following line assumes that agentCard.capabilities() always returns a non-null object:

this.streaming = this.agentCard.capabilities().streaming();

If an AgentCard implementation returns null for capabilities(), this will result in a NullPointerException.


Location

RemoteA2AAgent constructor

this.streaming = this.agentCard.capabilities().streaming();

Expected Behavior

The constructor should safely handle cases where capabilities() returns null.


Actual Behavior

If capabilities() is null, the code throws a NullPointerException.


Suggested Fix

Add a null check before accessing streaming():

var capabilities = this.agentCard.capabilities();
this.streaming = capabilities != null && capabilities.streaming();

Additional Context

This issue may occur when using custom AgentCard implementations where capabilities are optional or not initialized.

Handling this defensively would make the agent initialization more robust.

modified Code

public class RemoteA2AAgent extends BaseAgent {

private static final Logger logger = LoggerFactory.getLogger(RemoteA2AAgent.class);
private static final ObjectMapper objectMapper =
new ObjectMapper().registerModule(new JavaTimeModule());

private final AgentCard agentCard;
private final Client a2aClient;
private String description;
private final boolean streaming;

private RemoteA2AAgent(Builder builder) {
super(
builder.name,
builder.description,
builder.subAgents,
builder.beforeAgentCallback,
builder.afterAgentCallback);

if (builder.a2aClient == null) {
  throw new IllegalArgumentException("a2aClient cannot be null");
}

this.a2aClient = builder.a2aClient;

if (builder.agentCard != null) {
  this.agentCard = builder.agentCard;
} else {
  try {
    this.agentCard = this.a2aClient.getAgentCard();
  } catch (A2AClientException e) {
    throw new AgentCardResolutionError("Failed to resolve agent card", e);
  }
}

if (this.agentCard == null) {
  throw new IllegalArgumentException("agentCard cannot be null");
}

this.description = nullToEmpty(builder.description);

if (this.description.isEmpty() && this.agentCard.description() != null) {
  this.description = this.agentCard.description();
}

// Safe handling for capabilities
var capabilities = this.agentCard.capabilities();
if (capabilities == null) {
  throw new IllegalStateException("AgentCard capabilities cannot be null");
}

this.streaming = capabilities.streaming();

}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private String name;
private AgentCard agentCard;
private Client a2aClient;
private String description = "";
private List<? extends BaseAgent> subAgents;
private List<Callbacks.BeforeAgentCallback> beforeAgentCallback;
private List<Callbacks.AfterAgentCallback> afterAgentCallback;

@CanIgnoreReturnValue
public Builder name(String name) {
  this.name = name;
  return this;
}

@CanIgnoreReturnValue
public Builder agentCard(AgentCard agentCard) {
  this.agentCard = agentCard;
  return this;
}

@CanIgnoreReturnValue
public Builder description(String description) {
  this.description = description;
  return this;
}

@CanIgnoreReturnValue
public Builder subAgents(List<? extends BaseAgent> subAgents) {
  this.subAgents = subAgents;
  return this;
}

@CanIgnoreReturnValue
public Builder beforeAgentCallback(List<Callbacks.BeforeAgentCallback> beforeAgentCallback) {
  this.beforeAgentCallback = beforeAgentCallback;
  return this;
}

@CanIgnoreReturnValue
public Builder afterAgentCallback(List<Callbacks.AfterAgentCallback> afterAgentCallback) {
  this.afterAgentCallback = afterAgentCallback;
  return this;
}

@CanIgnoreReturnValue
public Builder a2aClient(Client a2aClient) {
  this.a2aClient = a2aClient;
  return this;
}

public RemoteA2AAgent build() {
  return new RemoteA2AAgent(this);
}

}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions