<start.fieldName>. For example, a `customerId` field shows up as <start.customerId> in downstream blocks and templates.
- **Chat-only fields** — When the workflow runs from the chat side panel or a deployed chat experience, Sim also provides <start.input> (latest user message), <start.conversationId> (active session id), and <start.files> (chat attachments).
@@ -33,11 +33,11 @@ Keep Input Format fields scoped to the names you expect to reference later—tho
## Configure the Input Format
-Use the Input Format sub-block to define the schema that applies across execution modes:
+Use the Input Format sub-block to define the schema that applies across run modes:
1. Add a field for each value you want to collect.
2. Choose a type (`string`, `number`, `boolean`, `object`, `array`, or `files`). File fields accept uploads from chat and API callers.
-3. Provide default values when you want the manual run modal to populate test data automatically. These defaults are ignored for deployed executions.
+3. Provide default values when you want the manual run modal to populate test data automatically. These defaults are ignored for deployed runs.
4. Reorder fields to control how they appear in the editor form.
Reference structured values downstream with expressions such as <start.customerId> depending on the block you connect.
@@ -53,7 +53,7 @@ Reference structured values downstream with expressions such as <start.
tools or storage steps.
- Deploying to API turns the Input Format into a JSON contract for clients. Each field becomes part of the request body, and Sim coerces primitive types on ingestion. File fields expect objects that reference uploaded files; use the execution file upload endpoint before invoking the workflow.
+ Deploying to API turns the Input Format into a JSON contract for clients. Each field becomes part of the request body, and Sim coerces primitive types on ingestion. File fields expect objects that reference uploaded files; use the file upload endpoint before invoking the workflow.
API callers can include additional optional properties. They are preserved
inside <start.fieldName> outputs so you can experiment
diff --git a/apps/docs/content/docs/en/triggers/webhook.mdx b/apps/docs/content/docs/en/triggers/webhook.mdx
index d897db7681b..33d3a6dd952 100644
--- a/apps/docs/content/docs/en/triggers/webhook.mdx
+++ b/apps/docs/content/docs/en/triggers/webhook.mdx
@@ -8,7 +8,7 @@ import { Image } from '@/components/ui/image'
import { Video } from '@/components/ui/video'
import { FAQ } from '@/components/ui/faq'
-Webhooks allow external services to trigger workflow execution by sending HTTP requests to your workflow. Sim supports two approaches for webhook-based triggers.
+Webhooks allow external services to trigger workflow runs by sending HTTP requests to your workflow. Sim supports two approaches for webhook-based triggers.
## Generic Webhook Trigger
@@ -30,7 +30,7 @@ The Generic Webhook block creates a flexible endpoint that can receive any paylo
2. **Configure Payload** - Set up the expected payload structure (optional)
3. **Get Webhook URL** - Copy the automatically generated unique endpoint
4. **External Integration** - Configure your external service to send POST requests to this URL
-5. **Workflow Execution** - Every request to the webhook URL triggers the workflow
+5. **Workflow Run** - Every request to the webhook URL triggers the workflow
### Features
@@ -38,7 +38,7 @@ The Generic Webhook block creates a flexible endpoint that can receive any paylo
- **Automatic Parsing**: Webhook data is automatically parsed and available to subsequent blocks
- **Authentication**: Optional bearer token or custom header authentication
- **Rate Limiting**: Built-in protection against abuse
-- **Deduplication**: Prevents duplicate executions from repeated requests
+- **Deduplication**: Prevents duplicate runs from repeated requests
The Generic Webhook trigger fires every time the webhook URL receives a request, making it perfect for real-time integrations.
@@ -58,7 +58,7 @@ Alternatively, you can use specific service blocks (like Slack, GitHub, etc.) in
2. **Enable Trigger Mode** - Toggle "Use as Trigger" in the block settings
3. **Configure Service** - Set up authentication and event filters specific to that service
4. **Webhook Registration** - The service automatically registers the webhook with the external platform
-5. **Event-Based Execution** - Workflow triggers only for specific events from that service
+5. **Event-Based Runs** - Workflow triggers only for specific events from that service
### When to Use Each Approach
@@ -120,7 +120,7 @@ Alternatively, you can use specific service blocks (like Slack, GitHub, etc.) in
### Testing Webhooks
1. Use tools like Postman or curl to test your webhook endpoints
-2. Check workflow execution logs for debugging
+2. Check workflow run logs for debugging
3. Verify payload structure matches your expectations
4. Test authentication and error scenarios
@@ -153,8 +153,8 @@ Always validate and sanitize incoming webhook data before processing it in your
{ question: "What HTTP methods does the Generic Webhook endpoint accept?", answer: "The webhook endpoint handles POST requests for triggering workflows. GET requests are only used for provider-specific verification challenges (such as Microsoft Graph or WhatsApp verification). Other methods return a 405 Method Not Allowed response." },
{ question: "How do I authenticate webhook requests?", answer: "Enable the Require Authentication toggle in the webhook configuration, then set an Authentication Token. Callers can send the token as a Bearer token in the Authorization header, or you can specify a custom header name (e.g., X-Secret-Key) and the token will be matched against that header instead." },
{ question: "Can I define the expected payload structure for a webhook?", answer: "Yes. The Generic Webhook block includes an Input Format field where you can define the expected JSON schema. This is optional but helps document the expected structure. You can also use type \"file[]\" for file upload fields." },
- { question: "Does the webhook have deduplication built in?", answer: "Yes. The webhook processing pipeline includes idempotency checks to prevent duplicate executions from repeated requests with the same payload." },
+ { question: "Does the webhook have deduplication built in?", answer: "Yes. The webhook processing pipeline includes idempotency checks to prevent duplicate runs from repeated requests with the same payload." },
{ question: "What data from the webhook request is available in my workflow?", answer: "All request data including headers, body, and query parameters is parsed and made available to subsequent blocks. Common fields like event, id, and data are automatically extracted from the payload when present." },
- { question: "Do I need to deploy my workflow for the webhook URL to work?", answer: "Yes. The webhook endpoint checks that the associated workflow is deployed before triggering execution. If the workflow is not deployed, the webhook returns a not-found response." },
- { question: "Does the webhook auto-disable after repeated failures?", answer: "No. Unlike polling-based triggers (RSS, Gmail, IMAP), push-based generic webhooks do not auto-disable after consecutive failures. Each incoming request is processed independently. If your workflow consistently fails, check the execution logs for error details." },
+ { question: "Do I need to deploy my workflow for the webhook URL to work?", answer: "Yes. The webhook endpoint checks that the associated workflow is deployed before triggering a run. If the workflow is not deployed, the webhook returns a not-found response." },
+ { question: "Does the webhook auto-disable after repeated failures?", answer: "No. Unlike polling-based triggers (RSS, Gmail, IMAP), push-based generic webhooks do not auto-disable after consecutive failures. Each incoming request is processed independently. If your workflow consistently fails, check the run logs for error details." },
]} />
diff --git a/apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.test.ts b/apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.test.ts
index 73b16fdea1c..295b17e4e7e 100644
--- a/apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.test.ts
+++ b/apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.test.ts
@@ -2,6 +2,7 @@
* @vitest-environment node
*/
+import { databaseMock } from '@sim/testing'
import { NextRequest } from 'next/server'
import { beforeEach, describe, expect, it, vi } from 'vitest'
@@ -203,4 +204,73 @@ describe('POST /api/workflows/[id]/executions/[executionId]/cancel', () => {
expect(response.status).toBe(403)
})
+
+ it('updates execution log status in DB when durably recorded', async () => {
+ const mockWhere = vi.fn().mockResolvedValue(undefined)
+ const mockSet = vi.fn(() => ({ where: mockWhere }))
+ databaseMock.db.update.mockReturnValueOnce({ set: mockSet })
+ mockMarkExecutionCancelled.mockResolvedValue({
+ durablyRecorded: true,
+ reason: 'recorded',
+ })
+
+ await POST(makeRequest(), makeParams())
+
+ expect(databaseMock.db.update).toHaveBeenCalled()
+ expect(mockSet).toHaveBeenCalledWith({
+ status: 'cancelled',
+ endedAt: expect.any(Date),
+ })
+ })
+
+ it('updates execution log status in DB when locally aborted', async () => {
+ const mockWhere = vi.fn().mockResolvedValue(undefined)
+ const mockSet = vi.fn(() => ({ where: mockWhere }))
+ databaseMock.db.update.mockReturnValueOnce({ set: mockSet })
+ mockMarkExecutionCancelled.mockResolvedValue({
+ durablyRecorded: false,
+ reason: 'redis_unavailable',
+ })
+ mockAbortManualExecution.mockReturnValue(true)
+
+ await POST(makeRequest(), makeParams())
+
+ expect(databaseMock.db.update).toHaveBeenCalled()
+ expect(mockSet).toHaveBeenCalledWith({
+ status: 'cancelled',
+ endedAt: expect.any(Date),
+ })
+ })
+
+ it('does not update execution log status in DB when only paused execution was cancelled', async () => {
+ mockMarkExecutionCancelled.mockResolvedValue({
+ durablyRecorded: false,
+ reason: 'redis_unavailable',
+ })
+ mockCancelPausedExecution.mockResolvedValue(true)
+
+ await POST(makeRequest(), makeParams())
+
+ expect(databaseMock.db.update).not.toHaveBeenCalled()
+ })
+
+ it('returns success even if direct DB update fails', async () => {
+ mockMarkExecutionCancelled.mockResolvedValue({
+ durablyRecorded: true,
+ reason: 'recorded',
+ })
+ databaseMock.db.update.mockReturnValueOnce({
+ set: vi.fn(() => ({
+ where: vi.fn(() => {
+ throw new Error('DB connection failed')
+ }),
+ })),
+ })
+
+ const response = await POST(makeRequest(), makeParams())
+
+ expect(response.status).toBe(200)
+ const data = await response.json()
+ expect(data.success).toBe(true)
+ })
})
diff --git a/apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.ts b/apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.ts
index ec65f693501..889cc353dd5 100644
--- a/apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.ts
+++ b/apps/sim/app/api/workflows/[id]/executions/[executionId]/cancel/route.ts
@@ -1,4 +1,7 @@
+import { db } from '@sim/db'
+import { workflowExecutionLogs } from '@sim/db/schema'
import { createLogger } from '@sim/logger'
+import { and, eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid'
import { markExecutionCancelled } from '@/lib/execution/cancellation'
@@ -83,6 +86,25 @@ export async function POST(
})
}
+ if ((cancellation.durablyRecorded || locallyAborted) && !pausedCancelled) {
+ try {
+ await db
+ .update(workflowExecutionLogs)
+ .set({ status: 'cancelled', endedAt: new Date() })
+ .where(
+ and(
+ eq(workflowExecutionLogs.executionId, executionId),
+ eq(workflowExecutionLogs.status, 'running')
+ )
+ )
+ } catch (dbError) {
+ logger.warn('Failed to update execution log status directly', {
+ executionId,
+ error: dbError,
+ })
+ }
+ }
+
const success = cancellation.durablyRecorded || locallyAborted || pausedCancelled
if (success) {
diff --git a/apps/sim/app/api/workflows/[id]/executions/[executionId]/stream/route.ts b/apps/sim/app/api/workflows/[id]/executions/[executionId]/stream/route.ts
index ad2f94722d1..22b60f5aae7 100644
--- a/apps/sim/app/api/workflows/[id]/executions/[executionId]/stream/route.ts
+++ b/apps/sim/app/api/workflows/[id]/executions/[executionId]/stream/route.ts
@@ -48,14 +48,11 @@ export async function GET(
const meta = await getExecutionMeta(executionId)
if (!meta) {
- return NextResponse.json({ error: 'Execution buffer not found or expired' }, { status: 404 })
+ return NextResponse.json({ error: 'Run buffer not found or expired' }, { status: 404 })
}
if (meta.workflowId && meta.workflowId !== workflowId) {
- return NextResponse.json(
- { error: 'Execution does not belong to this workflow' },
- { status: 403 }
- )
+ return NextResponse.json({ error: 'Run does not belong to this workflow' }, { status: 403 })
}
const fromParam = req.nextUrl.searchParams.get('from')
diff --git a/apps/sim/app/api/workflows/[id]/log/route.ts b/apps/sim/app/api/workflows/[id]/log/route.ts
index dc50fa6bd4f..dead4bf36db 100644
--- a/apps/sim/app/api/workflows/[id]/log/route.ts
+++ b/apps/sim/app/api/workflows/[id]/log/route.ts
@@ -95,7 +95,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
const { traceSpans, totalDuration } = buildTraceSpans(resultWithOutput as ExecutionResult)
if (result.success === false) {
- const message = result.error || 'Workflow execution failed'
+ const message = result.error || 'Workflow run failed'
await loggingSession.safeCompleteWithError({
endedAt: new Date().toISOString(),
totalDurationMs: totalDuration || result.metadata?.duration || 0,
@@ -112,7 +112,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
}
return createSuccessResponse({
- message: 'Execution logs persisted successfully',
+ message: 'Run logs persisted successfully',
})
}
diff --git a/apps/sim/app/chat/constants.ts b/apps/sim/app/chat/constants.ts
index babbdd00da4..52e515ca9ec 100644
--- a/apps/sim/app/chat/constants.ts
+++ b/apps/sim/app/chat/constants.ts
@@ -6,7 +6,7 @@ export const CHAT_ERROR_MESSAGES = {
AUTH_REQUIRED_EMAIL: 'Please provide your email to access this chat.',
CHAT_UNAVAILABLE: 'This chat is currently unavailable. Please try again later.',
NO_CHAT_TRIGGER:
- 'No Chat trigger configured for this workflow. Add a Chat Trigger block to enable chat execution.',
+ 'No Chat trigger configured for this workflow. Add a Chat Trigger block to enable chat.',
USAGE_LIMIT_EXCEEDED: 'Usage limit exceeded. Please upgrade your plan to continue using chat.',
} as const
diff --git a/apps/sim/app/llms.txt/route.ts b/apps/sim/app/llms.txt/route.ts
index 0e6f7c31873..387f73d4962 100644
--- a/apps/sim/app/llms.txt/route.ts
+++ b/apps/sim/app/llms.txt/route.ts
@@ -25,10 +25,10 @@ Sim lets teams create agents visually with the workflow builder, conversationall
## Key Concepts
-- **Workspace**: The AI workspace — container for agents, workflows, data sources, and executions
+- **Workspace**: The AI workspace — container for agents, workflows, data sources, and runs
- **Workflow**: Visual builder — directed graph of blocks defining agent logic
- **Block**: Individual step such as an LLM call, tool call, HTTP request, or code execution
-- **Trigger**: Event or schedule that initiates workflow execution
+- **Trigger**: Event or schedule that initiates a workflow run
- **Execution**: A single run of a workflow with logs and outputs
- **Knowledge Base**: Document store used for retrieval-augmented generation
@@ -41,7 +41,7 @@ Sim lets teams create agents visually with the workflow builder, conversationall
- Knowledge bases and retrieval-augmented generation
- Table creation and management
- Document creation and processing
-- Scheduled and webhook-triggered executions
+- Scheduled and webhook-triggered runs
## Use Cases
diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx
index 4b25c0affcc..35d8c2e115b 100644
--- a/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx
@@ -684,12 +684,10 @@ function EmbeddedLog({ logId }: EmbeddedLogProps) {
- Total cost includes a base execution charge of{' '} - {formatCost(BASE_EXECUTION_CHARGE)} plus any model and tool usage costs. + Total cost includes a base run charge of {formatCost(BASE_EXECUTION_CHARGE)}{' '} + plus any model and tool usage costs.