Orkestia
Blog
App Enablement

Compositions — use, invoke, share

Save a virtual workflow, invoke it, expose it to your app's users, and let them run it with their Sign in with Orkestia JWT.

A composition (a virtual workflow) is your business logic as structure, not code: layers of existing catalog workflows, with every input wired from input, step, or static. After composition.save it is a normal type:

virtual.<composition_uuid>@<version>

That is the only kind of workflow you can share with an app end-user. Raw catalog types are not startable with an end-user JWT.

Contract on reference.orkestia.dev/composition. Authoring detail: Creating & exposing virtual workflows. To put a closed-set gate in front of later steps, use Typed decisions with TypeSafe as the first layer.

What you do

  1. Author — JSON, DGI, the console DAG builder, or ltinteg-devkit vw.
  2. Validate / save — composition.validate then composition.save (org-member token or MCP).
  3. Invoke — start virtual.<uuid>@N as yourself to prove it.
  4. Share — identity.app.expose-virtual-workflow so your app's users can start that version.
  5. Enable the user — they sign in with @orkestia/auth and your UI starts the virtual with their JWT.

Do not pass organization_uuid or actor. The server fills those from the token.

1. Author and save

input_mapping is an object. Keys are the step's parameter names. Live dialect:

{
  "name": "list-my-orders",
  "layers": [
    {
      "name": "query",
      "steps": [
        {
          "name": "rows",
          "workflow_type": "data.appdata.record.query",
          "input_mapping": {
            "table": { "source": "static", "value": "orders" },
            "page_size": { "source": "input", "field_name": "page_size" }
          }
        }
      ]
    }
  ]
}
sourceWho sets itUse for
staticYou, at authoring timeTable, connection, tenant column — the user must not see or change this
inputThe caller at invoke timeFree inputs only (a filter, a page size)
stepA previous step's outputChain layers
// MCP or org-member SDK
composition.validate({ definition })
composition.save({ name: "list-my-orders", definition })
// → { composition_uuid, workflow_type: "virtual.<uuid>@1", version: 1 }

composition.version appends @2 on the same lineage. composition.activate re-validates and sets active. Browse ops on reference — Composition domain.

Every step you will expose must be end_user_eligible in the catalog. Expose fails with ineligible_steps otherwise.

2. Invoke (you)

Org member, API token, or MCP — same type name:

import { LtIntegWorkflowsClient } from "@ltinteg/workflows-sdk"

const client = new LtIntegWorkflowsClient({
  baseUrl: "https://workflow-api.orkestia.dev",
  token: process.env.ORKESTIA_TOKEN,
})

const run = await client.start("virtual.<composition_uuid>@1", {
  page_size: 20,
})
const { state_data } = await run.wait()

REST: POST https://workflow-api.orkestia.dev/api/workflows/start with Authorization: Bearer … and { "workflow_type": "virtual.<uuid>@1", "initial_data": { … } }.

MCP: start_workflow("virtual.<uuid>@1", { … }) after whoami().

3. Share with an app user

Provision the app first (Sign in with Orkestia / agent prompt). Then expose that version:

identity.app.expose-virtual-workflow({
  identity_app_uuid: "…",   // from identity.app.provision
  composition_uuid: "…",    // from composition.save
  version: 1,
})

Revoke with identity.app.unexpose-virtual-workflow (same ids; version optional).

An end-user token can start only virtuals you exposed — never data.appdata.record.query by catalog name.

4. Enable the user to use it

In their browser: Sign in, then start the virtual with their JWT. Never put an org-member token in the page.

import { createOrkestiaAuth } from "@orkestia/auth"
import { LtIntegWorkflowsClient } from "@ltinteg/workflows-sdk"

const auth = createOrkestiaAuth({ clientKey: "orkestia_…" })
const session = auth.getSession()

const client = new LtIntegWorkflowsClient({
  baseUrl: "https://workflow-api.orkestia.dev",
  token: session.token,
})

const run = await client.start("virtual.<composition_uuid>@1", {
  page_size: 20, // free inputs only
})

Orkestia injects the end-user principal immutably. Ownership / workspace on App Data is forced from that identity.

App user  →  @orkestia/auth  →  JWT
        →  start virtual.<uuid>@N
        →  only their rows

Paste this into your agent

Copy into Cursor, Claude, or any client connected to https://mcp.orkestia.dev/mcp:

Enable this app's users to run an Orkestia composition.

You are connected to the Orkestia MCP (https://mcp.orkestia.dev/mcp).
If you are not, stop: https://docs.orkestia.dev/reference/mcp-integration

1. Call whoami() first. Do not ask me for organization_uuid.
2. If I do not already have an identity app, follow
   https://docs.orkestia.dev/app-enablement#paste-this-into-your-agent
3. Ask me what the composition should do, and the free inputs vs static secrets.
4. Author a definition using input_mapping objects (not input_mappings arrays):
   { "<param>": { "source": "input"|"step"|"static", "field_name"?, "step"?, "value"? } }
   Every step I will expose must be end_user_eligible.
5. start_workflow("composition.validate", { definition }). Fix errors.
6. start_workflow("composition.save", { name, definition }).
   Take composition_uuid, workflow_type, version from the terminal output.
7. Invoke it once as me: start_workflow("virtual.<uuid>@<version>", free inputs).
8. Share with app users:
   start_workflow("identity.app.expose-virtual-workflow", {
     identity_app_uuid, composition_uuid, version
   })
9. Wire the frontend: createOrkestiaAuth({ clientKey }) + start the virtual
   with session.token. Never put an org token in the browser.
10. Tell me composition_uuid, version, workflow_type, and the files you changed.
static mappings are how you share a capability without sharing a credential. The user never sees the connection or the table name.

Next

Sign in with Orkestia

Hosted login + @orkestia/auth so the user has a JWT.

End-user data

Why only exposed virtuals are startable.

Expose App Data

Same pattern for declared tables.

Reference — compositions

Definition format, composition.* ops, MCP invoke.