All docs

Docs · Reference

The envelope

rule-author reference

Everything a rule can read and write on txc. (the @ namespace), plus the complete WITH directive table. Companion to the TXCL reference; kept here so authors don't read processor.go to learn the field names.

What you read

Identity and routing (stamped by the chassis; read-only):

FieldMeaning
@srcInlet: http, lmtp, cron, tcp
@ridRequest id (trace correlation)
@tenant / @stackResolved by ingress; pinned per request
@ingress / @hostname_verifiedMatched ingress key / ownership-verification bit
@op / @stepThe firing op’s identity and scope (stamped on dispatched envelopes)

Per-inlet request data:

InletNamespace highlights
web@web.req.method, @web.req.url.{path,hostname,port,full,query.<k>.0,query.raw}, @web.req.headers.<name>.0 (arrays), @web.req.cookies.*, @web.req.body (base64), @web.req.host, @web.req.proto
lmtp@lmtp.rcpt[], @lmtp.msg.{subject,text,html,from[].addr,to[],headers.*,attachments[],raw} (text/html are the parsed bodies; raw is the b64 original), @lmtp.listener; spam verdict under @mail.spam.{score,verdict} when an upstream Rspamd stamped it
cron@cron.job, @cron.tenant
tcp@tcp.listener, @tcp.{local,remote}.{ip,port}

Stamped by builtins/AI ops: @computed.* (e.g. hmac-verify results), @chat.* (token telemetry).

What you write

Author-writable controls (via EMIT, or returned by an op in its JSON):

FieldEffect
@halt = trueTerminate after this scope’s merge; return the document
@goto = "stack/0" or "200"Jump to a stage (bare number = current stack)
@ttl = NLower (never raise) the remaining hop budget (fuel.md)
@web.res.statusHTTP response status
@web.res.headers.<name>Response headers (arrays)
@web.res.bodyResponse body (base64); set in a non-terminal scope it streams
@lmtp.res.{code,msg,recipients[]}SMTP verdict back to Postfix (lmtp.md)

Everything else under _txc.* is chassis-owned — writes to reserved fields (tenant, fuel_used, computed.*, …) are rejected by the guard. Payload fields (no _txc. prefix) are always yours; fields starting with _ are dropped from the final answer by convention.

WITH — the complete directive table

KeyApplies toMeaning
timeoutany EXECPer-call wall clock (ms or "2h"); capped by --op-timeout-max
methodhttp(s)HTTP verb override (default POST)
secrets.headers.<h>.secret / .formathttp(s), builtinsSplice a stored secret into the request; format = "Bearer {}" templates it (runbook)
secrets.body.<path>.secrethttp(s)Same, into the JSON body
mode = "async"http(s), mcp+Worker acks 202 now, calls back later (continuations)
mode = "continuable"http(s)Answer synchronously if quick; promote to a continuation at the deadline
continue_aftercontinuableThe promotion deadline (default --continue-after-default, 5s)
redact / omitanyScrub paths from trace artifacts (runtime data untouched)
debug = trueanySurface extra op debug detail to the trace
prompt, system, messages, model, provider, schema, intent, limits.*ai://chatThe chat request — see ai.md

SET vs SET PRE

SET writes fields onto the event before dispatch and they persist downstream. SET PRE decorates only this op’s input — the value never merges forward. Use it for scratch values a prompt template or handler needs once:

SET PRE @body_text = .ticket.description
WITH prompt = "Summarize: {{@body_text}}"
EXEC "ai://chat"

Conditions: the full operator set

== != < <= > >= (numbers, lexical strings), =~ / !~ (regex, /pattern/ literals), && and ||, prefix !, parentheses for grouping. A comma in WHEN is an AND.

PRIORITY — sharper than “tie-breaker”

Default 0. When any matching op at a scope declares a priority above the others, only the highest-priority op(s) run — equal priorities fire in parallel as usual. Use it to let a specific handler preempt a catch-all at the same scope, without restructuring scopes.

Edit this page · View as markdown