Atrium Actions overview
How to choose the right trigger, host, and template without guessing.
An Atrium Action is a JavaScript handler bound to a ZITADEL execution. Atrium stores the source, the runtime executes it, and ZITADEL calls the matching endpoint when the configured condition fires.
Start here
Pick the first statement that matches your goal:
| If you need to... | Use | Why |
|---|---|---|
| React after something happened | Event | Best for onboarding, provisioning, notifications, and audit fan-out |
| Change claims in userinfo / ID token | Function: preuserinfo | Synchronous claim mutation |
| Change claims in access tokens | Function: preaccesstoken | Synchronous access-token mutation |
| Change SAML attributes | Function: presamlresponse | Synchronous SAML response mutation |
| Intercept a specific ZITADEL API request/response | Request / Response | Narrow, advanced webhook routing |
The most important trap to avoid is this:
- Events are not claim hooks.
- Functions are not generic lifecycle automations.
If the old v1 script used api.v1.claims.setClaim(...), its v2 replacement is
almost certainly a Function, not an Event.
OMMAX patterns that are actually real
1. First-time onboarding
Use EVENT:user.human.added.
Examples:
- create or populate an Atrium group
- append a default app grant
- send a welcome notification
2. Login-time catch-up for existing users
Use an observed login event such as EVENT:oidc_session.added.
Important:
- this event usually gives you
userIDplus session/client context - it does not reliably carry custom user attributes like
department - fetch persisted user metadata explicitly via
ctx.zitadel.users.getMetadata(...)
3. flatRoles parity
Use:
FUNCTION:preuserinfo- and, if needed by consuming apps,
FUNCTION:preaccesstoken
This is the right home for:
urn:ommax:departmentlitellm_team_idsmy:zitadel:grants
Trigger slots in Atrium
ZITADEL can route multiple Targets for the same condition. Atrium's runtime does not merge multiple scripts for the same exact trigger.
In practice that means:
- many DRAFT scripts may point at
FUNCTION:preuserinfo - only one ACTIVE script can own
FUNCTION:preuserinfo - the same is true for exact Event names like
EVENT:user.human.added
If you need two behaviours in one live slot, compose them into one script.
Event groups vs exact script triggers
ZITADEL supports Event execution conditions at three levels:
allgroupevent
That is a routing scope in ZITADEL, not an inheritance model inside Atrium.
So:
- an Execution on
all eventscan still feed Atrium - Atrium then matches scripts by exact
triggerType:triggerName session.addedandoidc_session.addedare different slots
Do not assume:
- a child event implies a parent event
oidc_session.access_token.addedalso matchesoidc_session.addedsession.addedis a safe shorthand for "real app login"
Return values by trigger type
| Trigger type | Does ZITADEL care about the body? | What to return |
|---|---|---|
| Event | Usually no business effect from the body | Any diagnostic object you want to inspect in test runs |
| Function | Yes | A valid mutation payload such as { setClaims: { ... } } |
| Request | Yes | Modified request or null to pass through |
| Response | Yes | Modified response or null to pass through |
For Functions, the returned JSON is the point of the integration.
For Events, the important work usually happens through side effects such as:
ctx.atrium.groups.*ctx.zitadel.users.*ctx.fetch(...)
Where each class of script belongs
| Kind | Recommended home |
|---|---|
Atrium lifecycle automation (user.human.added, user.grant.added, oidc_session.added) | Atrium Actions runtime |
Load-bearing token/userinfo mutation (flatRoles) | Dedicated Zitadel-adjacent function endpoint is the target architecture |
Current OMMAX reality:
- the Atrium runtime can execute Function scripts
- that is useful for iteration and migration
- but auth-path functions still deserve a higher bar for latency and failure isolation than normal Event scripts
Recommended templates
Start with these first:
auto-group-by-departmentprefill-from-entraflatten-rolesflatten-roles-access-token
Use these as integration patterns, not drop-in business logic:
welcome-emailscim-fanout-on-grantsentry-grant-fanoutdokploy-grant-fanoutslack-notify-on-grant
For the catalog with readiness notes and prerequisites, see Action templates.