Reference

Triggers

A trigger tells Mobius when to start a loop. The loop is the saved plan. Each successful start creates a new run tied to the loop version that existed at that time.

Manual runs work a little differently from automatic triggers. Every loop can always be started with its Run button or through the API. You do not add, enable, or remove a manual trigger.

You can add any number of automatic triggers to a loop:

TriggerUse it whenExample
ScheduleA clock decides when work startsRun a check every weekday at 9:00 AM
EventA received event decides when work startsRun when a pull request is opened
HTTP requestYour software directly asks Mobius to startStart from an internal portal

Each automatic trigger has its own Enabled switch. Keep new triggers disabled until the loop has completed safely with manual test input.

Create a safe test loop

Use the same harmless loop for the schedule and HTTP tests on this page:

  1. Open Build > Loops and select New loop.
  2. Name the loop Trigger walkthrough.
  3. Remove the Agent step that appears in the new loop.
  4. Select Add step > Sleep and set the duration to 1 second.
  5. Select Create, then select Run on the loop page.
  6. Confirm that the run reaches Completed and its Timeline shows one completed Sleep step.

Do not add an automatic trigger until this manual run succeeds. The test loop has no agent calls, integrations, or external side effects.

Test a schedule from end to end

  1. Return to the Trigger walkthrough loop and select Edit loop.
  2. Select Add trigger > Schedule.
  3. Under Runs, choose Every few minutes and 5 minutes.
  4. Choose the intended Timezone and leave the trigger enabled.
  5. Select Save changes.

The loop page should show the enabled schedule. Within five minutes, a new item should appear under Recent runs. Open it and confirm:

  • the run is Completed;
  • Timeline shows the Sleep step completed; and
  • Meta identifies the scheduled source and includes its scheduled time.

After the test, edit the loop, remove the five-minute schedule, and save. A manual run proves the loop works; only an automatic run proves the schedule works.

Manual runs

On a loop page, select Run to start with an empty event object. Use the arrow beside Run, then Run with event, when you want to provide JSON test data.

For example:

{
  "ticket": {
    "number": "T-104",
    "priority": "high"
  }
}

The new run's Event tab should show the same object. Manual testing is a safe way to check step references such as ${{ event.ticket.number }}, but it does not test an automatic trigger's event matcher or condition.

Starting another manual run creates new work. If the loop sends messages or changes outside records, use test destinations and check for prior effects before running it again.

Schedules

A schedule stores both a recurrence and a timezone. The app provides common choices such as every few minutes, hourly, daily, weekdays, weekly, and monthly. It also lets advanced users edit the five-field cron expression.

The trigger defaults to weekdays at 9:00 AM in the browser's timezone. Review both values before saving. The summary beneath the controls shows the schedule Mobius will use.

A schedule may fire while an earlier run is still active. The loop's concurrency policy decides whether the new start runs in parallel, queues, skips, or replaces the earlier run. Configure that policy in the loop settings; it is not a schedule setting.

Events

An event trigger matches events that Mobius receives from a connected integration or from a project capability such as tables.

Test an event with a table row

This test uses only Mobius and the side-effect-free Trigger walkthrough loop. First create a source for the test event:

  1. Open Build > Tables and select New table.
  2. Name it trigger_walkthrough_events.
  3. Name the first column test_id. Leave its type as string, and leave it marked Required and Identity.
  4. Select Create.

Now add a trigger to the test loop:

  1. Open Build > Loops > Trigger walkthrough and select Edit loop.

  2. Select Add trigger > Event.

  3. For Event source, choose Tables.

  4. For Event type, choose table.row.inserted.

  5. Select Add condition and enter:

    event.data.test_id == "match-001"
  6. Turn the trigger off, select Save changes, and review the saved event type and condition on the loop page.

  7. Edit the loop again, enable the trigger, and save.

Open Build > Tables > trigger_walkthrough_events, select Insert rows, keep JSON selected, and enter:

{
  "test_id": "match-001"
}

