Skip to main content
Two complementary surfaces for reacting to canonical card changes without polling:
  • Server-Sent Events at GET /v1/agents/{id}/stream — long-lived HTTP connection; you receive a card_changed SSE frame whenever the agent’s canonical card recomposes.
  • Signed webhook subscriptions at POST /v1/agents/{id}/notifications/webhook — Mnemom POSTs a signed payload to your URL on each canonical change.
Both surfaces read from the transparency log. This is a distinct mechanism from the org-level Webhook Notifications system — different endpoints, its own signing convention (below), and scoped to one agent’s card rather than a whole org’s event stream.
Both surfaces are gated per-agent by agents.sse_enabled / agents.webhook_enabled, which default to off. There is currently no self-service API to flip these flags — contact support to enable card-change notifications for an agent. Until enabled, both endpoints return 404 (to avoid enumerating which agents exist).

SSE channel

Connect

The response is Content-Type: text/event-stream. Each canonical change emits a frame like:

Reconnect with a cursor

The id field on each frame is the transparency-log log_index. On reconnect, pass it as Last-Event-ID (standard SSE reconnection header) or as the since query parameter — Last-Event-ID takes precedence when both are present:
Frames are delivered strictly in log_index ascending order, so the cursor is monotone.

Stream lifetime

Each connection caps at 5 minutes. Reconnect with the latest cursor — EventSource implementations handle this automatically. A : keepalive <timestamp> comment frame is emitted every 15 seconds; a final event: close frame fires before the connection drops.

Webhook channel

Subscribe

Response:
The secret is shown exactly once — store it server-side. Mnemom holds only its hash. Subscriptions expire after 30 days by default unless you pass an explicit expires_at.

Delivery shape

On every canonical card change, Mnemom POSTs to your URL:
With headers:
This is a different header pair from the org-level Webhook Notifications system (X-Webhook-Id / X-Webhook-Signature, no Mnemom- prefix) — don’t share verification code between the two without checking the header names.

Verify the signature

The HMAC-SHA256 signature is computed over the string <timestamp>.<raw-body>:

List active subscriptions

Returns each subscription’s subscription_id, channel (webhook or sse), consumer_id, webhook_url, and last_sent_log_index — never the secret.

Idempotent delivery

Each subscription tracks last_sent_log_index. If the same log entry is re-processed (e.g. a reconciler closes a gap that the normal compose path also closed), delivery is skipped for any subscription whose last_sent_log_index is already at or past that entry.

Unsubscribe

Returns 204 on success, 404 if the subscription is already gone (idempotent).

Webhook URL constraints

  • https:// only — http:// URLs are rejected.
  • No loopback, RFC 1918, link-local, multicast, or reserved address space (IPv4 or IPv6).
  • No .local / .internal hostnames.
These defend against SSRF on outbound delivery. For local development, tunnel with ngrok or cloudflared.

SSE vs webhook — which to use

Both surfaces deliver from the same event source (the transparency log) — subscribing to both is fine.

See also