carlos

home · docs · gateway

guides · gateway

Reach carlos from anywhere.

When the daemon is enabled, carlos can send notifications, surface approval prompts, and accept replies through messaging channels. ntfy and Telegram ship; Signal is a stub. Future channels (Discord, Slack, email) follow the same adapter contract.

Architecture (Phase G1)

The broker is daemon-owned. Each channel implements a small adapter contract; the broker handles routing, retry, dedupe, and event streaming.

gateway envelopes
type Notification struct { // outbound: push to a channel
  ID      string
  Title   string
  Body    string
  Actions []Action  // up to 3 inline buttons
}

type Decision struct { // inbound: user resolved an approval
  ID     string
  Choice string     // matches Notification.Actions[i].ID
}

type Reply struct { // inbound: free-text reply
  ID   string
  Text string
}

Adapters (shipped)

adapter status notes
ntfy (G3) shipped JSON publish plus up to 3 action buttons plus HMAC-SHA256-signed action tokens. Inbound replies via Handler() http.Handler.
Telegram (G2) shipped Bot API long-poll. MarkdownV2 messages. Inline keyboard for actions. callback_query resolves to a Decision envelope.
Signal (G6) stub not yet implemented in enabled mode. The adapter is wired so the routing matrix can reference it once the bridge lands.
Custom contract Implement the Adapter interface; register via the daemon. Same envelopes, same retry plumbing.

Approval-queue routing (G4)

When the manage view surfaces an item awaiting input, the broker can deliver to whichever channel the user wired. Inline keyboard and action buttons resolve back into a Decision envelope that hits the same approval surface as an in-TUI prompt. One queue, two surfaces.

until /away lands

Future: /away mode gates gateway delivery so notifications only leave the box when you're actually away. Until then, gateway delivery is always-on once enabled. Plan accordingly if your phone is loud.

Setting up: onboarding wizard

Four-stage wizard. carlos gateway add runs the same flow standalone (Phase G5).

  1. Enable. Switch on the broker; defer until later if you're not ready.
  2. Channel picker. ntfy, Telegram, or Signal stub.
  3. ntfy. Server URL plus topic plus (optional) HMAC secret for signed action tokens.
  4. Telegram. Bot token plus chat ID (the wizard hints how to get both).

Inside the TUI onboarding, gateway defaults to "set up later" (Phase O-5). Skipping is the safe default; nothing breaks if you wire it up after the fact.

Testing the wiring

shell
carlos gateway test <channel>

Dispatches a fixed Notification envelope through one adapter via the UDS gateway-test verb. Successful delivery proves token, network path, and adapter wiring without waiting for an organic event.

Action tokens (ntfy)

ntfy buttons fire URLs back to a configured handler. To survive untrusted middlemen, action tokens are HMAC-SHA256-signed with the topic secret. Replayed tokens are rejected via the dedupe table, so a refreshed-tab double-tap can't double-resolve an approval.

Onward (Phase G deferred)

Soon

Related

Schedule covers the daemon-fired runs that route notifications through this gateway. Sub-agents covers the supervisor surface that emits the approval events the broker delivers. Slash commands documents /gateway and the future /away toggle; config covers every gateway field.