Skip to main content
The Hooks screen drives the server’s /api/hooks surface: it registers the hooks that fire a tool when an event arrives, binds a verifier to a topic’s public ingress door, and mints trigger links — public QR URLs that fire a topic on a scan. Every hook and every trigger link fires under a bound execution key: the api-key identity the dispatch runs as. The picker is the same on both forms, and wherever access control is enabled a fire never runs as “nobody”.

Register a hook

The Register hook form names the topic to listen on and the tool to fire, then binds the execution key that fire runs as. Name, topic and tool are required, and so is the execution key wherever access control is enabled; tool kwargs, a condition, and the door-contract jqs (start_expr, cancel_expr, resume_expr, extras_expr) are optional. The Tool field is a searchable picker of the tools the deployment serves; a stored tool the deployment no longer lists stays selected and is marked “(not registered)”. A session that may not list tools types the tool’s exact name instead, and saving checks that the deployment serves it. The condition and the door-contract jqs open the jq editor. The optional Subject group (“Key this fire’s state writes to a subject; leave blank for none.”) is the same subject group the Scheduling and Tools screens show: a conversation target, a subject kind, and a Key expression — “A jq over the event payload; it must yield a non-empty string key.” The key is a templated text like the other jq fields: inline jq in the jq editor, or a stored template with its kwargs, and editing a hook keeps a stored template and its kwargs as saved. Target, kind and key are all filled or all left blank; a partly filled subject is refused on submit with its error shown in the group. See Targeting a state subject.
The Studio Hooks page Register hook form with an execution-key picker selected.The Studio Hooks page Register hook form with an execution-key picker selected.

The Register hook form: the required execution-key picker binds the api-key identity each fire runs as.

The Execution key picker lists the api keys you own; an admin sees every key. Each option shows the key’s id, its description, and its stable fingerprint. The fire runs as that key: every tool call it makes is authorized against that key’s live grants, so prefer a least-privilege service key over a human’s broad one. What the picker offers depends on how you are signed in:
  • Signed in with an api key. When the list does not hold your own identity, the picker offers it as “<id> — this session’s identity”, and choosing it reads “This runs as this session’s own identity, <id>, with its live grants.”
  • Signed in as an account. An account is not an api key, so your own identity cannot be picked. With no key of yours listed, the picker says to mint one on the API-keys tab first, and Register and the trigger-link mint stay disabled until there is a key to bind.
  • No access to list keys. The picker says which read it needs (GET /api/auth/tokens-payload) and to ask an administrator to grant it.
With access control off, the hook, trigger-link and schedule forms have no Execution key field, and the record runs as the gate-off identity.
The binding is to the key’s fingerprint, not just its id. Revoking the key kills every hook and link bound to it, and re-minting the same id does not revive the binding — the fingerprint changes, and a fire against the stale binding is denied, not run as the new key. See owned keys for the delegation model.
The execution key is the whole authority a background fire runs on. A hook on a public topic fires for an anonymous caller, so the tool runs with exactly the key’s grants and nothing more — bind the narrowest key that can do the job.
When the tool-run store is configured, every hook and trigger-link fire is recorded like a background run — it lists in that tool’s Recent background runs on the Tools screen, gettable by run id.

Edit or remove a hook

Every registered hook lists in a table, and each row carries an Edit and a Delete control. Edit opens the same form prefilled from that hook, titled Edit hook; saving it is a true update over the register door — the button reads Save changes — not a delete-and-recreate. A hook edited through an inline field keeps any id-bound condition or door-contract jq it carried, so touching the topic or tool never silently drops a gate you set by id. A hook whose stored key is not in the picker’s list opens with that key flagged not a listed key, and a line says what the server will do with it on save: an admin may bind another identity, which the server checks; for anyone else the server refuses an unlisted key, unless an api-key session’s key is its own identity. A second line compares the key with your session before Save changes: a key that is not your session’s identity is flagged not your identity (for anyone but an admin, with “so the server will refuse it on save”), and your own account is flagged not an api key. Delete opens a confirm dialog and unregisters the hook by name; it is immediate and cannot be undone. Binding a verifier to the topic is the adjacent Bind verifier form. It is admin-only: a hooks-write role registers hooks and mints links but is fenced out of setting or removing a topic’s verifier. See fire a tool from a webhook for the verifier flow. A trigger link is a minted, public URL — GET /trigger/<token> — that fires a topic’s hooks on a bare request, printable as a QR code. The Create trigger link button opens a dialog that takes the topic, an optional name, the execution key, an Also require an api key toggle, an expiry (there is no default — choose one), and optional tool params. On success the dialog renders the link’s QR, shown once.
The Studio Hooks page create-trigger-link dialog showing the generated QR code.The Studio Hooks page create-trigger-link dialog showing the generated QR code.

The Create trigger link dialog mints a public QR bound to an execution key; the QR is shown once.

The link binds its own execution key, independent of the hooks on the topic — each fired hook still runs under its own bound key, while the link’s key gates the link’s dispatch, so revoking that key kills the link. The Also require an api key toggle adds a second gate: a caller must present an api key the route admits, beside the token. It is enforced only where access control is enabled, and it never touches the topic’s own /universal_webhook/{topic} door.

The trigger-auth type

The trigger-links table lists each live link with its name, topic, bound execution key, expiry, a params indicator, the token’s hash prefix, and a trigger-auth cell naming how that door reads. The value is server-derived from the live bindings, never a stored flag:
Verified topics and trigger links are mutually exclusive. Minting a link for a verifier-bound topic is refused, and a link whose topic later gains a verifier reads as Out of service and answers the uniform 404. Treat the URL and its QR as a capability: anyone who holds it fires the topic for as long as the link lives.
Revoke a link from its row’s revoke-confirm — immediate and durable, and a restored backup cannot re-arm it. The token is shown once at creation and never stored, so a listed link’s QR is unrecoverable; to rotate a code, revoke and mint a new one. See hooks for the dispatch model, fire a tool from a webhook for the full binding-and-condition workflow from the CLI, and the tai hooks reference for the command surface.