The dispatch model
A hook is a small record: a topic, the tool to run, the keyword arguments to pass it, and an optional condition and expression over the payload. Registration is keyed by topic, so one topic can drive several hooks and the manager dispatches to all of them:condition and expr are jq, and they say so in the schema: both carry the
x-tai42-expression annotation, which
names the input document and what the result is consumed as. An editor reads that
annotation and offers the visual jq editor on the field
without being told which fields are expressions.
Naming a hook and topic
A hook’stopic is dispatched as one path segment of the public webhook URL
(/universal_webhook/{topic}), and its name addresses the hook on every
management and delete door. Both must be a single URL-safe path segment: match
^[a-z0-9][a-z0-9_-]*$ — begin with a lowercase letter or digit, then lowercase
letters, digits, underscores, and hyphens only. No dots, slashes, uppercase, or
whitespace — a / or a stray character would mint a record no delivery could
route to and no door could address. The value is never sanitized: a violation is
rejected at registration with a 400, its message naming the offending field and
the pattern.
The ingress door
External systems deliver events to the publicPOST /universal_webhook/{topic}
door. The payload parser accepts any content type, and the matched hooks run in the
background — the ingress returns without waiting for the tools to finish.
Targeting a state subject
A hook may carry an optional subject so a state write during the fire is keyed and attributed to the hook. The subject names a conversation-target scope, a subjectkind, and a key_expr — a jq expression
evaluated over the event payload at fire, which must yield a non-empty string:
hook with the hook’s execution key as the actor. A key_expr that yields nothing
fails the fire loudly, like any hook error. Leaving subject unset leaves the fire
with no ambient state context, so a state tool it calls must carry an explicit
subject. The Studio’s Hooks screen surfaces the subject as an
optional group on the register form.
Managing hooks live
Hooks are managed at run time, with no restart. The manager comes in an in-memory and a Redis-backed form, and the authed management doors (GET/POST/DELETE
/api/hooks) are a thin skin over it — the same manager the hook-management
operations drive. Register and remove hooks from the
CLI:
register takes the whole hook record — topic, tool, kwargs, and an optional
condition — as one --params JSON object; its full option set is on the command
itself:
examples/hooks/register_hook.sh
PUT/DELETE /api/hooks/topics/{topic}/verifier).
See the fire-a-tool-from-a-webhook guide for
the binding-and-condition workflow, triggers and webhook
verifiers for authenticating the ingress, and
the HTTP API reference for the hook routes.
