diff --git a/apps/docs/content/docs/en/tools/google_bigquery.mdx b/apps/docs/content/docs/en/tools/google_bigquery.mdx
index 4218ff9f68..4b31096c7a 100644
--- a/apps/docs/content/docs/en/tools/google_bigquery.mdx
+++ b/apps/docs/content/docs/en/tools/google_bigquery.mdx
@@ -5,11 +5,17 @@ description: Query, list, and insert data in Google BigQuery
import { BlockInfoCard } from "@/components/ui/block-info-card"
-
+{/* MANUAL-CONTENT-START:intro */}
+[Google BigQuery](https://cloud.google.com/bigquery) is Google Cloud's fully managed, serverless data warehouse designed for large-scale data analytics. BigQuery lets you run fast SQL queries on massive datasets, making it ideal for business intelligence, data exploration, and machine learning pipelines. It supports standard SQL, streaming inserts, and integrates with the broader Google Cloud ecosystem.
+
+In Sim, the Google BigQuery integration allows your agents to query datasets, list tables, inspect schemas, and insert rows as part of automated workflows. This enables use cases such as automated reporting, data pipeline orchestration, real-time data ingestion, and analytics-driven decision making. By connecting Sim with BigQuery, your agents can pull insights from petabytes of data, write results back to tables, and keep your analytics workflows running without manual intervention.
+{/* MANUAL-CONTENT-END */}
+
## Usage Instructions
Connect to Google BigQuery to run SQL queries, list datasets and tables, get table metadata, and insert rows.
diff --git a/apps/docs/content/docs/en/tools/google_books.mdx b/apps/docs/content/docs/en/tools/google_books.mdx
index 2b370d1394..d23d424f8b 100644
--- a/apps/docs/content/docs/en/tools/google_books.mdx
+++ b/apps/docs/content/docs/en/tools/google_books.mdx
@@ -5,11 +5,17 @@ description: Search and retrieve book information
import { BlockInfoCard } from "@/components/ui/block-info-card"
-
+{/* MANUAL-CONTENT-START:intro */}
+[Google Books](https://books.google.com) is Google's comprehensive book discovery and metadata service, providing access to millions of books from publishers, libraries, and digitized collections worldwide. The Google Books API enables programmatic search and retrieval of detailed book information including titles, authors, descriptions, ratings, and publication details.
+
+In Sim, the Google Books integration allows your agents to search for books and retrieve volume details as part of automated workflows. This enables use cases such as content research, reading list curation, bibliographic data enrichment, ISBN lookups, and knowledge gathering from published works. By connecting Sim with Google Books, your agents can discover and analyze book metadata, filter by availability or format, and incorporate literary references into their outputs—all without manual research.
+{/* MANUAL-CONTENT-END */}
+
## Usage Instructions
Search for books using the Google Books API. Find volumes by title, author, ISBN, or keywords, and retrieve detailed information about specific books including descriptions, ratings, and publication details.
diff --git a/apps/docs/content/docs/en/tools/google_tasks.mdx b/apps/docs/content/docs/en/tools/google_tasks.mdx
index 192a6dc37b..9743de3979 100644
--- a/apps/docs/content/docs/en/tools/google_tasks.mdx
+++ b/apps/docs/content/docs/en/tools/google_tasks.mdx
@@ -5,11 +5,17 @@ description: Manage Google Tasks
import { BlockInfoCard } from "@/components/ui/block-info-card"
-
+{/* MANUAL-CONTENT-START:intro */}
+[Google Tasks](https://support.google.com/tasks) is Google's lightweight task management service, integrated into Gmail, Google Calendar, and the standalone Google Tasks app. It provides a simple way to create, organize, and track to-do items with support for due dates, subtasks, and task lists. As part of Google Workspace, Google Tasks keeps your action items synchronized across all your devices.
+
+In Sim, the Google Tasks integration allows your agents to create, read, update, delete, and list tasks and task lists as part of automated workflows. This enables use cases such as automated task creation from incoming data, to-do list management based on workflow triggers, task status tracking, and deadline monitoring. By connecting Sim with Google Tasks, your agents can manage action items programmatically, keep teams organized, and ensure nothing falls through the cracks.
+{/* MANUAL-CONTENT-END */}
+
## Usage Instructions
Integrate Google Tasks into your workflow. Create, read, update, delete, and list tasks and task lists.
diff --git a/apps/docs/content/docs/en/tools/table.mdx b/apps/docs/content/docs/en/tools/table.mdx
index acde8e300c..388005b772 100644
--- a/apps/docs/content/docs/en/tools/table.mdx
+++ b/apps/docs/content/docs/en/tools/table.mdx
@@ -5,11 +5,12 @@ description: User-defined data tables for storing and querying structured data
import { BlockInfoCard } from "@/components/ui/block-info-card"
-
+{/* MANUAL-CONTENT-START:intro */}
Tables allow you to create and manage custom data tables directly within Sim. Store, query, and manipulate structured data within your workflows without needing external database integrations.
**Why Use Tables?**
@@ -26,6 +27,7 @@ Tables allow you to create and manage custom data tables directly within Sim. St
- Batch operations for bulk inserts
- Bulk updates and deletes by filter
- Up to 10,000 rows per table, 100 tables per workspace
+{/* MANUAL-CONTENT-END */}
## Creating Tables
diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx
index 451e5a709f..02c6175c2f 100644
--- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx
@@ -2534,6 +2534,16 @@ const WorkflowContent = React.memo(() => {
window.removeEventListener('remove-from-subflow', handleRemoveFromSubflow as EventListener)
}, [blocks, edgesForDisplay, getNodeAbsolutePosition, collaborativeBatchUpdateParent])
+ useEffect(() => {
+ const handleToggleWorkflowLock = (e: CustomEvent<{ blockIds: string[] }>) => {
+ collaborativeBatchToggleLocked(e.detail.blockIds)
+ }
+
+ window.addEventListener('toggle-workflow-lock', handleToggleWorkflowLock as EventListener)
+ return () =>
+ window.removeEventListener('toggle-workflow-lock', handleToggleWorkflowLock as EventListener)
+ }, [collaborativeBatchToggleLocked])
+
/**
* Updates container dimensions in displayNodes during drag or keyboard movement.
*/
diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/context-menu/context-menu.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/context-menu/context-menu.tsx
index efb3e7eb0f..b20fea3d9c 100644
--- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/context-menu/context-menu.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/context-menu/context-menu.tsx
@@ -281,6 +281,24 @@ interface ContextMenuProps {
* Set to true when user cannot leave (e.g., last admin)
*/
disableLeave?: boolean
+ /**
+ * Callback when lock/unlock is clicked
+ */
+ onToggleLock?: () => void
+ /**
+ * Whether to show the lock option (default: false)
+ * Set to true for workflows that support locking
+ */
+ showLock?: boolean
+ /**
+ * Whether the lock option is disabled (default: false)
+ * Set to true when user lacks permissions
+ */
+ disableLock?: boolean
+ /**
+ * Whether the workflow is currently locked (all blocks locked)
+ */
+ isLocked?: boolean
}
/**
@@ -321,6 +339,10 @@ export function ContextMenu({
onLeave,
showLeave = false,
disableLeave = false,
+ onToggleLock,
+ showLock = false,
+ disableLock = false,
+ isLocked = false,
}: ContextMenuProps) {
const [hexInput, setHexInput] = useState(currentColor || '#ffffff')
@@ -372,7 +394,8 @@ export function ContextMenu({
(showRename && onRename) ||
(showCreate && onCreate) ||
(showCreateFolder && onCreateFolder) ||
- (showColorChange && onColorChange)
+ (showColorChange && onColorChange) ||
+ (showLock && onToggleLock)
const hasCopySection = (showDuplicate && onDuplicate) || (showExport && onExport)
return (
@@ -495,6 +518,19 @@ export function ContextMenu({
)}
+ {showLock && onToggleLock && (
+ {
+ onToggleLock()
+ onClose()
+ }}
+ >
+ {isLocked ? 'Unlock' : 'Lock'}
+
+ )}
+
{/* Copy and export actions */}
{hasEditSection && hasCopySection && }
{showDuplicate && onDuplicate && (
diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/workflow-item/workflow-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/workflow-item/workflow-item.tsx
index 6963464d46..6651f6880f 100644
--- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/workflow-item/workflow-item.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/workflow-item/workflow-item.tsx
@@ -6,6 +6,7 @@ import { MoreHorizontal } from 'lucide-react'
import Link from 'next/link'
import { useParams } from 'next/navigation'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
+import { getWorkflowLockToggleIds } from '@/app/workspace/[workspaceId]/w/[workflowId]/utils'
import { ContextMenu } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/context-menu/context-menu'
import { DeleteModal } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/delete-modal/delete-modal'
import { Avatars } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/workflow-item/avatars/avatars'
@@ -27,6 +28,7 @@ import {
import { useFolderStore } from '@/stores/folders/store'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import type { WorkflowMetadata } from '@/stores/workflows/registry/types'
+import { useWorkflowStore } from '@/stores/workflows/workflow/store'
interface WorkflowItemProps {
workflow: WorkflowMetadata
@@ -169,6 +171,29 @@ export function WorkflowItem({
[workflow.id, updateWorkflow]
)
+ const activeWorkflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
+ const isActiveWorkflow = workflow.id === activeWorkflowId
+
+ const isWorkflowLocked = useWorkflowStore(
+ useCallback(
+ (state) => {
+ if (!isActiveWorkflow) return false
+ const blockValues = Object.values(state.blocks)
+ if (blockValues.length === 0) return false
+ return blockValues.every((block) => block.locked)
+ },
+ [isActiveWorkflow]
+ )
+ )
+
+ const handleToggleLock = useCallback(() => {
+ if (!isActiveWorkflow) return
+ const blocks = useWorkflowStore.getState().blocks
+ const blockIds = getWorkflowLockToggleIds(blocks, !isWorkflowLocked)
+ if (blockIds.length === 0) return
+ window.dispatchEvent(new CustomEvent('toggle-workflow-lock', { detail: { blockIds } }))
+ }, [isActiveWorkflow, isWorkflowLocked])
+
const isEditingRef = useRef(false)
const {
@@ -461,6 +486,10 @@ export function WorkflowItem({
disableExport={!userPermissions.canEdit}
disableColorChange={!userPermissions.canEdit}
disableDelete={!userPermissions.canEdit || !canDeleteSelection}
+ onToggleLock={handleToggleLock}
+ showLock={isActiveWorkflow && !isMixedSelection && selectedWorkflows.size <= 1}
+ disableLock={!userPermissions.canAdmin}
+ isLocked={isWorkflowLocked}
/>