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:
- Open Workflows → New workflow.
- Trigger type: Webhook.
- Set the event type or trigger criteria the workflow should match, such as
ticket.created. - 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
202was 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:
- Trigger type: Salesforce Pub/Sub.
- Pick the connected Salesforce integration.
- Pick the channel (
/data/CaseChangeEvent,/event/Custom_Event__e, etc.). - 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:
- Per-node API override.
- Global API override.
- Node
config.execution_tier. settings.batch_mode.llm_defaults.execution_tier, orbatchwhen batch mode is enabled.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.