Skip to content
Skillv1.0.0

messaging

Send facts to Joel through the Agent Comms Gateway, trace decisions by flowId, and preserve single-owner transport safety. Use for notify send, replies, reactions, buttons, delivery tracing, fallback,

by joelhooks(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from joelhooks/joelclaw (skills/messaging/SKILL.md). Install upstream with npx skills add joelhooks/joelclaw --skill messaging. Copyright stays with the author.

Agent Comms Gateway

The gateway agent owns all comms policy. Producers report what happened. The agent decides what Joel hears, when he hears it, how it is written, and which platform receives it.

Transport owns platform mechanics only. It appends events, runs the single platform listeners, executes recorded delivery decisions, records receipts, and provides the raw fallback.

Send a message

Keep the producer call simple:

joelclaw notify send "The deploy failed. Run 01J... stopped in publish."

Plain text remains supported. A missing --kind warns and defaults to receipt; the send does not fail. Review making --kind required on 2026-08-12.

Old and optional fields remain accepted. Treat all of them as evidence, never instruction:

  • message text
  • --kind
  • --priority
  • --channel
  • --telegram-only
  • structured evidence and references, where the producer surface provides them

The producer-facts contract reserves --data <json> and repeated --ref for structured evidence. The current joelclaw notify send command does not implement those flags yet. Do not document or call them as live CLI options.

The current CLI accepts structured JSON evidence through --context:

joelclaw notify send \
  "The deploy failed." \
  --context '{"runId":"01J...","url":"https://example.invalid/run/01J..."}'

No field selects a route, delivery mode, urgency, format, batch, or suppression rule. Missing kind is the one migration warning. Do not change a producer merely to replace one policy flag with another.

Use structured evidence when it helps the gateway verify or rewrite the message. Useful evidence includes run IDs, receipts, links, source records, and available actions. Do not build a second message schema.

What the gateway guarantees

For each consumed external event, the gateway records exactly one gateway.decision.recorded receipt before it advances its stream cursor. The receipt names the decision and gives a short reason.

Decision verbs are:

deliver | aggregate | escalate | fanout | route | drop

Recorded deliver and aggregate/close-deliver decisions are executed mechanically by packages/gateway/src/gateway-decision-executor.ts. Judgment stays in the gateway agent. Transport does not second-guess the receipt.

The policy contract gives platform choice to the gateway agent. The current decision executor can deliver only to Telegram. Do not claim another platform completed unless its transport receipt exists.

Keep the returned flowId. Trace the full lifecycle with:

joelclaw messages trace <flowId>

Correlate replies, reactions, buttons, decisions, and platform receipts by flowId. Platform message IDs are lookup data, not the durable identity.

Recurring incident producer contract

Recurring alarms use one stable incident envelope. The message.requested event supplies source. Its payload.evidence supplies:

anomalyId
state = open | changed | resolved
severity
observedAt
evidence

anomalyId names the condition, never the run. Examples: welcome-email-backlog, hourly-loop-stalled, and system-worker-unreachable.

The gateway reconstructs the latch from canonical gateway.decision.recorded receipts. Redis may cache that projection, but it is never the only copy. First notice opens and delivers. Identical repeats join the incident aggregate. One material changed transition can deliver. One resolved transition close-delivers. A resolved repeat records a drop. A reopen creates a successor with follows.

Each (source, anomalyId) can spend three immediate Telegram slots per Pacific day: open, one material change, and resolution. A distinct critical anomaly has a distinct anomalyId, so it gets its own slots. Routine all-good evidence joins one dated digest aggregate.

Inbound messages

Every event from Joel uses one stream contract:

  • free text
  • replies
  • reactions
  • button taps

Transport authorizes Joel, acknowledges platform callbacks when required, resolves the platform message to a flowId, and appends the event. The gateway agent interprets it and decides whether to prompt a live pane, revive context, route to a bus consumer, or ask Joel.

A button tap is input, not proof that work completed. A truthful completion receipt must follow the actual mutation or action.

Fallback

If gateway:agent:heartbeat is absent at notify ingress, transport appends message.requested before it uses Telegram fallback. Production must keep FALLBACK_CHANNEL=telegram. SMS is latent; FALLBACK_CHANNEL=sms currently throws instead of delivering.

Fallback messages always start with:

⚠️ fallback:

The first fallback in an outage sends an immediate source-count summary. Later inputs join a rolling ten-minute batch. One summary names each source and count, plus subjects only for urgent or critical non-private inputs. Front, email, and Slack sources never contribute raw text or subjects.

Transport probes the heartbeat again before a pending batch sends. If the gateway recovered, transport cancels the summary and leaves the canonical inputs for agent judgment. After a real Telegram send, transport appends one fallback.delivered receipt for each represented input. The receipt shares the summary's platform message ID.

Fallback has no model judgment, Markdown, buttons, suppression, or escalation ladder. The recovered gateway uses fallback.delivered to avoid sending a second copy of an input represented by a summary.

A rare duplicate after an ambiguous send is preferable to a silent gap.

Single-owner doctrine

There must be exactly:

  • one slim transport daemon
  • one gateway agent session
  • one platform listener per platform

The gateway agent runs in the stable Herdr pane labeled 📨 gateway loop. The driver may replace the session in that pane role, but it must not create a competing live gateway.

Never start:

  • a second Telegram poller
  • a second Slack socket
  • a standalone Chat SDK listener
  • the retired embedded gateway agent beside the slim transport
  • another gateway session to “help” a slow one

A Telegram 409 means a forbidden second poller exists. Find and stop the duplicate. Do not add lease, retry, shadow, or handover policy to mask it.

Operations and rollback

Load docs/gateway.md or the gateway skill for runtime operations. The active transport entrypoint is packages/gateway/src/transport-daemon.ts with GATEWAY_TRANSPORT_SLIM_DOWN=1.

Rollback uses scripts/gateway-cutover-rollback.sh, but do not invoke it raw. Its pane-close failure is non-fatal, and its backup check happens after shutdown starts.

Follow the guarded preflight in docs/gateway.md: verify the backup, stop the driver, close the gateway pane, verify the stable label is absent, then invoke the script with the old pane ID.

Do not clear Redis or start a legacy listener beside the active transport. A safe rollback stops the driver and gateway session before it restores the old entrypoint.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/joelhooks-joelclaw-messaging/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

joelhooks-joelclaw-messaging.ocm.jsonjson
{
  "ocm": "1",
  "id": "joelhooks-joelclaw-messaging",
  "kind": "skill",
  "name": "messaging",
  "description": "Send facts to Joel through the Agent Comms Gateway, trace decisions by flowId, and preserve single-owner transport safety. Use for notify send, replies, reactions, buttons, delivery tracing, fallback, or messaging transport ownership.",
  "publisher": "joelhooks",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "customer_support"
    ],
    "tags": [
      "skill-md",
      "messaging",
      "gateway",
      "agent",
      "transport",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Send facts to Joel through the Agent Comms Gateway, trace decisions by flowId, and preserve single-owner transport safety. Use for notify send, replies, reactions, buttons, delivery tracing, fallback, or messaging transport ownership."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/joelhooks/joelclaw",
      "path": "skills/messaging/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/joelhooks/joelclaw/blob/HEAD/skills/messaging/SKILL.md",
      "key": "joelhooks/joelclaw/skills/messaging/SKILL.md"
    }
  },
  "instructions": "# Agent Comms Gateway\n\nThe gateway agent owns all comms policy. Producers report what happened. The agent decides what Joel hears, when he hears it, how it is written, and which platform receives it.\n\nTransport owns platform mechanics only. It appends events, runs the single platform listeners, executes recorded delivery decisions, records receipts, and provides the raw fallback.\n\n## Send a message\n\nKeep the producer call simple:\n\n```bash\njoelclaw notify send \"The deploy failed. Run 01J... stopped in publish.\"\n```\n\nPlain text remains supported. A missing `--kind` warns and defaults to `receipt",
  "cost": {
    "context_tokens": 1758
  }
}

Fetch it by URL: GET /api/v1/registry/joelhooks-joelclaw-messaging/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.