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 withDocumentation Index
Fetch the complete documentation index at: https://docs.useterse.ai/llms.txt
Use this file to discover all available pages before exploring further.
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 (Attio record created, Slack message received, GitHub PR opened) 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 and you can decide to skip this particular event.Handler
The function that runs when the trigger fires. Inside the handler, you can make deterministic tool calls, use the TerseAgent, parse structured output, or combine all three.What happens when a job runs
- Trigger fires. An event arrives from the connected integration or on the configured schedule.
- Filter evaluates. If you defined a
filterfunction, Terse calls it with the event. Returnfalseto skip the run entirely. No tokens spent, no side effects. - Handler executes. Your
onTriggerruns with the event payload. - 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.
Deterministic vs. agentic
Inside a handler, you have two ways to get things done:| Approach | How | When to use |
|---|---|---|
| Deterministic | toolbox.* | You know exactly which tool to call and with what parameters |
| Agentic | generateText({ prompt, skills }) | You need the model to reason, summarize, classify, or decide |
Filtering events
Not every event needs a full run. Usefilter to skip events that don’t match your criteria before the handler executes.
Tool approvals
For jobs that write to production systems, you can require human approval before specific tools execute. List the tool names intoolApprovals on generateText (or TerseAgent.create()). During local testing, the CLI prompts in your terminal. In production, approval requests appear in the Terse app under Notifications.
Lifecycle
Jobs follow a straightforward path from code to production:- Define. Register workflows with top-level
createJob()insrc/terse.jobs.ts(or split across files and import them for side effects). - Generate. Run
terse generateto get typed helpers for your integrations. - Test. Run
terse testto execute against real sample events locally. - Deploy. Run
terse deployto package and host serverlessly. New jobs are created, existing jobs are updated, and removed jobs are cleaned up. - Monitor. View runs, actions, and failures in the Activity tab.
Where to go next
Deterministic tool calls
Call integration tools directly from code, no LLM in the loop.
Triggers reference
Every available trigger and its event payload.
