Skip to content

Platform-level relay reply: every agent converses over the relay by default #254

Description

@khaliqgant

Problem

Deployed agents can receive relay DMs today (persona relay.inbox: ['@self'] → cloud inbox_selectors → candidates → deliver → tick wakes the box), but they cannot reply over the relay. A relay DM from a local/peer agent wakes the target, but the answer goes to the wrong place:

  • @agentworkforce/delivery only knows 'slack' | 'telegram' targets (DeliveryClient.targets, resolveDeliveryTargets, onlyTargets, SlackRef/TelegramRef are all hardcoded to those two).
  • So an agent's relay Q&A branch (e.g. hn-monitor handleQaMessage(provider:'relay')) replies via the delivery package to Slack, never back to the relay sender. hn-monitor.parseRelayMessage even drops the sender.
  • There is no relaycast writeback provider in @relayfile/adapter-core (the catalog is external integrations only), and no handler-side relay-send primitive.

Net: "local agent ↔ deployed agent over the relay" doesn't round-trip. Patching each persona (hn-monitor, then inbox-buddy, then every future agent) is the wrong layer. Every agent should be on the relay and able to converse by default, with zero per-persona code.

Proposed design (workforce)

1. packages/delivery — add relaycast as a first-class target.

  • Widen the target union 'slack' | 'telegram''slack' | 'telegram' | 'relaycast' across DeliveryClient.targets, resolveDeliveryTargets(ctx), createDelivery(ctx, transports?, onlyTargets?), and add RelaycastRef alongside SlackRef/TelegramRef.
  • The relaycast transport posts via the relaycast API using RELAY_API_KEY + RELAY_WORKSPACE_ID (already injected into every box by packages/core launcher in cloud) to the inbound relay event's channel/threadId (carried on RelaycastMessageEvent@agent-relay/events).
  • resolveDeliveryTargets includes relaycast when the current run is handling a relay DM (origin-transport reply), so the existing "reply to origin transport" pattern in hn-monitor/inbox-buddy/joke-bot covers relay automatically — no persona changes.

2. packages/runtime — expose relay reply on ctx.

  • Add ctx.relay.reply(text) / ctx.relay.send(toAgent, text) sugar for agents that don't use the delivery package, backed by the same relaycast client.
  • Surface the inbound sender + channel/thread on the relay event so replies address the right DM/thread (today RelaycastMessageEvent carries channel/messageId but personas re-parse ad hoc and drop the sender).

3. (cross-repo) AgentWorkforce/cloud — relay-on by default.

  • Default inbox_selectors to ['@self'] for every deployed agent in translatePersonaRelayToInboxSelectors (packages/web/lib/proactive-runtime/inbox-selectors.ts), opt-out via relay.enabled:false, so addressability is the default rather than opt-in. (Receiving side; complements the reply primitive above.)

Migration / cleanup

  • Once delivery has the relaycast target, drop the per-persona Slack-fallback hack in agents repo hn-monitor relay branch; inbox-buddy/joke-bot inherit relay reply for free.

Acceptance

A local (broker-spawned) agent DMs a deployed agent (e.g. hn-monitor) over the relay and gets the answer back in the relay (full round-trip), with zero persona-specific relay code. Verified against a real workspace (rw_* on the cloud-configured relaycast gateway).

Context

Surfaced while wiring local-agent ↔ cloud-agent chat for the AgentWorkforce/agents personas (inbox-buddy/joke-bot/spotify/hn-monitor dual-transport unification). Relates to cloud inbox delivery (#2212) and the optional-integrations work (#252).

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