Skip to content

The LLM-workflow runtime (executor B)

Executor B runs an intent as an in-band model workflow: a Hub-hosted Claude Messages-API loop whose every tool call passes the same gate and can escalate to you. It is the alternative to spawning a Commander, for work that is "read, reason, act" rather than "get a machine and build."

The defining property is in-band by construction: because the Hub itself makes every model call and dispatches every tool, it sees and controls every step. There is no external session to observe through a side channel — the loop is the Hub.

Status

The underlying model tool-loop, the Messages-API client, cost accounting, the cron/event triggers, and the SSRF-safe egress path are live in the platform. The workflow definition, the run executor, the universal HTTP connector, and the A/B selector described here are merged on main but dark behind a default-OFF flag — dev-safe, and not yet activated in production.

The worked example

"Every morning, summarize the newsfeed list and post it to my site."

A saved workflow with a schedule trigger: the model reads the list (a fetch action), summarizes it (a model step), and posts it (an HTTP action). Each action is gated allowed / needs-approval / denied. If the post is gated needs-approval, it escalates to you and resumes on approval. No Commander is ever spawned — a "post to my site" job needs only the model plus the gate.

The runtime loop

At heart the runtime is a bounded model-plus-tools loop:

flowchart TD
    T[Trigger fires] --> R[Resolve model + build system prompt<br/>role · injected knowledge · trigger context]
    R --> L[Build tools = the workflow's allowed actions]
    L --> C[model call]
    C --> S{stop reason}
    S -->|tool_use| G{{gate each action}}
    G -->|allow| DISP[dispatch → tool_result]
    G -->|deny| DR[model-readable denial → tool_result]
    G -->|needs approval| PAUSE[pause + escalate]
    PAUSE -->|approved| DISP
    DISP --> C
    DR --> C
    S -->|stop| OUT[emit result to destination]

Each turn: build the request with the allowed tools, call the model, and for each tool-use block the model emits, gate the action. On allow, dispatch it and feed the result back. On needs-approval, pause the run and escalate. On deny, feed a model-readable denial back as the tool result and let the loop continue in a degraded state — it never bypasses. The loop is bounded by a maximum iteration count and a per-run cost budget.

What a workflow is

A workflow is a saved, per-user definition — one row per saved workflow, owned per user (the tenancy key lives here). Its fields:

  • model — an explicit model or a role/task-type the router resolves, plus a thinking level.
  • role / prompt — the system prompt and persona for the loop.
  • allowed_actions — the action allow-set: an explicit list of tool names, integration verbs, and named HTTP-connector actions the workflow may call. Default-deny: only listed actions are offered to the model as tools, and each is independently gated at call time.
  • trigger — one of schedule (cron), event (a bus predicate), or on_demand.
  • output / destination — where the result goes: a result message, a report, an alert push, or a named HTTP destination.
  • gates — the per-workflow, per-action policy, composed with the estate's gate model.
  • budget — a per-run cost ceiling (and optionally per-day).
  • cred_refsreferences to the credentials the workflow may use, never inline secrets (see Credential scoping).

Each execution is a separate run record, moving through pending → running → awaiting_approval → done / failed / denied, stamped with trigger provenance, the accumulated token usage and cost, and a transcript pointer.

The action vocabulary

A workflow's tools come from one uniform vocabulary so that everything is "configured the same way":

  • Hub tool surface — the existing set of agent-action tools.
  • Integration verbs — per-integration outbound connectors with encrypted credentials.
  • A universal HTTP/webhook action — a typed http_request{method, url, headers, body} for "post to my site" / "curl," behind SSRF protection and the gate.

Spawn is optional: if an allowed action happens to be a spawn action, the loop dispatches it exactly like any other action, through the same gate — and only then is a Commander spun up. Executors A and B are not mutually exclusive at the action level; the selector only picks the top-level executor.

Safety properties

The runtime inherits the platform's invariants and adds none weaker:

  1. Default-deny at every action — only allow-set actions are offered; each is independently gated; anything unlisted is denied.
  2. The workflow model never self-approves — it can propose a gated or irreversible action, never approve it. Prod deploys and external publishes always pause for you.
  3. Fail-closed — an approval timeout defaults to deny; a gate or resolution fault denies; a denied action degrades the run, it never bypasses.
  4. Verified identity, injected — the action's credential is injected server-side over the model-supplied params; the model never sees a raw secret (the confused-deputy defense).
  5. Bounded — per-run cost and budget caps, bounded loop iterations, a per-turn dispatch budget, and a timeout.
  6. SSRF-safe egress — every external action is pinned through resolved-IP classification with DNS-rebind defense.
  7. Audited and observable in-band — every action, gate decision, and approval is on the tamper-evident audit chain, and the whole run is visible in the Hub.
  8. Irreversible ⇒ human — prod, irreversible, or external-publish actions always escalate to you.

Provider note

Tool-use workflows run on the Claude Messages API, which is where the multi-turn tool loop lives. Non-tool "summarize" steps can use provider-flexible completion; a multi-provider tool-use bridge is a larger, separate effort and is out of scope for the first version.