Orkestia
Blog
Chat

Cards, live updates and proactive posts

Refresh a read card, keep it live, act on table rows, use the / command palette, run cards, and post cards from outside the chat with buzz.actor.post-view and buzz.message.post

A card from a DGI actor is not a static answer. Read cards refresh and stay live, table rows carry actions, data grids sort and page on the server, runs update in place, and your workflows can post cards on a schedule. Every card is described in the card catalog. Structured chat is part of DGI and is Alpha.

Read cards

A table, chart, KPI tiles or logs card that DGI built from a read it can run again is a read card. The server keeps what produced it (the workflow, its inputs, the view, each row's id) next to the card. None of that is posted: the chat only sees labels and values.

Refresh

The card's toolbar shows Refresh. Pressing it runs the same read again, with exactly the same inputs, and rewrites the card in place with a "refreshed at" time.

  • The read runs as the card's stored principal, never as the person who pressed the button: the person who asked, re-checked now, or for a posted card the organization member who posted it.
  • The read must still be in the actor's allowed_workflow_types, and it must be a read. A card whose workflow left the scope refuses (card_scope_changed).
  • At most one refresh per card every 10 seconds.
  • A refresh is not a new message: no reply, no notification, no progress line.
  • A read card can be refreshed for 7 days.

Live

Live keeps a read card current by itself.

  • It starts when the person presses Live (every 60 s, for 30 minutes), or when the message asks for it ("keep it live", "ao vivo", "tempo real").
  • The interval is 60 to 900 seconds, and a live card stops after 60 minutes at most.
  • The card is edited only when the data changed.
  • The toolbar shows a pulsing dot and "live, every 60 s until 14:30". Stop ends it early.
  • It also stops when the actor is paused or detached, when the read leaves the scope or its principal no longer qualifies, or after three failed reruns in a row.

Row actions

On a table, DGI looks at the actor's other allowed workflows. Each one whose schema needs exactly one id input matching the rows' id becomes a row action, up to four, with a localized label. For tickets that is typically Details (ticket.get), Comment (ticket.comment) and Assign (ticket.assign).

Pressing a row action is a normal turn as the person who pressed it, with the row's id filled in by the server:

  • a read shows its view;
  • a write with missing inputs asks with a form;
  • a write with everything it needs posts a confirm card.

The structured confirm stays mandatory for every write. Below 480 px of card width, each row gets a menu button instead of inline buttons.

Sort, filter, page and controls

A datagrid, the query console and any read card with view controls (a date range, a status filter, a group-by) answer with the query card action. The server checks the values against the stored card, re-runs the same read with only those values, and rewrites the card in place, at most once every 2 seconds. See View controls and the query action.

The / command palette

Typing / at the start of the composer opens the actor's commands: one per allowed workflow the person may run, with a title, a description and a read or write badge. Picking one sends /<command>, and DGI maps it straight to the workflow: a read runs, a write asks for its inputs. In a channel, mention the actor first (@Support /ticket-search); in a DM or a thread with the actor, / is enough.

The commands come from the commands entry point. Spaces created before it existed get it when you re-run buzz.space.enable.

Run cards

When DGI starts a workflow in the conversation (usually right after a confirm), it posts a run card: the workflow, its status, its current state and its steps. The card is edited in place on every change until the run ends, for up to 30 minutes. It shows only states, step timing and a short failure code, never the run's data or error text, and only for runs of the space's organization that DGI started in that conversation.

Proactive cards

Your workflows can post cards without anyone asking.

buzz.actor.post-view: a refreshable read card

Runs one read and posts it as a read card signed by the actor. People can refresh it, act on its rows and make it live, exactly as with a card DGI drew in a reply.

start_workflow("buzz.actor.post-view", {
  "space_uuid": "<space uuid>",
  "attachment_uuid": "<attachment uuid>",
  "channel_id": "<channel id>",
  "workflow_type": "ticket.search",
  "input": {"status": ["blocked"]},
  "kind": "table",
  "title": "Blocked tickets this morning",
  "content": "Good morning. These are waiting on someone:",
  "live": {"every_s": 300, "until_minutes": 60}
})
InputMeaning
workflow_type, inputA read in the actor's DGI allowed_workflow_types. Writes are refused
kindtable, chart, kpi or logs
group_by, chartFor chart and kpi: the field to group by, and bar, line or pie
title, contentThe card title and the text above it
liveOptional {every_s: 60-900, until_minutes: 1-60} to start it live
  • No LLM. The view is built deterministically from the read.
  • The actor needs a DGI responder. Its scope is what the card may read.
  • Who it runs as. The organization member who started it. A scheduled run has no person, so it runs as the admin who configured the responder, re-checked as admin.
  • Schedulable. Put it on a schedule for a morning KPI post or a daily list of blocked tickets.
  • Channel rules and the reply ceiling are the same as for buzz.message.post.

buzz.message.post with ui: a card on any post

buzz.message.post takes an optional ui:

start_workflow("buzz.message.post", {
  "space_uuid": "<space uuid>",
  "member_uuid": "<the actor's member uuid>",
  "channel_id": "<channel id>",
  "content": "This week's signups",
  "ui": {
    "renderer": "kpi",
    "render": {"tiles": [{"label": "Signups", "value": 128, "delta": "+12%", "trend": "up"}]}
  }
})
rendererBehavior
table, chart, kpi, logs, linkDisplay only. Checked by the same rules as a DGI card. Not refreshable: use buzz.actor.post-view for that
formNeeds for (the member uuid or relay public key of one active person) and pending_input. The form is stored for that person like a DGI form; when pending_input names its workflow and the actor has a DGI responder, the submit continues in DGI
confirmRefused (ui_confirm_not_allowed). A confirm stands for a proposal DGI computed and checked. Post a form instead, and DGI proposes after the submit

Values you put in render are posted as you send them, after validation. Keep secrets and internal ids out of them.

Ask your AI assistant

prompts
Every weekday at 9:00, post a table of blocked support tickets in #support as my Support actor with buzz.actor.post-view, live for 60 minutes. Show me the schedule and the call before creating anything.

Post a KPI card with this week's signups in #general as my actor with buzz.message.post and a ui block. Confirm the content with me first.

Why did my live card stop updating? Explain the stop conditions and what I should check.

For AI agents

RuleDetail
Refreshable cardsUse buzz.actor.post-view. buzz.message.post cards are display only
Scopepost-view reads only types in the actor's DGI allowed_workflow_types, and only reads
ConfirmsNever post a confirm card. Post a form addressed to one person
Confirm with the userBoth verbs post in a shared channel and count against the actor's reply ceiling. Show the call first
Schedulespost-view is schedulable; a scheduled run acts as the admin who configured the responder