Contextual agent subscriptions
A contextual subscription turns a durable domain event into bounded agent work without running an agent, connector, or callback inside the originating transaction. Its compiled definition binds one exact event stream, up to 16 named hydration queries, up to 32 declared command reactions, canonical parameters, and fixed delivery limits.
Work item semantics
One pull leases at most one event. RiffDB executes every hydration in one shared read snapshot whose application head is at least the event’s commit sequence. The returned item contains:
- the selected typed event and stable event ID;
- attempt-specific lease token, attempt, expiry, and history incarnation;
- one shared
context_headand bounded named hydration results; - only reactions that are both declared and currently authorized; and
- an opaque server-sealed causation token for each available reaction.
Hydrated values are never stored in consumer state. Redelivery recomputes them under current authorization, so an agent must treat each returned item as a fresh view. Available reactions can still return declared business-rejection outcomes when command preconditions do not hold.
Reaction safety
Reaction execution uses the ordinary application command service and commit coordinator. The contextual permission is not command authority. Before a new commit, RiffDB reauthorizes the target command and verifies the token’s database, history incarnation, reactive identity, canonical parameter and consumer identity, event and lease attempt, principal and capability revision, target command, and expiry against durable lease truth.
For a protected role, lease truth alone is insufficient. Immediately before a reaction command begins, the storage safe point also reloads the exact current capability revision, the trigger event’s compiler-owned policy anchor, its current source row, and bounded relationship evidence in one authoritative snapshot. A revoked capability, deleted or newly hidden row, changed role, old unanchored event, or stale lease all produce the same authorization denial and no new command admission. The nested command then performs its own ordinary transaction-current authorization and commit verification.
RiffDB derives the direct UUID or bounded-string idempotency input from the reactive module hash, contextual operation hash, event ID, command ID, and declared reaction name. It replaces caller input at the service boundary. The command’s mutations, outcome, events, causing event, inherited root request, provenance, and commit record are then atomic.
The reaction operation and its nested command are separate audited service operations. RiffDB derives a deterministic child request ID for the nested command so their audit lifecycles cannot collide, while the durable causation record continues to carry the original root request ID. Applications must not construct or substitute either identity.
If the reaction commits but its response or the following acknowledgement is lost, the event is redelivered. Repeating the reaction resolves the persisted outcome and cannot duplicate authoritative state. An expired token may resolve that exact prior outcome but cannot authorize a new commit.
Worker order
- Pull one contextual work item.
- Inspect its typed event, fresh hydration, and available reactions.
- Execute one generated reaction helper or perform separately idempotent work.
- Persist the successful result or external effect.
- Acknowledge with the exact work item evidence.
- Negative-acknowledge with a bounded delay when retry is appropriate.
Never acknowledge before protected work is durable. Never reconstruct a lease or causation token. On restore, the new history incarnation invalidates old lease evidence and the durable consumer resumes from its restored checkpoint.
Public surfaces
The five API-neutral operations are consume, acknowledge, negative acknowledge, status, and execute reaction. gRPC exposes them as bounded unary methods. Generated Rust, Go, TypeScript, Python, and MCP artifacts bind the exact reactive identity. MCP fixed tools use underscore-only names:
riffdb_contextual_nextriffdb_contextual_ackriffdb_contextual_nackriffdb_contextual_statusriffdb_contextual_react
MCP uses the same authorization and service path as every other transport. A resource update is only a coalescible, payload-free wakeup; durable consumer truth remains the source of correctness.
The singleton database-wide reactive wakeup is unavailable to protected roles
because it would expose hidden commit timing without a subscription identity.
Protected agents should long-poll riffdb_contextual_next; reconnecting or a
spurious host wakeup always returns to that durable, policy-revalidated path.
See Reactive Modules, Reactive Application Clients, and MCP for Agents.