AgentsScheduled & triggered runs

Scheduled and triggered runs

⚠️
Preview — this feature is being built; the design below is the spec.

A deployment starts agent sessions for you, either on a schedule or when an event arrives. Every firing creates a new session with a message you define, so the run shows up in session lists, executions and usage exactly like a session you started yourself.

This page is about the /v1/deployments API. Giving a Console project its runtime node is a different thing, covered in Deployment.

When to use it

TriggerExample
scheduleEvery weekday at 07:00, summarise yesterday’s support tickets and post the digest.
webhookWhen your shop system posts a new order, check it for fraud signals.
manualA button in your admin panel that runs a fixed task on demand, with a fixed agent and settings.

If your own code already decides when to run, call POST /v1/sessions directly; a deployment adds nothing.

Endpoints

MethodPathPurpose
POST/v1/deploymentsCreate a deployment.
GET/v1/deploymentsList deployments.
GET/v1/deployments/{deployment_id}Read one, including next and last run.
PATCH/v1/deployments/{deployment_id}Change it.
POST/v1/deployments/{deployment_id}/pauseStop firing.
POST/v1/deployments/{deployment_id}/resumeStart firing again.
POST/v1/deployments/{deployment_id}/runFire once now, whatever the trigger.
GET/v1/deployments/{deployment_id}/runsHistory of firings and the sessions they created.
DELETE/v1/deployments/{deployment_id}Delete. Sessions it created are kept.
POST/v1/deployments/{deployment_id}/triggerThe inbound URL for webhook deployments (see below).

Base URL https://app.syntic.ai/v1 (the paths above already include /v1). Authenticate with a private key and send syntic-beta: agents-2026-11-01, except on the inbound /trigger URL, which uses its own signing secret.

The deployment object

{
  "id": "dep_01JC9E2G4J6L8N0Q2S4U",
  "type": "deployment",
  "name": "daily-ticket-digest",
  "agent_id": "agt_01JC4R8W6Q2N9X3T5V7Y",
  "agent_version": null,
  "status": "active",
  "trigger": {
    "type": "schedule",
    "cron": "0 7 * * 1-5",
    "timezone": "Europe/London"
  },
  "input_template": "Summarise the support tickets opened on {{run.date_previous_day}}. Post the digest to #support-leads.",
  "session_options": { "memory_scope": "team:support", "limits": { "max_turns": 20 } },
  "concurrency": "skip_if_running",
  "next_run_at": "2026-11-06T07:00:00Z",
  "last_run": { "id": "drn_01JC9F...", "status": "succeeded", "session_id": "sesn_01JC9F...", "fired_at": "2026-11-05T07:00:00Z" },
  "created_at": "2026-11-01T12:00:00Z"
}
FieldRequired on createDescription
nameYesUnique in the workspace.
agent_idYesAn active agent definition.
agent_versionNoPin a version; null means latest at firing time.
triggerYesSee Triggers.
input_templateYesThe first user message of each session. {{...}} placeholders are filled at firing time; see Templates. Up to 20,000 characters.
session_optionsNoAny POST /v1/sessions options except agent_id and input: memory_scope, environment_id, limits, metadata.
concurrencyNoWhat happens if the previous run’s session is still running: skip_if_running (default), queue (start after it ends, at most one waiting) or allow (start in parallel).
statusactive or paused. A deployment is paused automatically after 5 failed firings in a row.

Triggers

Schedule

{ "type": "schedule", "cron": "0 7 * * 1-5", "timezone": "Europe/London" }

cron uses the usual five-field syntax; 0 7 * * 1-5, for example, means 07:00 on weekdays. timezone is an IANA name; default UTC. Daylight-saving changes follow the time zone, so a 07:00 job stays at 07:00 local time. The minimum interval is 5 minutes. Firings happen within 60 seconds of the scheduled time.

Webhook

{ "type": "webhook" }

When you create a webhook deployment, the response includes a trigger_url and a signing_secret (shown once). Your system calls:

POST https://app.syntic.ai/v1/deployments/dep_01JC9E2G4J6L8N0Q2S4U/trigger
Content-Type: application/json
syntic-signature: t=1762300800,v1=5d41402abc4b2a76b9719d911017c592...
 
{"order_id": "88123", "total": 412.50}

The signature is an HMAC-SHA256 of "<t>.<raw body>" with the signing secret, hex-encoded, the same scheme Syntic uses for outgoing webhooks. Requests older than 5 minutes or with a bad signature are refused with 401. The JSON body (up to 256 KB) is available to the template as {{payload}}. The response is 202 Accepted with the run id.

Manual

{ "type": "manual" }

Fires only through POST /v1/deployments/{id}/run. That endpoint also accepts an optional payload object for any trigger type.

Templates

PlaceholderValue
{{run.id}}The firing’s id.
{{run.fired_at}}Firing time, RFC 3339 in the deployment’s time zone.
{{run.date}}, {{run.date_previous_day}}Dates as YYYY-MM-DD in the deployment’s time zone.
{{payload}}The webhook or manual payload as pretty-printed JSON.
{{payload.some.path}}One value from the payload. Missing paths become an empty string.

Placeholders are substituted as text. Treat webhook payloads as untrusted input: they become part of a user message, and the agent’s instructions should say how to handle content it did not expect.

Create a scheduled deployment

curl -sS https://app.syntic.ai/v1/deployments \
  -H "Authorization: Bearer $SYNTIC_API_KEY" \
  -H "Content-Type: application/json" \
  -H "syntic-beta: agents-2026-11-01" \
  -d '{
    "name": "daily-ticket-digest",
    "agent_id": "agt_01JC4R8W6Q2N9X3T5V7Y",
    "trigger": {"type": "schedule", "cron": "0 7 * * 1-5", "timezone": "Europe/London"},
    "input_template": "Summarise the support tickets opened on {{run.date_previous_day}}.",
    "concurrency": "skip_if_running"
  }'

Run history

GET /v1/deployments/{id}/runs lists firings, newest first, with cursor pagination (limit, after_id, before_id). Each run has id, fired_at, trigger_type, status (started, skipped, queued, succeeded, failed), session_id (when a session was created), skip_reason (for example previous_run_active) and error. A run is succeeded when its session’s turn ends with outcome end_turn, and failed for any other outcome or if the session could not be started.

Subscribe to deployment.run.failed with webhooks to hear about failures without polling.

Errors

Errors use the error envelope.

StatustypecodeWhen
400invalid_requestinvalid_cronThe expression cannot be parsed or fires more often than every 5 minutes.
400invalid_requestunknown_timezoneNot an IANA time zone name.
400invalid_requestinvalid_templateUnclosed or unknown placeholder.
401authenticationinvalid_signatureInbound /trigger call with a missing, stale or wrong signature.
404not_founddeployment_not_foundNo such deployment.
409invalid_requestagent_archivedThe agent is archived.
409invalid_requestdeployment_paused/trigger called while paused. /run still works.
413invalid_requestpayload_too_largeInbound payload over 256 KB.

Limits and billing

LimitValue
Deployments per workspace200
Minimum schedule interval5 minutes
Inbound /trigger calls60 per minute per deployment
Run history kept90 days

Deployments are free; the sessions they start are billed like any other session.

Build notes for the platform team

  • Reuse the workflow trigger tick and activation functions for schedules and inbound webhooks.
  • Each firing calls the same internal path as POST /v1/sessions, so limits, billing and audit stay identical.
  • The auto-pause after 5 consecutive failures writes an audit event and sends deployment.paused.
Was this page helpful?