Orkestia
Blog
DGI

How DGI works

The life of one DGI request. Who it runs as, which workflows it may reach, how Jev and the optional LLM decide, how reads become cards and writes become confirms, and how the person's answer comes back

Every DGI interface (chat, API, Living Surfaces) runs the same six steps. This page follows one request through them.

1. Who is asking

DGI takes the caller from the token, never from the request body. There are two kinds of caller:

CallerRuns asCan reach
A member of your organizationThemselvesWhat their role allows
An end user of your app, signed in with your app's tokenThemselves, in end-user lockdownOnly workflows your app exposes to end users

Every workflow DGI starts afterwards runs as that same caller, so it gets the same permissions, the same data scoping and the same audit trail as if the person had started it by hand.

2. What may run

The set of workflows DGI may consider is the intersection of three lists:

  1. The workflows registered for your organization.
  2. The allowed_workflow_types you configured for this chat profile, actor or surface (1 to 50 exact names or prefix.* patterns; required, never empty).
  3. What the caller may run.

A workflow outside that intersection cannot be chosen, proposed or drawn, whatever the message says.

3. Deciding: Jev first

Jev is a typed decision engine. It answers the questions a request raises (is this a read or a change? which workflow? which view?) with typed values in one call, usually in a few seconds. It decides with your organization's TypeSafe connection when you have one.

When Jev is not confident, what happens next is your choice:

SettingResult
llm_fallback: false (default)DGI does not guess. The person gets suggestion chips to pick from
llm_fallback: trueDGI's LLM tool loop answers, on your organization's own AI provider, within a turn budget
llm_fallback_handoffReasons that should still come back as chips even with the LLM on

Every answer reports how it was decided in decision_path, for example jev:<path>, llm or llm_fallback:<reason>, so you can see how often the model was involved.

4. Acting

Reads become views

For a read, DGI runs the workflow as the caller and builds a card from its output in code: a table, chart, KPI tiles, logs, a paged data grid, a record detail, a diagram, a timeline or a diff. The card keeps a server-side source (the workflow, its inputs and the view), so it can be refreshed, sorted, filtered or paged later without asking the model again. Row identifiers stay on the server; the person's click refers to a row by position.

Writes become proposals

For a change, DGI never runs it right away:

  1. If inputs are missing, it asks with a form that has exactly the workflow's fields.
  2. With every input known, it posts a confirm card: what will run, with which values, in plain labels.
  3. The server stores that proposal with a hash of its inputs (action_input_hash).
  4. Only a Confirm on that card, by the person it was issued to, within 30 minutes, runs it. The server runs its own stored copy, never values sent back by the client.

5. The answer

Every DGI answer has the same parts:

PartWhat it is
textA short answer in markdown that stands on its own
uiAt most one card, or none. The JSON is the same in every interface; see the card catalog
suggestionsUp to five chips. A chip sends its label as the next message
decision_pathHow the answer was decided

Answers follow the person's language when it is pt-BR, en or es, or the locale you configure.

6. The person answers the card

Clicking a card sends only the card's id, the action and the values (submit, confirm, cancel, edit, select, refresh, row_action, query). The server checks the answer against the card it stored:

  • A form or confirm answers once. A second answer is refused as ui_consumed.
  • Only the person the card was issued to may answer it.
  • Values must match the card's fields, options and controls.
  • refresh and query re-run the read with no reasoning, at most every 10 seconds and every 2 seconds respectively, and rewrite the card in place.

A refused answer changes nothing and comes back with a reason such as ui_expired or ui_wrong_author.

On a Living Surface

A Living Surface runs the same steps in a loop instead of per message. Each tick consumes signals (a click, an intent, an event, a timer), refreshes every card, and decides whether to add, remove or wait. A heartbeat ticks every 5 minutes and pauses when nobody is looking. Changes are streamed to open pages over a WebSocket. A scheduled tick never writes: a change still needs the owner's confirm.

From a conversation to a reusable workflow

When a multi-step plan proves useful, a member can freeze it with dgi.workflow.promote into a versioned composition (virtual.<uuid>@<version>). A composition runs as an ordinary workflow, with no model call. Plans with state-changing steps need an explicit confirm: true to be promoted. A Living Surface can be crystallized the same way. See Virtual workflows.