conductor-oss/conductor · error · NonRetryableException

AGENT requires one of: message, parts, text, or prompt

Error message

AGENT requires one of: message, parts, text, or prompt

What it means

Thrown as NonRetryableException while building the outbound A2A message when none of message, parts, text, or prompt are supplied on the A2ACallRequest. The message builder needs at least one content source to construct an A2AMessage with parts. Because the input is fundamentally incomplete, it fails terminally rather than retrying the same empty payload.

Source

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

        result.setCallbackAfterSeconds(
                usePush(request) ? pushBackstopSeconds(request) : pollInterval(request));
    }

    private A2AMessage buildMessage(A2ACallRequest request, Task task) {
        A2AMessage message;
        if (request.getMessage() != null && !request.getMessage().isEmpty()) {
            message = objectMapper.convertValue(request.getMessage(), A2AMessage.class);
        } else {
            message = new A2AMessage();
            List<Part> parts = new ArrayList<>();
            if (request.getParts() != null && !request.getParts().isEmpty()) {
                for (Map<String, Object> raw : request.getParts()) {
                    parts.add(objectMapper.convertValue(raw, Part.class));
                }
            } else {
                String text = StringUtils.firstNonBlank(request.getText(), request.getPrompt());
                if (StringUtils.isBlank(text)) {
                    throw new NonRetryableException(
                            "AGENT requires one of: message, parts, text, or prompt");
                }
                Part part = new Part();
                part.setKind("text");
                part.setText(text);
                parts.add(part);
            }
            message.setParts(parts);
        }
        if (message.getRole() == null) {
            message.setRole("user");
        }
        if (message.getMessageId() == null) {
            message.setMessageId(deterministicMessageId(task));
        }
        if (message.getKind() == null) {
            message.setKind("message");
        }

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Provide at least one of message, parts, text, or prompt in the task input.
  2. If using text/prompt via template variables, verify the upstream task actually emitted the referenced variable (not null/empty).
  3. Set a static fallback text in the task definition so the field is never blank.
  4. Check for key typos: the worker reads request.getText() and request.getPrompt() exactly.

Example fix

// before
{ "agentUrl": "https://agent/a2a", "agentType": "a2a" }  // no content -> fails
// after
{ "agentUrl": "https://agent/a2a", "agentType": "a2a", "text": "${task.generate.output.result}" }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure at least one content source is present before building the message
boolean hasContent =
    (request.getMessage() != null && !request.getMessage().isEmpty())
    || (request.getParts() != null && !request.getParts().isEmpty())
    || StringUtils.isNoneBlank(request.getText(), request.getPrompt());
if (!hasContent) {
    throw new IllegalArgumentException("Supply one of message, parts, text, or prompt");
}

Prevention

When it happens

Trigger: An AGENT workflow task whose input omits all four content fields; calling the worker with an A2ACallRequest where message is null/empty, parts is null/empty, and both text and prompt are blank.

Common situations: Workflow author forgot to wire input variables; upstream task produced no text so the templated field resolved to empty; a programmatic SDK caller constructed A2ACallRequest without setting content; typo in input key (e.g. 'txt' instead of 'text').

Related errors


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