Sources, consumers and triggers
A source is a named stream of events. It is what the owner grants and what a consumer reads. There are two ways to declare one:
sourcesinconnecting, fed by one of the realm’s channels:{ channel: "updates", description: "..." }. The description is required and may not be blank; the owner reads it when deciding.dataPipes.sources, a stream the realm’s own handlers publish to:{ stream: "events", type: "note.changed" }. At most 128; the name,streamandtypeare each at most 256 bytes.
A name may be declared one way or the other, never both.
A consumer is a handler that reads one source. Declare it in connecting
({ source, handler, assistant? }) or in dataPipes.consumers ({ handler }, at most 128). A
dataPipes consumer’s handler is written namespace.verb, and must be a handler the realm
declares: defineRealm checks it at compile time, and synth refuses one the realm does not
declare, since the host refuses that consumer and every trigger bound to it. dataPipes takes only sources and
consumers, and data-pipes.yml is at most 64 KiB.
The consumer is handed each event as its first argument and as ctx.frame, and the host
checkpoints only after the handler succeeds. Delivery is at least once, so give every effect its
own idempotency key. assistant: true asks for the separate grant that lets the consumer call
ctx.assistant.chat; the owner also pairs each sender the assistant may answer (see
pairing).
A consumer may read another realm’s source. The owner grants each consumer one exact source: a host channel’s source, a source from the same realm, or a source another installed realm declares. The realm does not name the other realm; the owner picks the source at approval, and the consumer receives whatever that source carries.
A trigger narrows what a consumer sees and says what it may do:
handlers: { record: { namespace: "notes" }, index: { namespace: "notes" },},dataPipes: { sources: { changes: { stream: "notes", type: "note.changed" } }, consumers: { index: { handler: "notes.index" } },},triggers: { "on-change": { source: "changes", consumer: "index", mode: "observe", input: ["eventId", "payload"] },},- The key is
[a-z][a-z0-9-]{0,63}.sourceandconsumernamedataPipesdeclarations, which synth checks. inputpicks fromoffset,eventId,streamId,type,occurredAt,gapandpayload, each once; left out, the consumer gets all seven.descriptionis at most 512 characters.mode: "observe"lets the handler read and refuses, for the whole invocation, every publish, every write proposal and every approved API write.mode: "apply"type-checks, and the host refuses it at bind time.- One trigger naming a missing source, consumer or handler stops delivery to every consumer of that installation until it is fixed, so check trigger names with care. The full behaviour is in the trigger profile.

