Register and secure it
Pushed code is a definition. It is not runnable yet.
Registration turns a definition into a workflow and sets its envelope: the secrets a run can read, the hosts it declares, whether it can call a model, and whose identity it acts as. This is the security decision, so it takes a signed-in person, not a machine.
Register the workflow
Section titled “Register the workflow”In the app, open Workflows and select Register workflow.
| Field | Value for the example | What it does |
|---|---|---|
| Definition | the pushed acme-reconcile project |
The list of type: workflow definitions in your organization. |
| Workflow class | ReconcileInvoices |
The exported @PersistentObject class to start. It must match the name in the code exactly. |
| Allowed secrets | ACME_API_KEY |
The only names that secrets.get() resolves. |
| Network allowlist | api.acme.com |
The hosts the code reaches. |
| Chat access | on | Gates urai:chat. With it off, extract() and chat() get nothing. |
| Run as | empty | Whose integration connections a run reaches. See below. |
Urai cannot list the classes in a definition for you. UraiJS registers them when the code runs, so the class name is a contract you record here. A name that does not match fails at the first run, not at registration.
The same registration over the API:
curl -X POST https://chat.app.urai.dev/api/workflows \ -H 'authorization: Bearer <session token>' \ -H 'content-type: application/json' \ -d '{ "name": "Reconcile overdue invoices", "uraijs_tool_id": "...", "object_type": "ReconcileInvoices", "allowed_secrets": ["ACME_API_KEY"], "net_allowlist": ["api.acme.com"], "allow_chat": true }'GET /api/workflow-definitions lists the definitions you can register from, and
gives you the uraijs_tool_id.
Who can register
Section titled “Who can register”Registration and every edit need a signed-in person with authority over the target:
- With a
project_id, the person must be able to manage that project. - Without one, the person must be able to manage the organization.
An org API key cannot register a workflow, edit one, or change its envelope. A machine credential does not get to widen what it may do. Starting runs and deciding approvals do accept an API key, which Triggers and runs covers.
The envelope belongs to the workflow
Section titled “The envelope belongs to the workflow”The envelope sits on the workflow, not on a trigger. Several triggers can start the same workflow, and none of them can widen it. A trigger changes what a run receives, never what a run may do.
Run as
Section titled “Run as”This field decides whose integration connections a step reaches when it calls
secrets.get().
Leave it empty and the run resolves org-shared connections only. It can never reach anyone’s personal credentials. For invoice reconciliation that is correct: the Acme key belongs to the team.
Pin an identity when the workflow must act as a specific person, such as a workflow that files tickets under someone’s account.
A caller can never choose the identity. Not in the request body, and not in a header. A webhook secret is a shared credential and an API key is a machine, so either one choosing an identity would be an escalation. Someone who can already manage the project configures the delegation in advance.
A trigger can override the workflow’s default for the runs it starts. See Run as on a trigger.
How a secret resolves during a run
Section titled “How a secret resolves during a run”When a step calls secrets.get("ACME_API_KEY"), Urai runs four checks in order.
- The run must be active. A cancelled or finished run resolves nothing further. Cancelling a run is therefore an immediate cut-off, not a request to stop.
- Reserved
urai:names are capabilities, not stored secrets.urai:chatresolves only when chat access is on for the workflow. - Any other name must be in the allowed secrets list. A name outside the list fails, whether or not the integration exists.
- The integrations service resolves the name for the acting identity, or for org-shared connections when there is none.
A name that fails any check makes secrets.get() reject, and that step fails.
None of this is checked at registration. You see it in the run.
This is the most common reason a workflow that ran on your machine fails on the server. Add every name the code reads to the allowed secrets list, and connect the matching integration.
About the network allowlist
Section titled “About the network allowlist”The network allowlist records the hosts your workflow code reaches, and Urai carries it to the runtime with every run.
Today the persistent workflow runtime does not enforce it. Treat the list as a declaration that documents the workflow and prepares it for enforcement. The control that bites now is the allowed secrets list: code that cannot resolve a credential cannot do much with a host it reaches.
Editing and disabling
Section titled “Editing and disabling”PATCH /api/workflows/{id} updates the envelope. Any field you omit stays as it
is.
DELETE /api/workflows/{id} disables the workflow. It is not deleted, and the
run history stays readable.
Both need a signed-in person, the same as registration.
Next: start runs with a trigger.