conductor-oss/conductor · error · NonRetryableException

GET_AGENT_CARD requires 'agentUrl'

Error message

GET_AGENT_CARD requires 'agentUrl'

What it means

Thrown by A2AWorkers.getAgentCard as NonRetryableException when the A2AAgentCardRequest.agentUrl is blank. The GET_AGENT_CARD worker first validates agentType is 'a2a' (via requireA2a), then requires a non-blank agentUrl before fetching the remote Agent Card. NonRetryableException marks the task FAILED_WITH_TERMINAL_ERROR so Conductor will not retry it.

Source

Thrown at ai/src/main/java/org/conductoross/conductor/ai/tasks/worker/A2AWorkers.java:168

            synchronized (agentClients) {
                if (!agentClientsLoaded) {
                    applicationContext
                            .getBeansOfType(ConductorAgentClient.class)
                            .values()
                            .forEach(this::register);
                    agentClientsLoaded = true;
                }
            }
        }
        return agentClients;
    }

    /** Fetch a remote agent's Agent Card. */
    @WorkerTask(GET_AGENT_CARD)
    public A2AAgentCardResult getAgentCard(A2AAgentCardRequest request) {
        requireA2a(request.getAgentType());
        if (StringUtils.isBlank(request.getAgentUrl())) {
            throw new NonRetryableException("GET_AGENT_CARD requires 'agentUrl'");
        }
        AgentCard agentCard = a2aService.getAgentCard(request.getAgentUrl(), request.getHeaders());
        return new A2AAgentCardResult(agentCard);
    }

    /**
     * Start or advance an agent call.
     *
     * <p>The output is returned as a plain POJO. Task lifecycle state is applied through {@link
     * TaskContext}; {@code IN_PROGRESS} with a callback delay requeues the task without holding a
     * worker thread. Streaming is the one exception and enables lease extension because it blocks
     * while consuming the remote SSE response.
     */
    @WorkerTask(value = AGENT, leaseExtendEnabled = true)
    public A2ACallResult agent(A2ACallRequest request) {
        Task task = TaskContext.get().getTask();
        TaskResult result;
        ConductorAgentClient client =

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Add a non-blank 'agentUrl' to the GET_AGENT_CARD task input (the Agent Card well-known URL).
  2. If the URL is dynamic, ensure the upstream task producing it always yields a non-empty value.
  3. Validate the task input at authoring time before running the workflow.

Example fix

// before
{
  "name": "fetch_card",
  "taskReferenceName": "fetch_card",
  "type": "GET_AGENT_CARD",
  "inputParameters": { "agentType": "a2a" }
}

// after
{
  "type": "GET_AGENT_CARD",
  "inputParameters": {
    "agentType": "a2a",
    "agentUrl": "https://agent.example.com/.well-known/agent.json"
  }
}
Defensive patterns

Strategy: validation

Validate before calling

if (StringUtils.isBlank(request.getAgentUrl())) {
    throw new IllegalArgumentException(
        "GET_AGENT_CARD task requires a non-blank 'agentUrl' input");
}
if (!"a2a".equalsIgnoreCase(request.getAgentType())) {
    throw new IllegalArgumentException("GET_AGENT_CARD requires agentType='a2a'");
}

Try / catch

// NonRetryableException marks the task terminal; catch it to degrade gracefully
// (e.g. in a worker wrapper) rather than retry.
try {
    workers.getAgentCard(request);
} catch (NonRetryableException e) {
    // log and fail the task without retry
}

Prevention

When it happens

Trigger: A GET_AGENT_CARD task whose input omits agentUrl or supplies an empty/whitespace value, or an agentType other than 'a2a' (which fails requireA2a first with a different message).

Common situations: Workflow author forgetting the agentUrl input field, a dynamic input parameter that resolved to empty, or copy-pasting a task definition without the URL.

Related errors


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