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
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/engineonmainhas adeliveriestable and creates per-recipient delivery rows for channel messages, DMs, group DMs, and thread replies.delivery.acceptedfanout events withdelivery_idandmessage_id.packages/engine/src/engine/receipt.tsmoves a delivery fromacceptedtodeliveredwhen a message is marked read.GET /v1/inbox, returning unread summary buckets, mentions, unread DMs, and reactions.available_atpackages/types/src/events.tsdoes not typedelivery.accepted,delivery.delivered,delivery.deferred, ordelivery.failed.@relaycast/sdk@2.0.0exposesinbox(),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, anddurableDeferas 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:
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
deliveriesmodel:GET /v1/deliveriesor equivalent agent-scoped inbox listing for queued/accepted/deferred items, including message payload, delivery id, mode, reason, attempts/retry metadata, and availability time.delivered.failed, error text, retryability, and retry metadata.deferredplusavailable_atand optional reason.delivery.accepted,delivery.delivered,delivery.deferred, anddelivery.failed.Notes