The preview should say Ready to insert 1 row. Select Insert row, return to the loop, and wait up to one minute for a new item under Recent runs. Open the run and confirm:

  • Event contains event.data.test_id with the value match-001;
  • Meta contains table_name: trigger_walkthrough_events; and
  • Timeline reaches Completed after the Sleep step.

This proves receipt, matching, run creation, and completion separately. To check the negative case, insert a second row with test_id set to no-match-001. Watch Recent runs and Trigger activity for one full minute. Neither list should gain an item for that row, because the condition returned false.

After the test, remove the event trigger from the loop and save. Then return to Build > Tables and delete trigger_walkthrough_events.

Use events from an integration

The same trigger controls apply to connected systems. Choose the narrowest event type that represents the work you want, then use Add condition to filter fields from event or meta. Selecting a source initially matches every event from that source, so narrow it before enabling the trigger.

Use the expression directly, without ${{ ... }}. A condition that returns false creates neither a run nor a Trigger activity row. If the condition cannot be evaluated, such as when a referenced field is missing, Mobius creates a failed Trigger activity row and does not start a run.

Before enabling an integration trigger, open Library > Integrations, select the provider, and inspect a harmless sample under Recent events. That view confirms receipt and shows the actual payload in your project. After enabling the trigger and sending one uniquely identifiable test event, verify its run's Event, Meta, and Timeline just as you did for the table row.

Do not treat provider receipt as proof that the trigger matched, or treat a created run as proof that the loop completed. Disable or remove the trigger after the test.

The event catalog lists available event names and the normalized fields for project events.

HTTP triggers

An HTTP request trigger gives the loop a delivery URL. External software sends a request to that URL with the event data for the run. Test it against the harmless Trigger walkthrough loop:

  1. Edit the loop and select Add trigger > HTTP request.
  2. Turn that trigger's Enabled switch off, then select Save changes.
  3. On the loop page, copy the generated Delivery URL into a temporary entry in a password manager or another approved secret store. Clear the clipboard.
  4. Open Signing options > Generate signing secret.
  5. Add the full whsec_... secret to the same temporary entry, then clear the clipboard. Mobius shows the secret only once.
  6. Edit the loop again, enable the HTTP trigger, and save.

Without a signing secret, the loop page labels the endpoint Unsigned. Do not expose an unsigned trigger to an untrusted network: anyone who can call it may be able to start paid or side-effecting work. Treat both the URL and signing secret as sensitive configuration.

Run this Python 3 standard-library example. It prompts for both values at run time, hides them as you paste them, and does not put either value in the command or process arguments. Copy each value from the temporary secret-store entry only when prompted, then clear the clipboard again:

python3 - <<'PY'
import getpass
import hashlib
import hmac
import json
import urllib.request
 
url = getpass.getpass("Delivery URL: ").strip()
secret = getpass.getpass("Signing secret: ")
body = json.dumps(
    {"test_id": "trigger-walkthrough"},
    separators=(",", ":"),
).encode()
signature = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
 
request = urllib.request.Request(
    url,
    data=body,
    method="POST",
    headers={
        "Content-Type": "application/json",
        "X-Mobius-Signature": f"sha256={signature}",
        "X-Idempotency-Key": "trigger-walkthrough-1",
    },
)
with urllib.request.urlopen(request) as response:
    print(response.status, response.read().decode())
PY

The response should be 202 Accepted with this shape:

{
  "source_event_id": "sevt_...",
  "status": "accepted",
  "deduped": false
}

202 proves that Mobius saved the incoming event; run creation happens asynchronously. Return to the loop and wait up to one minute for a new Recent runs item. Open it and confirm Event contains test_id: trigger-walkthrough, Meta names the HTTP trigger, and Timeline reaches Completed. If no run appears within a minute, continue with Find where an automatic start stopped.

Run the same Python command again and paste the same values. The unchanged idempotency key should immediately return the same source_event_id with deduped: true. Watch Recent runs for one full minute and confirm that it still contains only one HTTP run whose Event has test_id: trigger-walkthrough. A real calling system must use a stable, unique key for each logical event.

