Skip to content

feat(delivery): surface deliveryStatus in --json output for openclaw agent --deliver #57730

@Kaspre

Description

@Kaspre

Problem

openclaw agent --json --deliver currently has no machine-readable indication of whether delivery succeeded, failed, or was skipped. The JSON envelope contains payloads and meta but no delivery status.

This means automation consuming --json output cannot detect silent delivery failures — the exact scenario that #53961 adds diagnostic logging for in non-JSON mode.

Desired behavior

Add a deliveryStatus field to the JSON output envelope when --deliver is used:

{
  "payloads": [...],
  "meta": {...},
  "deliveryStatus": {
    "requested": true,
    "attempted": true,
    "succeeded": false,
    "error": true
  }
}

Design considerations

The JSON envelope is currently emitted before delivery (so stdout stays machine-readable even if delivery throws). Adding deliveryStatus requires either:

  1. Deferring JSON output until after delivery — but then late throws (non-bestEffort API timeouts) would skip JSON output entirely, breaking scripts
  2. Emitting two JSON objects — payload first, status second — but this changes the single-object contract
  3. Wrapping delivery in try/finally to ensure JSON is always emitted, with status reflecting the outcome
  4. Separate status line — a second JSON line (JSONL-style) with just the delivery result

Each approach has trade-offs around backward compatibility, error handling, and parseability. Needs design discussion before implementation.

Additional edge cases to address

  • Partial best-effort delivery (some payloads succeed, others fail)
  • No-payload runs (tool-only turns, heartbeat acks) where delivery is requested but nothing to send
  • normalizeAgentCommandReplyPayloads() intentionally dropping silent-only payloads

Context

Related: #53961 (adds non-JSON diagnostic logging for silent delivery failures). The deliveryStatus object is already returned in the function's in-process return value — this issue is specifically about surfacing it in the stdout JSON output.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions