conductor-oss/conductor · error · IllegalArgumentException

A2A agent-card discovery requires agentType 'a2a'

Error message

A2A agent-card discovery requires agentType 'a2a'

What it means

Thrown by the A2ACallbackResource.getAgentCard() REST endpoint (POST /api/a2a/agent-card) when the request body is null or the agentType field does not select the A2A runtime. The isA2aAgentType() check accepts null, blank, or 'a2a' (case-insensitive), so this fires only when agentType is explicitly set to a non-A2A value like 'azure-foundry' or 'conductor'.

Source

Thrown at ai/src/main/java/org/conductoross/conductor/ai/a2a/A2ACallbackResource.java:83

    private final A2AService a2aService;

    public A2ACallbackResource(TaskService taskService, A2AService a2aService) {
        this.taskService = taskService;
        this.a2aService = a2aService;
    }

    /**
     * Resolve a public A2A Agent Card using the same discovery, network policy, and SSRF checks as
     * the {@code GET_AGENT_CARD} system task.
     *
     * <p>The typed result deliberately contains only the discovered card. Request headers are used
     * for discovery but are never reflected into the response, which makes the result safe to
     * persist as workflow task metadata.
     */
    @PostMapping("/agent-card")
    public A2AAgentCardResult getAgentCard(@RequestBody A2AAgentCardRequest request) {
        if (request == null || !A2AService.isA2aAgentType(request.getAgentType())) {
            throw new IllegalArgumentException("A2A agent-card discovery requires agentType 'a2a'");
        }
        if (StringUtils.isBlank(request.getAgentUrl())) {
            throw new IllegalArgumentException("A2A agent-card discovery requires 'agentUrl'");
        }
        AgentCard card = a2aService.getAgentCard(request.getAgentUrl(), request.getHeaders());
        return new A2AAgentCardResult(card);
    }

    @PostMapping("/callback/{taskId}")
    public ResponseEntity<Void> onPushNotification(
            @PathVariable("taskId") String taskId,
            @RequestHeader(value = "Authorization", required = false) String authHeader,
            @RequestHeader(value = "X-Conductor-A2A-Token", required = false) String customHeader,
            @RequestBody(required = false) JsonNode payload) {

        try (A2ALogging.Scope scope = A2ALogging.of(A2ALogging.TASK_ID, taskId)) {
            String token = resolveToken(authHeader, customHeader);

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Set agentType to 'a2a' or omit it entirely (null/blank defaults to A2A) in the request body
  2. If using azure-foundry or conductor agents, use the appropriate discovery mechanism instead of this endpoint
  3. Ensure the request body is valid JSON with an agentType field

Example fix

// before
{"agentType": "azure-foundry", "agentUrl": "https://my-agent.example.com"}
// after
{"agentType": "a2a", "agentUrl": "https://my-agent.example.com"}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the request before sending to the endpoint
if (request == null || !A2AService.isA2aAgentType(request.getAgentType())) {
    throw new IllegalArgumentException(
        "agentType must be null, blank, or 'a2a' for this endpoint");
}

Type guard

// Type guard for A2AAgentCardRequest
public boolean isValidA2AAgentCardRequest(A2AAgentCardRequest req) {
    return req != null
        && A2AService.isA2aAgentType(req.getAgentType())
        && StringUtils.isNotBlank(req.getAgentUrl());
}

Try / catch

// This is a REST endpoint — handle via @ExceptionHandler or global advice
// The IllegalArgumentException will be mapped to HTTP 400 by Spring if not caught

Prevention

When it happens

Trigger: POST to /api/a2a/agent-card with a request body where agentType is set to a non-A2A value (e.g. 'azure-foundry', 'conductor'), or when the entire request body is null/malformed.

Common situations: The caller set agentType to 'azure-foundry' or 'conductor' but used the generic A2A agent-card endpoint instead of the provider-specific discovery path. The request body was not sent or was malformed JSON, resulting in a null deserialized request.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/c1333bec9832c983. Report an issue: GitHub.