Next, prove that the signing secret is required. This command sends a different event without X-Mobius-Signature:

python3 - <<'PY'
import getpass
import urllib.error
import urllib.request
 
url = getpass.getpass("Delivery URL: ").strip()
request = urllib.request.Request(
    url,
    data=b'{"test_id":"unsigned-should-fail"}',
    method="POST",
    headers={"Content-Type": "application/json"},
)
try:
    with urllib.request.urlopen(request) as response:
        print(response.status)
except urllib.error.HTTPError as error:
    print(error.code)
PY

It should print 401. Watch Recent runs and Trigger activity for one full minute and confirm that neither list gains an item whose event has test_id: unsigned-should-fail. A 401 response plus the absence of a run proves that Mobius rejected the request before starting work.

Immediately before removing the trigger, return to its loop page and copy the complete Delivery URL into the temporary secret-store entry again. Clear the clipboard. Then edit the loop, remove the HTTP trigger, and save. Removing it invalidates the delivery URL and deletes that trigger's signing secret.

Prove that the old URL is revoked without sending the secret again:

python3 - <<'PY'
import getpass
import urllib.error
import urllib.request
 
url = getpass.getpass("Old delivery URL: ").strip()
request = urllib.request.Request(
    url,
    data=b"{}",
    method="POST",
    headers={"Content-Type": "application/json"},
)
try:
    with urllib.request.urlopen(request) as response:
        print(response.status)
except urllib.error.HTTPError as error:
    print(error.code)
PY

The command should print 404. Any other result means the endpoint was not revoked as expected; return to the loop and confirm the HTTP trigger was removed and the change was saved. After the 404, delete the temporary secret-store entry and clear the clipboard.

The interactive API reference defines request size limits, error responses, and how to find a run by source_event_id. Use that contract before adding caller retries.

Some external products call any outbound HTTP delivery a “webhook.” In Mobius, the request entering Mobius is an HTTP request trigger. A webhook is the opposite direction: Mobius sends an event to your software.

Clean up the walkthrough

After finishing the schedule, event, and HTTP tests, the Trigger walkthrough loop should have no automatic triggers. Keep it if you want a side-effect-free test loop. Otherwise open its Loop actions menu, select Delete loop, and confirm the deletion. Its existing test runs remain available for inspection, but the loop cannot start new runs.

When starts collide

All trigger types use the loop's concurrency policy:

  • Queue creates a queued run and starts it after the earlier active run reaches a final state.
  • Skip records trigger activity but creates no run.
  • Replace stops the earlier run and starts the new one. It does not undo an external action the earlier run already performed.
  • Parallel allows both to run, subject to the organization's plan limit.

See Decide what happens when runs overlap for timing, version, and queue behavior. A broad event matcher or exposed HTTP URL can create many starts quickly, so choose concurrency before enabling it.

Find where an automatic start stopped

Use these records in order:

  1. Source receipt: does the provider's Library > Integrations > provider > Recent events list the event, did the test table insert the row, or did the HTTP caller receive 202 Accepted?
  2. Loop > Recent runs: did that event create a run?
  3. Loop > Trigger activity: was an automatic start evaluated but blocked by a concurrency rule or run-start limit?
  4. Run > Timeline: did the created run complete its steps?

If the provider event exists but neither a run nor trigger activity appears, check the selected project, the trigger's Enabled switch, event type, and condition. A disabled trigger, event-type mismatch, or condition that evaluates to false produces no activity row. A condition evaluation error, concurrency skip, or rejected start does produce a row with its reason. If a run exists, the trigger worked; diagnose the run itself.

For a schedule, also verify the saved timezone and recurrence. For an HTTP trigger, use the caller's HTTP response together with the API contract. The Source events guide covers the full provider path.

Next

  • Define the job with loops.
  • Use the received event in steps.
  • Inspect what happened with runs.
  • Send Mobius events outward with webhooks.