Skip to content

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.

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:

Terminal window
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.

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 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.

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.

When a step calls secrets.get("ACME_API_KEY"), Urai runs four checks in order.

  1. 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.
  2. Reserved urai: names are capabilities, not stored secrets. urai:chat resolves only when chat access is on for the workflow.
  3. Any other name must be in the allowed secrets list. A name outside the list fails, whether or not the integration exists.
  4. 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.

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.

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.