Jobs
Jobs automate work by firing agent actions on a schedule, workspace event, or incoming webhook — another way to make agents work besides tickets.
Jobs
A job is a workflow rule that runs automatically when a trigger condition is met. The trigger can be a cron schedule, a workspace event, or an inbound webhook. When triggered, a job dispatches an action — creating a ticket, assigning an agent task, or sending a notification.
If tickets are "event-driven" (someone files a request, reports a problem, or asks for a change), jobs are "time-driven" — they fire at a set time without human intervention. Both are ways to make agents work; the only difference is what triggers them.
Jobs live under Jobs in the sidebar.
Trigger Types
| Type | Fires When |
|---|---|
| Schedule | A cron expression matches the current time. |
| Event | A specific workspace event occurs (e.g. a ticket status change). |
| Webhook | An HTTP POST hits the job's unique URL. |
A single job has one trigger type.
Action Types
| Action | What it does |
|---|---|
| Create ticket | On trigger, uses the job's Instruction as the ticket description, creates and assigns a ticket, then starts the executor. This is similar to automatically carrying out a manual create-and-assign-ticket flow, and the work is tracked in its own ticket. |
| Run Only | Does not create a ticket; directly starts one independent agent task using the Instruction. It is similar to sending that instruction to the agent in chat, but it is not a chat message or conversation turn; it belongs to the job run. |
| Send notification | Sends an in-app or inbox notification to the specified workspace members; it does not start an agent task. |
The action type can be changed from the job detail page. The Instruction field is shared across all action types:
- Create ticket — becomes the ticket description
- Run Only — becomes the agent task instruction
- Send notification — used as the notification message if no message is set in the action config
Action Configuration
Each action type has its own configuration fields, accessible in the job detail sidebar.
Create ticket
| Field | Description |
|---|---|
| Ticket title | Title of the ticket to create. Defaults to Job: <name> if empty. |
| Priority | Ticket priority: low / normal / high / urgent (leave empty for normal). |
| Project | Project to assign the ticket to. |
| Agent / Team | Agent or team to receive the ticket (set in the Agent Assignment section). |
Run Only
| Field | Description |
|---|---|
| Agent / Team | Agent or team to dispatch the task to (set in the Agent Assignment section). |
The task instruction comes from the job's Instruction field.
Team assignees: Both action types support assigning to a team instead of a single agent. When a team is assigned, the platform picks the most available team member at dispatch time.
Send notification
| Field | Description |
|---|---|
| Message | Notification message. Falls back to the Instruction field if empty. |
Job Owner
Every job has an owner — the member who created it. The owner is shown in the job detail sidebar and controls who can edit or delete the job when the workspace uses self-only permission rules.
| Operation | Required Scope | Ownership Rule |
|---|---|---|
| Create job | jobs:write | — |
| Edit job | jobs:write | Self-only: only the job owner can edit |
| Delete job | jobs:delete | Self-only: only the job owner can delete |
Create a Job
- Open Jobs in the sidebar
- Click New job
- Fill in:
- Name — descriptive label (
Daily health check,Slow query weekly report,On-call alert) - Description — optional note explaining what this job does and why it exists
- Goal — optional target outcome or success criteria for the job
- Trigger type — Schedule, Event, or Webhook
- Action type — what to do when triggered
- Name — descriptive label (
- Click Create
- On the detail page, set the Instruction and any action-specific config in the sidebar
Schedule Triggers
A schedule trigger uses a standard 5-field cron expression: minute hour day-of-month month day-of-week. Times are evaluated in the workspace's timezone.
Examples:
| Cron | What it does |
|---|---|
0 9 * * 1 | Every Monday at 9:00 |
*/15 * * * * | Every 15 minutes |
0 0 1 * * | Midnight on the first of every month |
0 17 * * 1-5 | Weekdays at 17:00 |
30 8 * * 6,0 | Saturdays and Sundays at 08:30 |
The platform's cron scheduler polls for due triggers. Drift can be a few seconds — do not use schedule triggers for hard-real-time work.
Event Triggers
Event triggers subscribe to real-time workspace lifecycle events (such as ticket updates, agent task completions, new comments, or runtime disconnects) and execute jobs automatically when declared filter criteria are met.
Using event triggers, you can build autonomous, event-driven pipelines — for instance: "When a high-priority bug ticket transitions to Done, automatically assign an agent to conduct post-incident review" or "When a GPU runtime goes offline, automatically create an incident ticket and notify on-call engineers".
Supported Events and Actions
Event Type (event) | Description | Supported Actions (actions) |
|---|---|---|
ticket | Ticket lifecycle events | created, updated, deleted |
agent_task | Agent task execution state | completed, failed, interaction, created, updated |
comment | Ticket comments & replies | created, updated, deleted |
runtime | Daemon execution nodes | offline, register, updated |
4-Tier Boolean Filter Logic
The event trigger engine evaluates rules using a 4-tier boolean model:
- Between Rule Cards —
OR: A single trigger can define multiple event rules; matching any one rule fires the job. - Action List (
actions) —OR: Within a single rule, matching any listed action satisfies the action check (e.g.,actions: ["created", "updated"]). - Conditions Map (
conditions) —AND: Within a single rule, all declared condition keys must simultaneously match. - Array Enum Values —
OR: If an individual condition field is provided as an array, matching any element is considered a match (e.g.,priority: [3, 4]matches High or Urgent).
Common Condition Fields and Enum References
Inside the conditions object, use structured payload properties:
ticket:status: Status enum (0backlog,1todo,2in_progress,3in_review,4done,5blocked,6cancelled)priority: Priority enum (0none,1low,2normal,3high,4urgent)assigneeType: Assignee type (0member,1agent,3team)projectId: Associated project UUIDlabels: Array of label names (subset match)
agent_task:status: Task status (10pending,20queued,30running,40completed,50failed,60cancelled)failureReason: Failure code (e.g.,runtime_process_crashed,run_timeout)agentId: Executing agent UUID
runtime:status: Node status (0offline,1online,2busy,3error)provider: Provider CLI type (e.g.,claude,kimi,codex)
Self-Trigger Prevention
The job engine includes built-in cycle detection: downstream events created by a job's own actions (such as creating tickets, posting comments, or launching tasks) never re-trigger that same job, ensuring stability and preventing infinite loops.
[!NOTE] Supported Action Types: Event triggers are designed for reactive automation and instant workflows, supporting
assign_agentandsend_notificationactions. If a formal ticket needs to be created upon an event, instruct the assigned agent to dynamically callmopheus ticket createCLI with context extracted from the event payload.
CLI Configuration Examples
Event triggers can be declared and updated via the Mopheus CLI:
# 1. Trigger when a high-priority ticket is marked done OR when an agent task crashes
mopheus job trigger-add <job-id> \
--kind event \
--label "Incident Resolution & Crash Watchdog" \
--event-filter '[
{
"event": "ticket",
"actions": ["updated"],
"conditions": {
"status": 4,
"priority": [3, 4]
}
},
{
"event": "agent_task",
"actions": ["failed"],
"conditions": {
"failureReason": "runtime_process_crashed"
}
}
]'
# 2. Attach an event trigger using an external JSON rule file
mopheus job trigger-add <job-id> --kind event --event-filter-file ./event-rules.json
# 3. Update event filter rules on an existing trigger
mopheus job trigger-update <job-id> <trigger-id> --event-filter '[{"event":"comment","actions":["created"]}]'
# 4. Introspect workspace supported event schemas and template variables
mopheus job event-schemaWeb Console Visualization: Configured event triggers render on the Job Detail → Triggers tab with visual status badges, explicit AND / OR connectors, localized enum labels, and raw JSON export.
Webhook Triggers
A webhook trigger gives the job a unique URL. The URL is shown in the Webhook tab on the job detail page:
POST https://<server_url>/api/v1/webhooks/jobs/<token>Send an HTTP POST with a JSON body to that URL and the job fires. The token is generated when the trigger is created and is part of the URL — no additional Authorization header is required for basic usage.
Authentication Methods
| Method | How it works |
|---|---|
| URL Token | The secret is embedded in the URL path. Anyone with the URL can trigger the job. |
| HMAC Signing | An additional signing secret is configured. Every request must include a valid signature header. |
HMAC Signing
To require signature verification, add a Signing Secret to the trigger. The server will reject any request that does not include a valid X-Webhook-Signature (or X-Hub-Signature-256 for GitHub compatibility) header.
The signature format is sha256=<hex-encoded HMAC-SHA256 of the raw request body>.
curl example:
BODY='{"event":"test"}'
SECRET="your-signing-secret"
SIG="sha256=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')"
curl -X POST "https://<server_url>/api/v1/webhooks/jobs/<token>" \
-H "Content-Type: application/json" \
-H "X-Webhook-Signature: $SIG" \
-d "$BODY"Python example:
import hmac, hashlib, requests
secret = "your-signing-secret"
body = b'{"event":"test"}'
sig = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
requests.post(
"https://<server_url>/api/v1/webhooks/jobs/<token>",
data=body,
headers={"Content-Type": "application/json", "X-Webhook-Signature": sig},
)Trigger Expiry
Both schedule and webhook triggers support an optional Expires at date. After this date the trigger is disabled — for webhook triggers, all incoming requests return 403; for schedule triggers, the trigger stops firing. Set an expiry when you want time-limited integrations without manual cleanup.
From the CLI, set the expiry with --expires-at when adding or updating a trigger (accepts RFC3339 or YYYY-MM-DD HH:MM):
# Schedule trigger with an expiry
mopheus job trigger-add <job-id> --kind schedule --cron "0 9 * * 1-5" --expires-at "2026-12-31T00:00:00Z"Token Rotation
Rotate the URL token from the Webhook tab if it is compromised. Rotating invalidates the old URL immediately — update any upstream callers before rotating.
Enable and Disable
Every job has an enable toggle. Disabled jobs:
- Do not fire on schedule
- Reject incoming webhook requests
- Retain their configuration — re-enabling resumes the workflow without reconfiguration
Agent Readiness
Before executing an action, the job engine checks that the target agent is ready. A dispatch is skipped (not failed) if:
- The agent does not exist or has been archived
- The agent has no runtime bound
- The agent's runtime is offline or in an error state
Skipped runs appear in the run history with status Skipped and a reason. They do not count as failures and do not trigger retries.
Job Runs
Each job has a run history that lists every firing — when it ran, what triggered it, and the outcome. Failed runs show the error reason and can be replayed from the detail page.
| Status | Meaning |
|---|---|
| Running | Currently executing. |
| Completed | Finished successfully. |
| Failed | Finished with an error. |
| Skipped | Agent was not ready at dispatch time. |
Failures do not retry automatically. If a webhook event is critical, configure the upstream system to retry on non-2xx responses.
Command Line Reference
# List jobs in the active workspace
mopheus job list
# Create a job
mopheus job create \
--name "Daily health check" \
--trigger-type schedule \
--action-type create_ticket \
--instruction "Connect to production DB, check pg_stat_activity for long-running transactions and lock waits, generate a report" \
--action-config '{"title":"Daily health check","priority":2}' \
--cron "0 9 * * 1-5" \
--timezone "Asia/Shanghai"
# Create a Quartz seven-field schedule: weekdays at 09:00
mopheus job create \
--name "Weekday report" \
--trigger-type schedule \
--action-type create_ticket \
--cron-dialect quartz \
--cron "0 0 9 ? * 2-6 *" \
--timezone "Asia/Shanghai"
# Add a cron trigger to a job
mopheus job trigger-add <job-id> \
--kind schedule \
--cron "0 9 * * 1-5" \
--timezone "Asia/Shanghai"
# Manually fire a job
mopheus job trigger <id>
# Update a job
mopheus job update <id> --instruction "New agent instruction"
mopheus job update <id> --enabled false
# View run history
mopheus job runs <id>
# Delete a job
mopheus job delete <id>
# Manage triggers
mopheus job trigger-list <job-id>
mopheus job trigger-delete <job-id> <trigger-id>
mopheus job trigger-rotate-url <job-id> <trigger-id>Run mopheus job create --help for the full action config key reference.
For a schedule job, --cron creates the initial trigger. The default standard
dialect uses minute hour day-of-month month day-of-week; quartz uses
second minute hour day-of-month month day-of-week year. For example,
0 0 9 ? * 2-6 * is Quartz for 09:00 on weekdays, where ? leaves the
day-of-month unspecified. --start-at sets the earliest eligible run (default:
now), while --expires-at is an exclusive deadline: occurrences at or after it
do not run.