Skip to content

Triggering workflows

Status: Current | Last reviewed: 2026-09-29

This page is three end-to-end recipes for getting an event into a TrueServe workflow. Pick the one that matches your source system.

Recipe 1: Webhook from a partner system

Use this when the source has nothing to do with TrueServe except "it can POST JSON."

Step 1 — author the workflow

In the UI:

  1. Open Workflows → New workflow.
  2. Trigger type: Webhook.
  3. Set the event type or trigger criteria the workflow should match, such as ticket.created.
  4. Save and test the workflow.

Step 2 — mint a token

In Profile → Settings, create a Personal Access Token with Viewer, Builder or Admin access to the active tenant. Event ingestion requires agents:run; Builder and Admin tokens include it through agents:manage. Tenant administrators can instead manage tenant tokens from Configuration → API Tokens.

Step 3 — point the source at the webhook

curl -X POST https://events.vanguard.dev.trueserve.deloitte.com/api/v1/events \
  -H "Authorization: Bearer tsf_..." \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "ticket.created",
    "source": "partner-helpdesk",
    "payload": {
      "ticket_id": 8421,
      "summary": "Customer requested refund"
    }
  }'

The response is 202 Accepted. The workflow runs asynchronously when its trigger rules match event_type and payload criteria. Test it in the UI's workflow tester before pointing real traffic.

Note: The generic event endpoint assigns a new event id for each accepted request. Retry only when no 202 was received. If the source requires queue-level retry and dedupe semantics, prefer a broker or provider adapter.

Recipe 2: Salesforce Pub/Sub

Use this when the trigger is a Salesforce CDC (Change Data Capture) or platform event.

Step 1 — connect Salesforce

In the UI under Integrations, add a Salesforce integration. Pick Production or Sandbox. Complete the OAuth flow.

Step 2 — subscribe to a channel

In the workflow editor:

  1. Trigger type: Salesforce Pub/Sub.
  2. Pick the connected Salesforce integration.
  3. Pick the channel (/data/CaseChangeEvent, /event/Custom_Event__e, etc.).
  4. Save.

The platform's Salesforce Pub/Sub adapter (apps/async-agent/app/events/adapters/salesforce_pubsub.py in the repo) opens a gRPC stream against Salesforce on workflow publish. Events arrive in real time.

Step 3 — verify with a test record

Modify the relevant Salesforce object in the UI; the workflow's run history should pick up the event within a few seconds.

Note: Replay IDs are persisted per-channel-per-workflow. Restarting the platform replays unprocessed events; you do not lose anything across deploys.

Recipe 3: Direct workflow execution

Use this when the caller knows which workflow to run and wants to bypass trigger-rule matching. Direct execution is useful for workflow-as-tool integrations, backend jobs, and synchronous calls that need the End node's mapped outputs.

Step 1 — mint a token

Mint a tenant-scoped token and check the endpoint security block in workflows-api. The current direct execution endpoint is part of the public workflows surface even though it is backed by the runtime service internally.

Step 2 — call the public workflows endpoint

curl -X POST https://events.vanguard.dev.trueserve.deloitte.com/api/v1/workflows/42/execute \
  -H "Authorization: Bearer tsf_..." \
  -H "Content-Type: application/json" \
  -d '{
    "execution_mode": "sync",
    "inputs": {
      "case_id": "5003X00001abcd",
      "priority": "high"
    }
  }'

Use execution_mode: "sync" when the workflow can finish quickly and you need the End node's outputs in the HTTP response. Use execution_mode: "async" when the workflow may wait, call humans, or run long; the response returns an execution_id that can be inspected with GET /api/v1/executions/{id} or streamed with GET /sse/executions/{id}.

Picking the right recipe

Source Recipe
Partner SaaS, custom script, third-party 1 (Webhook)
Salesforce object change or platform event 2 (Pub/Sub)
Backend job or workflow-as-tool caller 3 (Direct workflow execution)
RabbitMQ / SQS / Pub/Sub queue you already run Broker — see Event integration patterns

Sync outputs

Synchronous workflow calls return the End node's output mapping when one is defined. Each output row has a name and either a raw source path or a JSONata expression. Path mode is not a merge template. Valid path roots are:

Root Resolves from
<node_id>.<field> A workflow node's result in node_results
state.<node_id>.<field> / node_results.<node_id>.<field> The same node result namespace, explicit form
vars.<name> Flow variables written by Assignment or Code nodes
input.<name> Declared workflow input parameters
trigger.<field> / context.<field> Trigger event payload/context

Nested object fields and concrete list indexes are supported, for example lookup_case.data.records[0].Id.

JSONata mode evaluates the source against the same workflow document. Upstream node IDs are available at the top level, with reserved roots for vars, input, trigger, context, iterator, node_results, and state. For example, an output source can reshape Salesforce rows with {"names": lookup_case.data.records.Name, "count": $count(lookup_case.data.records)}.

If no output mapping is configured, sync calls return the raw node_results object.

LLM execution overrides

Direct workflow execution accepts invocation-scoped execution_overrides. Overrides apply only to that run and never update the saved workflow config. Use a global LLM override for every LLM node, and nodes entries when one node needs a different tier or fallback policy:

{
  "inputs": {
    "case_id": "500A"
  },
  "execution_mode": "async",
  "execution_overrides": {
    "llm": {
      "execution_tier": "standard",
      "fallback_to_standard_on_capacity_error": true,
      "nodes": {
        "summarize_case": {
          "execution_tier": "flex",
          "fallback_to_standard_on_capacity_error": false
        }
      }
    }
  }
}

The same override shape is accepted on the implicit workflow.execute event payload:

{
  "event_type": "workflow.execute",
  "source": "internal-service",
  "payload": {
    "workflow_config_id": 42,
    "inputs": {
      "case_id": "500A"
    },
    "execution_overrides": {
      "llm": {
        "execution_tier": "standard",
        "nodes": {
          "summarize_case": {
            "execution_tier": "flex"
          }
        }
      }
    }
  }
}

LLM tier resolution is:

  1. Per-node API override.
  2. Global API override.
  3. Node config.execution_tier.
  4. settings.batch_mode.llm_defaults.execution_tier, or batch when batch mode is enabled.
  5. standard.

Direct sync /execute calls are rejected when any LLM node resolves to batch. Use execution_mode: "async" or override those nodes to standard or flex for that invocation.

See also