Learn

How Mobius works

Mobius runs loops: versioned definitions that start from triggers, execute ordered steps, and leave behind inspectable runs.

If you remember one shape, make it this one:

organization
  project: platform
    agents: Triager, Scout
      toolkits, skills, tables, environments
    loop: morning-brief
      version 1
        triggers: schedule, event, http, manual
        steps: agent, action, sleep, wait_for_event, interaction, loop
      run: run_01...
        step records, event stream, context, artifacts

A project is the workspace boundary. A loop is the thing you author. A run is one execution of a published loop version. A step is one bounded piece of work inside that run.

Resource hierarchy

Everything customer-visible is scoped to a project. That includes loops, runs, agents, workers, integrations, secrets, tables, artifacts, API keys, roles, and audit records.

Loops are versioned. Publishing a version makes that version runnable and supersedes the previous published version. Existing runs keep their original version, so a run started on version 3 never changes behavior because you publish version 4.

Agents are project resources too. An agent can run inside a loop step, but it is not owned by that loop. The same agent can also have agent sessions, table grants, toolkits, skills, and managed environment access.

The run lifecycle

trigger fires
  Mobius creates or reuses a trigger-fire record
  Mobius starts a run against the latest runnable loop version
  each step moves from pending to running
  step output is saved into run context under save_as or the step key
  later steps read inputs and context through templates
  artifacts are published against the active run and step
  the run ends as completed, failed, or cancelled

The run event stream is the operator view. It records events such as run.started, step.started, action.completed, artifact.created, limit.reached, run.completed, and run.failed with a per-run sequence number. The app, CLI, and HTTP API all read the same event log.

Step types

Step typeWhat runsWhen to use it
agentOne bounded agent turn. The agent receives instructions, may call tools, and returns an output.Use this when judgment, tool use, or synthesis belongs inside the run.
actionOne deterministic action call with rendered parameters. It does not start an LLM turn.Use this for Slack posts, GitHub labels, table writes, worker code, or any exact side effect.
sleepA timer. The run suspends until duration or until.Use this when time is the condition.
wait_for_eventA source-event subscription. The run suspends until event_type matches, optionally with source_id, match, condition, and payload_mapping.Use this when another system needs to answer before the run continues.
interactionA request to humans or agents using request_information, request_approval, or request_review.Use this when the run needs a decision or response in the Mobius inbox.
loopA fire-and-forget child run of another loop in the same project.Use this when one loop should hand work to another loop without waiting for the child result.

Authored specs cannot include cleanup steps. Mobius materializes cleanup from the loop's cleanup block and from resources it allocated for the run.

When in doubt, start with one agent step followed by one action step. Add waits only when the outside world actually needs to answer.

Triggers

Triggers belong to loops. When a trigger fires, Mobius starts one run or applies the loop's concurrency policy if another run is active.

Trigger kindStarts fromUse when
scheduleA cron-like schedule.The loop should run on a clock, such as morning-brief at 7:00 on weekdays.
eventA public source event such as github.pull_request.opened or table.row.inserted.A provider or Mobius resource already emits the event you need.
httpAn inbound POST to the trigger's delivery URL.Another system can call Mobius directly.
manualA user, CLI command, or API request starts the run.You want an operator-controlled start path.

Trigger config becomes run input. For example, a GitHub event trigger starts a run with the event payload and metadata under the input envelope, while an HTTP trigger forwards the request payload.

Context and templates

Every step can receive an input object. String leaves in that object may use Go text/template expressions against run inputs and prior step context:

input:
  issue_title: "{{ .inputs.event.issue.title }}"
  triage_label: "{{ .context.classify.label }}"

Step output is saved under save_as. If save_as is omitted, Mobius uses the step key. This keeps later prompts and action parameters explicit:

steps:
  - key: classify
    kind: agent
    save_as: triage
    config:
      agent_id: agt_triager
      instructions: "Classify the issue and return JSON."
  - key: label
    kind: action
    config:
      action_name: github.issue.add_labels
      parameters:
        label: "{{ .context.triage.label }}"

Agent transcripts are not shared between steps by default. If one agent's work should guide a later step, have the producing step return a compact structured output and save it in context.

Artifacts

Artifacts are durable files produced by a run: markdown reports, JSON, images, audio, PDFs, source files, or anything else a worker publishes. They are separate from a managed environment's scratch filesystem.

Workers publish artifacts with an active lease token, so Mobius can derive the run, step, worker session, attempt, and visibility. That is why the run page can show "Scout produced brief.md during summarize" without trusting caller-supplied lineage.

Use artifacts for outputs humans or later systems should inspect. Use run context for small structured values that later steps need.

Why every run halts

Mobius is built around unattended execution, so every path needs a stop condition. These are the bounds enforced today:

BoundWhat happensWhy it exists
defaults.wall_clock_timeoutMobius stamps a run deadline. The reaper fails the run with wall_clock_deadline_exceeded after the deadline passes.A run should not occupy runtime state forever because one step wedged.
Step retriesretry.max_attempts defaults to 1. Retries stop when attempts are exhausted.Transient failures get another chance, but an action cannot loop forever.
Per-run step capBilling policy rejects an oversized plan at start, and the engine emits limit.reached if a running plan crosses the cap.Loop expansion and child-step materialization need a hard ceiling.
Concurrency policyallow, queue, skip, or replace decides what a new trigger fire does while another run is active.Overlap is a product choice, not an accident.
Suspended-step timeoutWaiting steps can set timeout.duration. Today timeout.on_timeout supports fail, so a timed-out wait_for_event or interaction fails the waiting step.A run waiting on another person or system still needs a final state.
CancellationOperators can cancel a run. Mobius closes open waits and records run.cancelled.Humans need a hard stop for obsolete or unsafe work.

Older examples may use forbid for concurrency. The compiler accepts it as a compatibility alias, but new specs should use skip.

Next

  • Build your first loop in the quickstart.
  • Read the step contract in steps.
  • Learn how runs behave in runs.
  • Choose trigger types in triggers.