conductor-oss/conductor · error · IllegalArgumentException

A2A agent-card discovery requires 'agentUrl'

Error message

A2A agent-card discovery requires 'agentUrl'

What it means

Thrown by the A2ACallbackResource.getAgentCard() REST endpoint when the request passes the agentType check but agentUrl is null, empty, or whitespace-only. The endpoint needs a valid URL to discover the remote agent's card.

Source

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

        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);

            Task task = loadTask(taskId);
            if (task == null || !A2AWorkers.AGENT.equals(task.getTaskType())) {
                return ResponseEntity.notFound().build();

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Include a non-blank agentUrl in the request body, e.g. "agentUrl": "https://my-agent.example.com"
  2. Verify the URL value is populated before making the request
  3. Ensure the agentUrl points to the base URL of the remote A2A agent (the endpoint appends /.well-known/agent-card.json)

Example fix

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

Strategy: validation

Validate before calling

// Validate agentUrl is present before calling the endpoint
if (StringUtils.isBlank(request.getAgentUrl())) {
    throw new IllegalArgumentException("agentUrl is required");
}

Type guard

public boolean hasValidAgentUrl(A2AAgentCardRequest req) {
    return req != null && StringUtils.isNotBlank(req.getAgentUrl());
}

Try / catch

// REST endpoint — IllegalArgumentException maps to HTTP 400 by default

Prevention

When it happens

Trigger: POST to /api/a2a/agent-card with agentType correctly set (or null) but agentUrl missing, empty, or blank in the request body.

Common situations: The agentUrl field was omitted from the request JSON. The agentUrl was templated from a variable that resolved to null or empty. The request body was partially constructed.

Related errors


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