Skip to main content
A job is the core building block in Terse. It connects an event (the trigger) to the code that should run when that event happens (the handler). When you deploy a Terse project, you’re deploying one or more jobs. In the SDK, you define jobs with createJob(). Across these docs, we sometimes call them workflows, and the Terse app surfaces them as agents. Same thing, different names.

Anatomy of a job

Every job has four parts:

Name

A unique string identifier. Terse uses this to match the job across deploys, so if you rename it, the platform treats it as a new job. Keep names stable and descriptive.

Triggers

The event that starts the job. A trigger is always tied to an integration (GitHub issue created, Slack message received, Attio record created) or to the system (cron schedule, webhook). A job can have multiple triggers, but each execution is started by exactly one event.

Filter (optional)

Runs a closure when the event fires so you can skip this particular event.

Handler

The function that runs when the trigger fires. Inside the handler you clone repos, run coding agents, pause for Slack approval with waitForInput, and open PRs — all inside a sandbox with its own filesystem and compute.

What happens when a job runs

  1. Trigger fires. An event arrives from the connected integration or on the configured schedule.
  2. Filter evaluates. If you defined a filter function, Terse calls it with the event. Return false to skip the run entirely. No tokens spent, no side effects.
  3. Handler executes. Your onTrigger runs with the event payload.
  4. Run is recorded. Every execution, whether it succeeds or fails, is logged in Activity with the full action trace so you can inspect what happened.

A durable handler

Most production jobs set durable: true so they can pause for humans and never repeat completed work. Wrap side effects in step(); use waitForInput when a person has to decide.

Filtering events

Not every event needs a full run. Use filter to skip events that don’t match your criteria before the handler executes.

Lifecycle

Jobs follow a straightforward path from code to production:
  1. Define. Register workflows with top-level createJob(), one file per job under src/jobs/, each imported for side effects from the src/terse.jobs.ts manifest.
  2. Generate. Run terse generate to get typed helpers for your integrations.
  3. Test. Run terse test to execute against real sample events locally.
  4. Deploy. Run terse deploy to package and host serverlessly. New jobs are created, existing jobs are updated, and removed jobs are cleaned up.
  5. Monitor. View runs, actions, and failures in the Activity tab.

Where to go next

Generated SDK

Typed triggers and workspace resources from terse generate.

Triggers reference

Every available trigger and its event payload.