Skip to content

Expose Relaycast durable delivery inbox and ack/fail/defer API #154

@willwashburn

Description

@willwashburn

Summary

Agent Relay wants every messaging path to go through Relaycast, including local broker delivery. There should not be a separate "local broker delivery backend" with stronger semantics than the public Relaycast path.

Today Relaycast has partial durable delivery state internally, but it does not expose the public engine/API/SDK surface needed for server-backed delivery handling. That is the gap downstream users see.

Current state

  • @relaycast/engine on main has a deliveries table and creates per-recipient delivery rows for channel messages, DMs, group DMs, and thread replies.
  • Those routes emit delivery.accepted fanout events with delivery_id and message_id.
  • packages/engine/src/engine/receipt.ts moves a delivery from accepted to delivered when a message is marked read.
  • The public inbox route is still only GET /v1/inbox, returning unread summary buckets, mentions, unread DMs, and reactions.
  • There are no public engine routes or SDK methods for:
    • listing pending durable delivery items for an agent
    • subscribing/replaying queued delivery items for offline consumers
    • acking a delivery
    • failing a delivery
    • deferring a delivery with available_at
  • packages/types/src/events.ts does not type delivery.accepted, delivery.delivered, delivery.deferred, or delivery.failed.
  • @relaycast/sdk@2.0.0 exposes inbox(), markRead(), readers, and read status, but no durable delivery list/subscribe/ack/fail/defer surface.

Agent Relay currently has to mark serverDeliveryState, durableDelivery, durableAck, durableFail, and durableDefer as unsupported in its Relaycast adapter because the Relaycast public surface does not support these flows yet.

Why this matters

Relaycast is intended to be the durable messaging backend, not a best-effort live event transport sitting next to a separate local broker delivery system. If local broker messaging goes through Relaycast, Relaycast needs to own the durable delivery contract end to end.

Downstream docs and support matrices should not separate "local broker delivery" from "Relaycast delivery" as if they are different backends. The real distinction is:

  • Relaycast engine already has some internal delivery state.
  • Relaycast does not yet expose enough public API/SDK functionality for clients to consume and update that state durably.

Without this public contract, Agent Relay documentation has to either overstate delivery guarantees or mark durable delivery as unsupported through the SDK adapter.

Proposed capability

Add a public durable delivery API and SDK surface around the existing deliveries model:

  • GET /v1/deliveries or equivalent agent-scoped inbox listing for queued/accepted/deferred items, including message payload, delivery id, mode, reason, attempts/retry metadata, and availability time.
  • WebSocket or polling semantics that allow offline agents to recover queued deliveries after reconnect.
  • Idempotent ack endpoint that transitions a delivery to delivered.
  • Idempotent fail endpoint that records failed, error text, retryability, and retry metadata.
  • Idempotent defer endpoint that records deferred plus available_at and optional reason.
  • Typed events for delivery.accepted, delivery.delivered, delivery.deferred, and delivery.failed.
  • TypeScript SDK methods for the above, so downstream SDKs can report durable delivery support honestly.

Notes

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