From 240067bbb5adc4075fe33f44b19c5ddb2a1c5921 Mon Sep 17 00:00:00 2001 From: Waleed Date: Fri, 25 Sep 2026 22:05:01 -0700 Subject: [PATCH 1/6] fix(search): align landing layout and history rows with Home (#8317) * fix(search): align landing layout and history rows with Home * fix(search): keep cancellation available while editing the draft --- .../components/organization-landing.tsx | 19 +++ .../components/search-landing-history.tsx | 146 +++++++++--------- .../home/organization-home.tsx | 48 +++--- .../search/search-results-view.tsx | 27 +--- .../app/o/[organizationId]/search/search.tsx | 32 ++-- .../search-transitions.test.tsx | 58 ++++++- .../components/source-card/source-card.tsx | 50 +++--- 7 files changed, 224 insertions(+), 156 deletions(-) create mode 100644 apps/sim/app/o/[organizationId]/components/organization-landing.tsx diff --git a/apps/sim/app/o/[organizationId]/components/organization-landing.tsx b/apps/sim/app/o/[organizationId]/components/organization-landing.tsx new file mode 100644 index 00000000000..4f58d030cef --- /dev/null +++ b/apps/sim/app/o/[organizationId]/components/organization-landing.tsx @@ -0,0 +1,19 @@ +import type { ReactNode } from 'react' +import { cn, pageHeadingClassName } from '@sim/emcn' + +interface OrganizationLandingProps { + heading: string + children: ReactNode +} + +/** Keeps the Home and Search composers centered independently of the shortcuts below them. */ +export function OrganizationLanding({ heading, children }: OrganizationLandingProps) { + return ( +
+
+

{heading}

+
{children}
+
+
+ ) +} diff --git a/apps/sim/app/o/[organizationId]/components/search-landing-history.tsx b/apps/sim/app/o/[organizationId]/components/search-landing-history.tsx index 08a1ba2116d..ef50e9c3635 100644 --- a/apps/sim/app/o/[organizationId]/components/search-landing-history.tsx +++ b/apps/sim/app/o/[organizationId]/components/search-landing-history.tsx @@ -29,86 +29,88 @@ export function SearchLandingHistory({ const queries = data?.queries.slice(0, 5) ?? [] const selected = selection ?? (sources.length > 0 ? 'sources' : 'queries') return ( -
+
{children} - {(sources.length > 0 || queries.length > 0) && ( -
-
-
+
+ {(sources.length > 0 || queries.length > 0) && ( +
+
+
+ setSelection('sources')} + > + Recently viewed + + setSelection('queries')} + > + Recent searches + +
setSelection('sources')} + disabled={clear.isPending} + onClick={() => + clear.mutate(undefined, { onError: (error) => toast.error(error.message) }) + } > - Recently viewed + Clear history - setSelection('queries')} +
+
+
- Recent searches - + {sources.length > 0 ? ( + sources.map((source) => ) + ) : ( +

+ Sources you open will appear here. +

+ )} +
+
+ {queries.length > 0 ? ( + queries.map(({ query }) => ( +
+ onSearch(query)}> + {query} + +
+ )) + ) : ( +

+ Your recent searches will appear here. +

+ )} +
- - clear.mutate(undefined, { onError: (error) => toast.error(error.message) }) - } - > - Clear history +
+ )} + {history.isError && ( +
+ Recent activity couldn’t load. + void history.refetch()} disabled={history.isFetching}> + Try again
-
-
- {sources.length > 0 ? ( - sources.map((source) => ) - ) : ( -

- Sources you open will appear here. -

- )} -
-
- {queries.length > 0 ? ( - queries.map(({ query }) => ( -
- onSearch(query)}> - {query} - -
- )) - ) : ( -

- Your recent searches will appear here. -

- )} -
-
-
- )} - {history.isError && ( -
- Recent activity couldn’t load. - void history.refetch()} disabled={history.isFetching}> - Try again - -
- )} + )} +
) } diff --git a/apps/sim/app/o/[organizationId]/home/organization-home.tsx b/apps/sim/app/o/[organizationId]/home/organization-home.tsx index 0d44c285fa6..7baabe357df 100644 --- a/apps/sim/app/o/[organizationId]/home/organization-home.tsx +++ b/apps/sim/app/o/[organizationId]/home/organization-home.tsx @@ -1,7 +1,7 @@ 'use client' import { useCallback, useEffect, useState, useSyncExternalStore } from 'react' -import { cn, pageHeadingClassName, toast } from '@sim/emcn' +import { toast } from '@sim/emcn' import { useQueryClient } from '@tanstack/react-query' import Link from 'next/link' import { useQueryStates } from 'nuqs' @@ -16,6 +16,7 @@ import { getMothershipAttachmentUrl, } from '@/lib/mothership/chat/attachment-preview' import { createSearchResource } from '@/lib/mothership/resources/search' +import { OrganizationLanding } from '@/app/o/[organizationId]/components/organization-landing' import { Composer } from '@/app/o/[organizationId]/home/components/composer' import { GetStarted } from '@/app/o/[organizationId]/home/components/get-started' import { organizationHomeParsers } from '@/app/o/[organizationId]/home/search-params' @@ -396,32 +397,27 @@ function OrganizationHomeContent({ } /> ) : ( -
- {/* Asymmetric padding biases the group up so the full cluster (heading + input + steps) sits at the optical center */} -
-

- {requestMode === 'assistant' - ? `Search ${organization.name}` - : requestMode === 'plan' - ? `What should we understand and plan${firstName ? `, ${firstName}` : ''}?` - : `What should we get done${firstName ? `, ${firstName}` : ''}?`} -

-
- {composer} - {/* Anchored out of flow so expanding/collapsing never shifts the centered input */} -
- {requestMode === 'agent' ? ( - setDraft(mentionifyIntegrations(prompt))} - /> - ) : searchAccess.memberScoped ? ( - - ) : null} -
-
+ + {composer} +
+ {requestMode === 'agent' ? ( + setDraft(mentionifyIntegrations(prompt))} + /> + ) : searchAccess.memberScoped ? ( + + ) : null}
-
+ )}
) diff --git a/apps/sim/app/o/[organizationId]/search/search-results-view.tsx b/apps/sim/app/o/[organizationId]/search/search-results-view.tsx index 6a3fa1e55e8..a0d6bdd76dd 100644 --- a/apps/sim/app/o/[organizationId]/search/search-results-view.tsx +++ b/apps/sim/app/o/[organizationId]/search/search-results-view.tsx @@ -1,14 +1,9 @@ import { type ReactNode, useRef } from 'react' -import { - cn, - pageHeadingClassName, - scrollFadeAttributes, - scrollFadeClass, - useScrollEdges, -} from '@sim/emcn' +import { cn, scrollFadeAttributes, scrollFadeClass, useScrollEdges } from '@sim/emcn' import { HEADER_ACTION_CLUSTER, PAGE_HEADER_BAR } from '@/components/page-header-bar' import type { WorkspaceSearchFilters } from '@/lib/api/contracts/knowledge' import type { SearchResource } from '@/lib/mothership/generated/resources' +import { OrganizationLanding } from '@/app/o/[organizationId]/components/organization-landing' import { PAGE_COLUMN_CLASS } from '@/app/o/[organizationId]/components/organization-page' import { useOrganizationContext } from '@/app/o/[organizationId]/providers/organization-provider' import { KnowledgeSearchResults } from '@/app/workspace/[workspaceId]/home/components/knowledge-search-results' @@ -42,11 +37,11 @@ export function SearchResultsView({ }) return (
-
-
-
{searching ? ( <> +
+
+
{composer}
@@ -73,15 +68,9 @@ export function SearchResultsView({
) : ( -
- {/* Asymmetric padding biases the group up so heading and field sit at the optical center, as on Home */} -
-

- Search {organization.name} -

-
{composer}
-
-
+ + {composer} + )}
) diff --git a/apps/sim/app/o/[organizationId]/search/search.tsx b/apps/sim/app/o/[organizationId]/search/search.tsx index 50bdbc978ca..c7c58551404 100644 --- a/apps/sim/app/o/[organizationId]/search/search.tsx +++ b/apps/sim/app/o/[organizationId]/search/search.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef } from 'react' import { ComposerActionButton, toast } from '@sim/emcn' -import { ArrowUp, Loader } from '@sim/emcn/icons' +import { ArrowUp, StopFilled } from '@sim/emcn/icons' import { useIsFetching, useQueryClient } from '@tanstack/react-query' import { useRouter } from 'next/navigation' import { useQueryStates } from 'nuqs' @@ -39,14 +39,13 @@ interface SearchFieldProps { function SearchField({ userId, initialValue, onSubmit }: SearchFieldProps) { const inputRef = useRef(null) const { organization } = useOrganizationContext() - const isSearching = - useIsFetching({ - queryKey: knowledgeKeys.searchQuery( - resourceScopeKey({ kind: 'organization', organizationId: organization.id }), - initialValue.trim(), - userId - ), - }) > 0 + const queryClient = useQueryClient() + const queryKey = knowledgeKeys.searchQuery( + resourceScopeKey({ kind: 'organization', organizationId: organization.id }), + initialValue.trim(), + userId + ) + const isSearching = useIsFetching({ queryKey }) > 0 const latestDraftKey = `${userId}:organization:${organization.id}:search` const latestDraft = useMothershipDraftsStore((state) => state.drafts[latestDraftKey]) const ownerQuery = initialValue || latestDraft?.searchQuery || '' @@ -60,7 +59,6 @@ function SearchField({ userId, initialValue, onSubmit }: SearchFieldProps) { setDraft(draftKey, payload) setDraft(latestDraftKey, payload) } - const pending = isSearching && value.trim() === initialValue.trim() const submit = (text = value) => { if (!text.trim() || (isSearching && text.trim() === initialValue.trim())) return const { clearDraft } = useMothershipDraftsStore.getState() @@ -99,14 +97,14 @@ function SearchField({ userId, initialValue, onSubmit }: SearchFieldProps) { submitControl={ submit()} - disabled={!canSubmit || pending} - aria-label={pending ? 'Searching' : 'Search'} - aria-busy={pending} - active={canSubmit} + onClick={() => (isSearching ? void queryClient.cancelQueries({ queryKey }) : submit())} + disabled={!canSubmit && !isSearching} + aria-label={isSearching ? 'Stop search' : 'Search'} + aria-busy={isSearching} + active={canSubmit || isSearching} > - {pending ? ( - + {isSearching ? ( + ) : ( )} diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/knowledge-search-results/search-transitions.test.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/knowledge-search-results/search-transitions.test.tsx index 77e85f9f3ed..e90ee758a4c 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/knowledge-search-results/search-transitions.test.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/knowledge-search-results/search-transitions.test.tsx @@ -272,6 +272,60 @@ describe('search refinement with the real query cache and URL state', () => { }) describe('live search submission feedback', () => { + it.each(['launch', 'edited draft', ''])( + 'cancels with draft %j, ignores late results, and allows a fresh submission', + async (draft) => { + const shape = resolveDeploymentShape() + seedDeploymentShape({ ...shape, features: { ...shape.features, liveEnterpriseSearch: true } }) + await render({ organizationPage: true, params: '?q=launch' }) + await act(async () => { + await vi.advanceTimersByTimeAsync(1) + }) + expect(requests).toHaveLength(1) + await act(async () => { + const input = container.querySelector('textarea')! + Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')!.set!.call( + input, + draft + ) + input.dispatchEvent(new Event('input', { bubbles: true })) + }) + await act(async () => { + const stop = container.querySelector('button[aria-label="Stop search"]') + if (!stop) throw new Error('No stop control for the pending search') + stop.click() + await vi.advanceTimersByTimeAsync(1) + }) + expect(requests[0].signal.aborted).toBe(true) + expect(container.querySelector('textarea')!.value).toBe(draft) + await complete(0, { title: 'Cancelled result' }) + expect( + client + .getQueriesData({ queryKey: knowledgeKeys.searches() }) + .every(([, data]) => data === undefined) + ).toBe(true) + await act(async () => { + const input = container.querySelector('textarea')! + Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')!.set!.call( + input, + 'launch' + ) + input.dispatchEvent(new Event('input', { bubbles: true })) + }) + await act(async () => { + container.querySelector('button[aria-label="Search"]')!.click() + await vi.advanceTimersByTimeAsync(1) + }) + expect(requests).toHaveLength(2) + await complete(1, { title: 'Fresh result' }) + expect( + client + .getQueriesData({ queryKey: knowledgeKeys.searches() }) + .flatMap(([, data]) => data?.results.map((result) => result.documentId) ?? []) + ).toEqual(['Fresh result']) + } + ) + it('acknowledges the submitted query before exposing refinement controls', async () => { const shape = resolveDeploymentShape() seedDeploymentShape({ ...shape, features: { ...shape.features, liveEnterpriseSearch: true } }) @@ -286,8 +340,8 @@ describe('live search submission feedback', () => { ) ).toBe(false) expect( - container.querySelector('button[aria-label="Searching"]')?.disabled - ).toBe(true) + container.querySelector('button[aria-label="Stop search"]')?.disabled + ).toBe(false) await complete(0) expect( container.querySelector('button[aria-label="Search"]')?.disabled diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/source-card/source-card.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/source-card/source-card.tsx index 6e6961afc5a..a9c43d7af35 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/source-card/source-card.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/source-card/source-card.tsx @@ -3,6 +3,7 @@ import type { ReactNode } from 'react' import { Chip, + chipGeometryClass, chipHoverSurfaceClass, chipIconSlotClass, chipRadiusClass, @@ -124,29 +125,38 @@ export function SourceCard({ source, query, onSummarize, dense = false }: Source if (dense) { return ( -
- - - - +
) } From 5126dc6dad022eeb276755858d15346282cd7073 Mon Sep 17 00:00:00 2001 From: Waleed Date: Fri, 25 Sep 2026 23:57:43 -0700 Subject: [PATCH 2/6] fix(tabs): preserve readable labels in crowded tab strips (#8319) * fix(tabs): preserve readable labels in crowded tab strips * fix(tabs): type layout checks and verify touch selection stability * fix(tabs): keep touch sizing stable across activity changes --- apps/desktop/e2e/browser-chrome.spec.ts | 147 ++++++++++++++++-- apps/desktop/e2e/fixtures/browser-chrome.tsx | 27 +++- .../src/components/tab-strip/tab-strip.tsx | 80 ++++------ 3 files changed, 182 insertions(+), 72 deletions(-) diff --git a/apps/desktop/e2e/browser-chrome.spec.ts b/apps/desktop/e2e/browser-chrome.spec.ts index a6917acf763..c5857f80ea0 100644 --- a/apps/desktop/e2e/browser-chrome.spec.ts +++ b/apps/desktop/e2e/browser-chrome.spec.ts @@ -55,7 +55,7 @@ mountBrowserChromeFixture(useBrowserPanelOcclusion);`, response.end( path.endsWith('.js') ? bundle.outputFiles.find((file) => file.path.endsWith('.js'))?.text - : css.css + : `${css.css}\n${bundle.outputFiles.find((file) => file.path.endsWith('.css'))?.text ?? ''}` ) return } @@ -75,7 +75,7 @@ mountBrowserChromeFixture(useBrowserPanelOcclusion);`, response.end( path === '/page' ? '

Browser fixture

A live page behind the application chrome.

' - : '
' + : '
' ) }) await new Promise((resolve) => server?.listen(0, resolve)) @@ -116,31 +116,150 @@ mountBrowserChromeFixture(useBrowserPanelOcclusion);`, return { width: bounds.width, right: bounds.right } }) ) - expect(geometry.every((tab) => tab.width >= 64 && tab.width < 160)).toBe(true) + expect(geometry.every((tab) => tab.width < 160)).toBe(true) expect(geometry.at(-1)?.right).toBeLessThan(1070) await page.screenshot({ path: testInfo.outputPath('tabs.png') }) }) - await test.step('Short labels keep their compact intrinsic width', async () => { - await page.locator('#short-tabs').click() - const widths = await page - .locator('[data-tab-strip-item]') - .evaluateAll((tabs) => tabs.map((tab) => tab.getBoundingClientRect().width)) - expect(widths.every((width) => width >= 64 && width < 96)).toBe(true) - await page.locator('#eight-tabs').click() - }) - await test.step('Crowded tabs preserve controls and scroll', async () => { + await test.step('Crowded tabs keep readable labels when selected, hovered, and focused', async () => { await page.locator('#many-tabs').click() await expect(page.locator('[data-tab-strip-item]')).toHaveCount(18) const overflow = await page .locator('[data-tab-strip-item]') .first() .evaluate((tab) => ({ - width: tab.getBoundingClientRect().width, scrollWidth: tab.parentElement?.scrollWidth ?? 0, clientWidth: tab.parentElement?.clientWidth ?? 0, })) - expect(overflow.width).toBeGreaterThanOrEqual(64) expect(overflow.scrollWidth).toBeGreaterThan(overflow.clientWidth) + const active = page.getByRole('tab', { selected: true }) + const label = active.locator('[data-overflow-text]') + await expect + .poll(() => label.evaluate((element) => element.getBoundingClientRect().width)) + .toBeGreaterThanOrEqual(48) + const neighbor = page.getByRole('tab').nth(2) + const beforeHover = await neighbor.evaluate((element: HTMLElement) => ({ + left: element.offsetLeft, + width: element.offsetWidth, + })) + await neighbor.hover() + await expect + .poll(() => + neighbor + .locator('[data-overflow-text]') + .evaluate((element) => element.getBoundingClientRect().width) + ) + .toBeGreaterThanOrEqual(48) + expect( + await neighbor.evaluate((element: HTMLElement) => ({ + left: element.offsetLeft, + width: element.offsetWidth, + })) + ).toEqual(beforeHover) + await neighbor.click() + await expect(neighbor).toHaveAttribute('aria-selected', 'true') + await page.keyboard.press('End') + const last = page.getByRole('tab').last() + await expect(last).toBeFocused() + await expect(last).toHaveAttribute('aria-selected', 'true') + await expect(last).toBeInViewport({ ratio: 1 }) + await expect + .poll(() => label.evaluate((element) => element.getBoundingClientRect().width)) + .toBeGreaterThanOrEqual(48) + await page.mouse.move(200, 180) + await page.screenshot({ + path: testInfo.outputPath('crowded-tabs.png'), + animations: 'disabled', + }) + await page.evaluate(() => document.documentElement.classList.remove('dark')) + await page.screenshot({ + path: testInfo.outputPath('crowded-tabs-light.png'), + animations: 'disabled', + }) + await page.evaluate(() => document.documentElement.classList.add('dark')) + await page.keyboard.press('Home') + await expect(page.getByRole('tab').first()).toBeInViewport({ ratio: 1 }) + await page.locator('#eight-tabs').click() + }) + await test.step('Touch tabs leave room for both attention and close controls', async () => { + const session = await page.context().newCDPSession(page) + try { + await session.send('Emulation.setTouchEmulationEnabled', { enabled: true }) + expect(await page.evaluate(() => matchMedia('(any-pointer: coarse)').matches)).toBe(true) + await page.locator('#many-tabs').click() + const attention = page.getByRole('tab').nth(1) + await expect + .poll(() => + attention + .locator('[data-overflow-text]') + .evaluate((element) => element.getBoundingClientRect().width) + ) + .toBeGreaterThanOrEqual(48) + const attentionItem = page.locator('[data-tab-strip-item="tab-1"]') + const indicator = attentionItem.locator('[data-row-action-indicator]') + const controls = attentionItem.locator('[data-row-action-controls]') + await expect(indicator).toBeVisible() + await expect(indicator).toHaveCSS('opacity', '1') + await expect(controls).toHaveCSS('opacity', '1') + await attentionItem.getByRole('button', { name: /^Close / }).click({ trial: true }) + expect( + await attentionItem.evaluate((element) => { + const title = element.querySelector('[data-overflow-text]')?.getBoundingClientRect() + const indicator = element + .querySelector('[data-row-action-indicator]') + ?.getBoundingClientRect() + const close = element.querySelector('[aria-label^="Close "]')?.getBoundingClientRect() + return ( + title && + indicator && + close && + title.right <= indicator.left && + indicator.right <= close.left && + close.right <= element.getBoundingClientRect().right + ) + }) + ).toBe(true) + await page.screenshot({ path: testInfo.outputPath('crowded-tabs-touch.png') }) + const beforeSelection = await attention.evaluate( + (element: HTMLElement) => element.offsetWidth + ) + await attention.click() + await expect(attention).toHaveAttribute('aria-selected', 'true') + expect(await attention.evaluate((element: HTMLElement) => element.offsetWidth)).toBe( + beforeSelection + ) + await page.locator('#toggle-activity').click() + expect(await attention.evaluate((element: HTMLElement) => element.offsetWidth)).toBe( + beforeSelection + ) + await page.locator('#toggle-activity').click() + await page.locator('#medium-tabs').click() + await page.getByRole('tab').first().click() + const intrinsicWidth = await attention.evaluate( + (element: HTMLElement) => element.offsetWidth + ) + expect(intrinsicWidth).toBeGreaterThan(144) + expect(intrinsicWidth).toBeLessThan(200) + await attention.click() + expect(await attention.evaluate((element: HTMLElement) => element.offsetWidth)).toBe( + intrinsicWidth + ) + await page.locator('#toggle-activity').click() + expect(await attention.evaluate((element: HTMLElement) => element.offsetWidth)).toBe( + intrinsicWidth + ) + await page.locator('#toggle-activity').click() + } finally { + await session.send('Emulation.setTouchEmulationEnabled', { enabled: false }) + await session.detach() + } + await page.locator('#eight-tabs').click() + }) + await test.step('Short labels stay below the maximum tab width', async () => { + await page.locator('#short-tabs').click() + const widths = await page + .locator('[data-tab-strip-item]') + .evaluateAll((tabs) => tabs.map((tab) => tab.getBoundingClientRect().width)) + expect(widths.every((width) => width < 120)).toBe(true) await page.locator('#eight-tabs').click() }) await test.step('An open menu recovers when no native page was available for its initial capture', async () => { diff --git a/apps/desktop/e2e/fixtures/browser-chrome.tsx b/apps/desktop/e2e/fixtures/browser-chrome.tsx index 1e1ae4e5e53..0fa62c97561 100644 --- a/apps/desktop/e2e/fixtures/browser-chrome.tsx +++ b/apps/desktop/e2e/fixtures/browser-chrome.tsx @@ -46,7 +46,8 @@ function BrowserChromeFixture({ useOcclusion }: BrowserChromeFixtureProps) { const [activeTabId, setActiveTabId] = useState(null) const [selected, setSelected] = useState('tab-0') const [tabCount, setTabCount] = useState(8) - const [shortTitles, setShortTitles] = useState(false) + const [titleLength, setTitleLength] = useState<'short' | 'medium' | 'long'>('long') + const [attention, setAttention] = useState(true) const [error, setError] = useState(null) const api = (globalThis as typeof globalThis & { simDesktop: SimDesktopApi }).simDesktop const { snapshot, snapshotLayer, onSnapshotError } = useOcclusion( @@ -93,7 +94,7 @@ function BrowserChromeFixture({ useOcclusion }: BrowserChromeFixtureProps) { id='eight-tabs' onClick={() => { setTabCount(8) - setShortTitles(false) + setTitleLength('long') }} > Eight tabs @@ -101,17 +102,35 @@ function BrowserChromeFixture({ useOcclusion }: BrowserChromeFixtureProps) { - + +
{error &&

{error}

} ({ id: `tab-${index}`, - title: shortTitles ? 'A' : `Example resource ${index + 1} with a descriptive title`, + title: + titleLength === 'short' + ? 'A' + : titleLength === 'medium' + ? 'Medium title' + : `Example resource ${index + 1} with a descriptive title`, icon: , active: selected === `tab-${index}`, + attention: attention && index === 1, }))} variant='floating' onSelect={setSelected} diff --git a/packages/emcn/src/components/tab-strip/tab-strip.tsx b/packages/emcn/src/components/tab-strip/tab-strip.tsx index 438b7b8d7bf..baef5cd3202 100644 --- a/packages/emcn/src/components/tab-strip/tab-strip.tsx +++ b/packages/emcn/src/components/tab-strip/tab-strip.tsx @@ -14,7 +14,14 @@ import { useRef, useState, } from 'react' -import { OverflowText, RowActions, rowActionsGroupClass } from '@sim/emcn' +import { + OverflowText, + RowActions, + rowActionsGroupClass, + SCROLL_FADE_BAND_PX, + scrollFadeAttributes, + scrollFadeXClass, +} from '@sim/emcn' import { AnimatePresence, motion, useReducedMotion } from 'framer-motion' import { Plus, X } from '../../icons' import { cn } from '../../lib/cn' @@ -24,36 +31,6 @@ import { TabStripAction } from './tab-strip-action' const DRAG_EDGE_ZONE = 40 const DRAG_SCROLL_SPEED = 8 -/** - * Width of the scroll-edge fades, and so the margin a tab has to clear to be - * genuinely visible. Keep in step with the `w-4` on the gradients below: a tab - * revealed flush against the container edge lands under its gradient and reads - * as half-faded, which is indistinguishable from "there is more to scroll". - */ -const EDGE_FADE_PX = 24 - -/** - * Edge fades, as a mask rather than a tinted gradient laid over the tabs. - * - * Tabs paint their own fills, and an overlay tinted with the surface colour - * washes a pill's edge toward that colour instead of dissolving it — and it is - * only correct while whatever sits behind the strip is exactly that colour. A - * mask fades pill and label together to real transparency, over any background. - * This is how the command palette fades its results, and how every other - * horizontal fade in the app is drawn. - * - * The four combinations are spelled out because Tailwind scans for literal class - * strings; a template built at runtime would never be generated. Keep the 24px - * stops in step with {@link EDGE_FADE_PX}, which is how far `revealActiveTab` - * insets a tab so it lands clear of the fade rather than under it. - */ -const SCROLL_FADE = { - none: '', - start: - '[-webkit-mask-image:linear-gradient(to_right,transparent_0px,black_24px)] [mask-image:linear-gradient(to_right,transparent_0px,black_24px)]', - end: '[-webkit-mask-image:linear-gradient(to_right,black_calc(100%_-_24px),transparent_100%)] [mask-image:linear-gradient(to_right,black_calc(100%_-_24px),transparent_100%)]', - both: '[-webkit-mask-image:linear-gradient(to_right,transparent_0px,black_24px,black_calc(100%_-_24px),transparent_100%)] [mask-image:linear-gradient(to_right,transparent_0px,black_24px,black_calc(100%_-_24px),transparent_100%)]', -} as const const TAB_TRANSITION = { duration: 0.1, ease: [0.2, 0, 0, 1] as const } /** @@ -62,13 +39,16 @@ const TAB_TRANSITION = { duration: 0.1, ease: [0.2, 0, 0, 1] as const } * the basis and left every tab sized by its own title. * * Floating tabs start at their content width, capped at 200px, then shrink with - * the available space. Floating tabs stop at a 64px control footprint; attached - * tabs retain their 96px label minimum. Crowded rows then scroll, and clipped - * titles remain available through tooltips. + * the available space. Their 112px minimum leaves 50px for the title beside a + * 16px icon and visible close button, including OverflowText's fade. Keep the + * same minimum in every interaction state so revealing actions never shifts + * tabs beneath the pointer. Touch layouts reserve both action slots even when + * no activity indicator is present, so activity changes cannot resize tabs. + * Crowded rows then scroll. */ const TAB_WIDTH: Record = { attached: 'w-[156px] min-w-[96px] shrink', - floating: 'min-w-[64px] max-w-[var(--tab-strip-max-tab-width,200px)] shrink', + floating: 'min-w-28 max-w-[var(--tab-strip-max-tab-width,200px)] shrink', } /** The resting shape of a tab that is not the active one. */ @@ -378,8 +358,7 @@ const Tab = forwardRef(function Tab( tab.pinned ? 'justify-center px-0' : 'justify-start gap-1.5 px-2', closeable && 'pr-8', closeable && - tab.attention && - !tab.active && + (variant === 'floating' || (tab.attention && !tab.active)) && '[@media(any-pointer:coarse)]:pr-[62px] [@media(hover:none)]:pr-[62px]', TAB_SHAPE[variant], tab.selected && !tab.active && TAB_SELECTED[variant], @@ -427,9 +406,10 @@ const Tab = forwardRef(function Tab( className={cn( 'group relative select-none', rowActionsGroupClass, - // `shrink` lets a crowded strip squeeze tabs to their floor before it - // starts scrolling. tab.pinned ? 'w-[34px] min-w-[34px] max-w-[34px] flex-none' : TAB_WIDTH[variant], + variant === 'floating' && + closeable && + '[@media(any-pointer:coarse)]:min-w-36 [@media(hover:none)]:min-w-36', dragging && 'opacity-30' )} data-tab-strip-item={tab.id} @@ -584,16 +564,15 @@ export function TabStrip({ const nodeRect = node.getBoundingClientRect() const tabLeft = tabRect.left - nodeRect.left + node.scrollLeft const tabRight = tabLeft + tabRect.width - // Inset by the fade on both sides so the tab comes to rest clear of the - // gradient rather than beneath it. - const viewLeft = node.scrollLeft + EDGE_FADE_PX - const viewRight = node.scrollLeft + node.clientWidth - EDGE_FADE_PX + /** Keep the active tab clear of the canonical scroll fade. */ + const viewLeft = node.scrollLeft + SCROLL_FADE_BAND_PX + const viewRight = node.scrollLeft + node.clientWidth - SCROLL_FADE_BAND_PX const maxScrollLeft = Math.max(0, node.scrollWidth - node.clientWidth) const target = tabLeft < viewLeft - ? tabLeft - EDGE_FADE_PX + ? tabLeft - SCROLL_FADE_BAND_PX : tabRight > viewRight - ? tabRight - node.clientWidth + EDGE_FADE_PX + ? tabRight - node.clientWidth + SCROLL_FADE_BAND_PX : null if (target === null) return // The clamp is what lets the first and last tabs sit flush: there is no @@ -926,18 +905,11 @@ export function TabStrip({
From 2b01631fbcca3d8818612f26eab8683b2dfb2e43 Mon Sep 17 00:00:00 2001 From: Waleed Date: Sat, 26 Sep 2026 00:14:58 -0700 Subject: [PATCH 3/6] chore(flags): drop leftover references to the retired async projection flag (#8320) --- .../knowledge-projection.integration.ts | 4 ++-- packages/db/knowledge-projection.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/sim/lib/knowledge/__integration__/knowledge-projection.integration.ts b/apps/sim/lib/knowledge/__integration__/knowledge-projection.integration.ts index 804b90ac24c..37f9abf9a5e 100644 --- a/apps/sim/lib/knowledge/__integration__/knowledge-projection.integration.ts +++ b/apps/sim/lib/knowledge/__integration__/knowledge-projection.integration.ts @@ -1,8 +1,8 @@ /** * The knowledge projector and the readers that must stay correct while it lags. A GitHub member * source's document in a search index is changed by a writer in either projection mode — - * synchronous, as every writer now is, or deferred, as writers of releases that carried the - * `knowledge-async-projection` flag were, leaving only a mark — and search is checked before the + * synchronous, as every writer now is, or deferred, as writers of earlier releases could be, + * leaving only a mark — and search is checked before the * projector runs: a revoked member is refused and a granted one is served, on the vector and * keyword legs and under the source filter, and a disabled or deleted chunk is gone at once. The * projector's own contract follows: it converges the rows and removes the mark, keeps a mark that diff --git a/packages/db/knowledge-projection.ts b/packages/db/knowledge-projection.ts index 37a837294a4..dc8cfcb6398 100644 --- a/packages/db/knowledge-projection.ts +++ b/packages/db/knowledge-projection.ts @@ -5,11 +5,11 @@ import type { Sql, TransactionSql } from 'postgres' const logger = createLogger('KnowledgeProjection') /** - * The transaction setting that skips the synchronous projection triggers. No application writer - * sets it: every writer's projection rows are written by those triggers in its own transaction. - * Releases that carried the `knowledge-async-projection` flag set it to leave a chunk write's rows - * to the projector, which is why a mark can still carry content to project. Either way the - * triggers mark the document in `knowledge_projection_dirty`. + * The transaction setting that skips the synchronous projection triggers. Only the projector sets + * it: every other writer's projection rows are written by those triggers in its own transaction. + * A mark can still carry content to project, because earlier releases also set it on chunk writes + * to leave their rows to the projector. Either way the triggers mark the document in + * `knowledge_projection_dirty`. */ const KNOWLEDGE_PROJECTION_MODE_SETTING = 'sim.projection_mode' From a0c93d65846a24cfd472192073870e9599c9ba32 Mon Sep 17 00:00:00 2001 From: Waleed Date: Sat, 26 Sep 2026 08:48:07 -0700 Subject: [PATCH 4/6] fix(search): read Confluence pages through the v2 API the Search grant allows (#8321) * fix(search): read Confluence pages through the v2 API the Search grant allows * fix(search): use search-response spaces for verification and fall back for legacy blog-post references * fix(search): fall back to blog posts only when the legacy page is missing * test(search): check that provider failures keep their HTTP status --- apps/sim/lib/sim-search/live/README.md | 2 +- .../sim/lib/sim-search/live/atlassian.test.ts | 155 ++++++++++++++++++ apps/sim/lib/sim-search/live/atlassian.ts | 82 +++++++-- apps/sim/lib/sim-search/live/http.test.ts | 16 ++ apps/sim/lib/sim-search/live/http.ts | 8 +- apps/sim/lib/sim-search/live/policy.test.ts | 22 ++- apps/sim/lib/sim-search/live/policy.ts | 20 ++- apps/sim/lib/sim-search/live/providers.ts | 2 +- 8 files changed, 285 insertions(+), 22 deletions(-) create mode 100644 apps/sim/lib/sim-search/live/atlassian.test.ts diff --git a/apps/sim/lib/sim-search/live/README.md b/apps/sim/lib/sim-search/live/README.md index c67b634c5d9..548d2d91047 100644 --- a/apps/sim/lib/sim-search/live/README.md +++ b/apps/sim/lib/sim-search/live/README.md @@ -123,7 +123,7 @@ Self-managed GitLab is resolved from the saved source's validated host/project i | Calendar | CalendarList then `/calendars/{id}/events` | `/calendars/{id}/events/{eventId}` | Same-user delegation, selected calendars, event window/query | | Slack | `POST /api/assistant.search.context` | `conversations.replies` or `files.info` preview | Member only; Slack enforces the connected user's grant | | Jira | `POST /ex/jira/{cloudId}/rest/api/3/search/jql` | `/rest/api/3/issue/{key}` under that cloud site | Member only | -| Confluence | `/ex/confluence/{cloudId}/wiki/rest/api/search` with CQL | `/wiki/rest/api/content/{id}` | Same site, spaces, current type/status/labels, source readability | +| Confluence | `/ex/confluence/{cloudId}/wiki/rest/api/search` with CQL | v2 `/wiki/api/v2/pages/{id}` or `/blogposts/{id}` (`body-format=view`); a space reads as its homepage | Same site, spaces, current type/status/labels, source readability | | GitHub | `/search/issues`, `/search/code`, `/search/repositories`, `/search/commits` | Issue, repository, commit, or contents endpoint for returned kind | Added repositories; installation coverage/stable IDs and code filters | | GitLab | Configured `/api/v4/projects/{project}/search`, or supported date listing | Project issue/MR/wiki/file endpoint | Current request-local admin ACL evidence or saved CSV grants, plus content filters | | Coda | Personal MCP `search`; REST `/apis/v1/docs` title-search compatibility | MCP read allowlist; REST compatibility document/page reads | Selected parent doc and current source-token visibility; optional Enterprise org membership | diff --git a/apps/sim/lib/sim-search/live/atlassian.test.ts b/apps/sim/lib/sim-search/live/atlassian.test.ts new file mode 100644 index 00000000000..fda5330dcdb --- /dev/null +++ b/apps/sim/lib/sim-search/live/atlassian.test.ts @@ -0,0 +1,155 @@ +import { describe, expect, it, vi } from 'vitest' +import { readAtlassian, searchAtlassian } from '@/lib/sim-search/live/atlassian' +import { NativeSearchError } from '@/lib/sim-search/live/http' +import type { NativeClient } from '@/lib/sim-search/live/types' + +const SITE = { id: 'cloud', url: 'https://acme.atlassian.net' } + +/** Answers only the paths a test names, so a read through the v1 content API fails loudly. */ +function client(rows: Record): NativeClient & { json: ReturnType } { + return { + json: vi.fn(async (path: string) => { + if (path === '/oauth/token/accessible-resources') return [SITE] + if (!(path in rows)) throw new Error(`Unexpected request: ${path}`) + return rows[path] + }), + text: vi.fn(), + } +} + +const v2 = '/ex/confluence/cloud/wiki/api/v2' + +describe('Confluence live documents', () => { + it('reads pages and blog posts through v2, which needs only the granular read scopes', async () => { + const api = client({ + [`${v2}/pages/123`]: { + id: '123', + title: 'Runbook', + body: { view: { value: '

Restart the ingest worker.

' } }, + version: { createdAt: '2026-09-18T04:50:29.778Z' }, + _links: { webui: '/spaces/ENG/pages/123/Runbook' }, + }, + [`${v2}/blogposts/9`]: { + id: '9', + title: 'Release notes', + body: { view: { value: '

Shipped search.

' } }, + version: { createdAt: '2026-09-20T00:00:00.000Z' }, + _links: { webui: '/spaces/ENG/blog/9' }, + }, + }) + await expect(readAtlassian(api, 'confluence', '123', 'cloud', 'page')).resolves.toMatchObject({ + id: '123', + kind: 'page', + title: 'Runbook', + content: expect.stringContaining('Restart the ingest worker.'), + url: 'https://acme.atlassian.net/wiki/spaces/ENG/pages/123/Runbook', + modifiedAt: '2026-09-18T04:50:29.778Z', + }) + await expect(readAtlassian(api, 'confluence', '9', 'cloud', 'blogpost')).resolves.toMatchObject( + { + kind: 'blogpost', + content: expect.stringContaining('Shipped search.'), + } + ) + }) + + it('reads a legacy reference without a kind as a blog post when no page has that id', async () => { + const api: NativeClient = { + json: vi.fn(async (path: string) => { + if (path === '/oauth/token/accessible-resources') return [SITE] + if (path === `${v2}/blogposts/9`) + return { id: '9', title: 'Release notes', body: { view: { value: '

Shipped.

' } } } + throw new NativeSearchError('unavailable', 'Provider request failed (404).', undefined, 404) + }), + text: vi.fn(), + } + await expect(readAtlassian(api, 'confluence', '9', 'cloud')).resolves.toMatchObject({ + kind: 'blogpost', + content: expect.stringContaining('Shipped.'), + }) + }) + + it('keeps a legacy reference page failure that is not a missing page', async () => { + const failure = new NativeSearchError( + 'unavailable', + 'Provider request failed (500).', + undefined, + 500 + ) + const api: NativeClient = { + json: vi.fn(async (path: string) => { + if (path === '/oauth/token/accessible-resources') return [SITE] + if (path === `${v2}/pages/9`) throw failure + throw new Error(`Unexpected request: ${path}`) + }), + text: vi.fn(), + } + await expect(readAtlassian(api, 'confluence', '9', 'cloud')).rejects.toBe(failure) + }) + + it('reads a space result as its homepage, keeping the space as the document', async () => { + const api = client({ + [`${v2}/spaces`]: { + results: [{ id: '7', key: 'ENG', name: 'Engineering', homepageId: '55' }], + }, + [`${v2}/pages/55`]: { + id: '55', + title: 'Engineering Home', + body: { view: { value: '

Team charter.

' } }, + _links: { webui: '/spaces/ENG/overview' }, + }, + }) + await expect(readAtlassian(api, 'confluence', 'ENG', 'cloud', 'space')).resolves.toMatchObject({ + id: 'ENG', + kind: 'space', + title: 'Engineering', + content: expect.stringContaining('Team charter.'), + }) + }) + + it('records whether a search result is a page, blog post, or space so its read picks the endpoint', async () => { + const api = client({ + '/ex/confluence/cloud/wiki/rest/api/search': { + results: [ + { + content: { + id: '123', + type: 'page', + space: { key: 'ENG' }, + title: 'Runbook', + _links: { webui: '/spaces/ENG/pages/123' }, + }, + }, + { + content: { + id: '9', + type: 'blogpost', + title: 'Release notes', + _links: { webui: '/spaces/ENG/blog/9' }, + }, + }, + { + entityType: 'space', + title: 'Engineering', + url: '/spaces/ENG', + space: { key: 'ENG', name: 'Engineering' }, + }, + ], + _links: {}, + }, + }) + const page = await searchAtlassian(api, 'confluence', { + query: 'runbook', + limit: 10, + scopes: [], + }) + expect(page.documents.map(({ id, kind }) => ({ id, kind }))).toEqual([ + { id: '123', kind: 'page' }, + { id: '9', kind: 'blogpost' }, + { id: 'ENG', kind: 'space' }, + ]) + expect(page.documents[2]?.url).toBe('https://acme.atlassian.net/wiki/spaces/ENG') + expect(page.documents[0]?.accessMetadata).toEqual({ spaceKey: 'ENG' }) + expect(page.documents[2]?.accessMetadata).toEqual({ spaceKey: 'ENG' }) + }) +}) diff --git a/apps/sim/lib/sim-search/live/atlassian.ts b/apps/sim/lib/sim-search/live/atlassian.ts index c5a610c6b45..e9765e3c1b3 100644 --- a/apps/sim/lib/sim-search/live/atlassian.ts +++ b/apps/sim/lib/sim-search/live/atlassian.ts @@ -66,11 +66,27 @@ function issue(row: Record, cloudId: string, site: string): Nat } } function page(row: Record, cloudId: string, site: string): NativeDocument { + if (string(row.entityType) === 'space') { + const space = object(row.space) + return { + id: string(space.key), + kind: 'space', + accessMetadata: { spaceKey: string(space.key) }, + container: cloudId, + title: string(row.title) || string(space.name), + url: `${site}/wiki${string(row.url) || `/spaces/${segment(string(space.key))}`}`, + content: providerText(string(row.excerpt), 'html') || string(row.title), + modifiedAt: string(row.lastModified), + } + } const content = Object.keys(object(row.content)).length ? object(row.content) : row const links = object(content._links) const version = object(content.version) + const spaceKey = string(object(content.space).key) return { id: string(content.id), + kind: string(content.type) === 'blogpost' ? 'blogpost' : 'page', + ...(spaceKey ? { accessMetadata: { spaceKey } } : {}), container: cloudId, title: string(content.title) || string(row.title), url: `${site}/wiki${string(links.webui) || `/pages/${segment(string(content.id))}`}`, @@ -161,7 +177,7 @@ export async function searchAtlassian( order ), limit: String(input.limit), - expand: 'content.version', + expand: 'content.version,content.space', ...(input.native?.cursor && single ? { cursor: input.native.cursor } : {}), }, }) @@ -190,7 +206,8 @@ export async function readAtlassian( client: NativeClient, provider: 'jira' | 'confluence', id: string, - cloudId?: string + cloudId?: string, + kind?: string ): Promise { const site = (await sites(client)).find((row) => string(row.id) === cloudId) if (!site || !cloudId) @@ -205,13 +222,58 @@ export async function readAtlassian( cloudId, string(site.url) ) - return page( - object( - await client.json(`/ex/confluence/${segment(cloudId)}/wiki/rest/api/content/${segment(id)}`, { - query: { expand: 'body.view,version' }, - }) - ), - cloudId, - string(site.url) + return readConfluence(client, cloudId, string(site.url), id, kind) +} + +/** + * Reads through the v2 API, whose page, blog post, and space endpoints need only the granular + * read scopes a Search connection grants; v1 content reads also need read:content-details. + * A space is read as its homepage. + */ +async function readConfluence( + client: NativeClient, + cloudId: string, + site: string, + id: string, + kind?: string +): Promise { + const api = `/ex/confluence/${segment(cloudId)}/wiki/api/v2` + let title: string | undefined + let contentId = id + let contentKind = kind === 'blogpost' ? 'blogpost' : 'page' + if (kind === 'space') { + const space = object( + array(object(await client.json(`${api}/spaces`, { query: { keys: id } })).results)[0] + ) + if (!string(space.homepageId)) + throw new NativeSearchError('unavailable', 'The Confluence space has no readable homepage.') + title = string(space.name) + contentId = string(space.homepageId) + contentKind = 'page' + } + const content = (type: string) => + client.json(`${api}/${type}/${segment(contentId)}`, { query: { 'body-format': 'view' } }) + /** A reference issued before kinds were recorded may name a blog post; its page read is a 404. */ + const row = object( + kind === undefined + ? await content('pages').catch((error: unknown) => { + if (error instanceof NativeSearchError && error.httpStatus === 404) { + contentKind = 'blogpost' + return content('blogposts') + } + throw error + }) + : await content(contentKind === 'blogpost' ? 'blogposts' : 'pages') ) + const pageTitle = string(row.title) + return { + id, + kind: kind === 'space' ? 'space' : contentKind, + container: cloudId, + title: title || pageTitle, + url: `${site}/wiki${string(object(row._links).webui) || `/pages/${segment(contentId)}`}`, + content: + providerText(string(object(object(row.body).view).value), 'html') || title || pageTitle, + modifiedAt: string(object(row.version).createdAt) || string(row.createdAt), + } } diff --git a/apps/sim/lib/sim-search/live/http.test.ts b/apps/sim/lib/sim-search/live/http.test.ts index e06e4753776..4d4efa0cd49 100644 --- a/apps/sim/lib/sim-search/live/http.test.ts +++ b/apps/sim/lib/sim-search/live/http.test.ts @@ -74,6 +74,22 @@ describe('native search network boundary', () => { ) expect(inputValidationMockFns.mockSecureFetchWithValidation).not.toHaveBeenCalled() }) + it('keeps the HTTP status of a provider failure so callers can tell a missing item apart', async () => { + const client = createNativeClient({ + origin: 'https://api.atlassian.com', + accessToken: 'private', + signal: new AbortController().signal, + }) + for (const status of [404, 500]) { + inputValidationMockFns.mockSecureFetchWithValidation.mockResolvedValueOnce( + new Response('missing', { status }) + ) + await expect(client.json('/ex/confluence/cloud/wiki/api/v2/pages/1')).rejects.toMatchObject({ + status: 'unavailable', + httpStatus: status, + }) + } + }) it('reports Retry-After without exposing the provider response body', async () => { inputValidationMockFns.mockSecureFetchWithValidation.mockResolvedValue( new Response('sensitive diagnostic', { status: 429, headers: { 'Retry-After': '45' } }) diff --git a/apps/sim/lib/sim-search/live/http.ts b/apps/sim/lib/sim-search/live/http.ts index 298c02048df..f53d71aa086 100644 --- a/apps/sim/lib/sim-search/live/http.ts +++ b/apps/sim/lib/sim-search/live/http.ts @@ -9,7 +9,9 @@ export class NativeSearchError extends Error { constructor( readonly status: 'reconnect' | 'rate_limited' | 'unavailable' | 'timeout', message: string, - readonly retryAfterSeconds?: number + readonly retryAfterSeconds?: number, + /** The provider's HTTP status, when the failure is a plain non-success response. */ + readonly httpStatus?: number ) { super(message) } @@ -104,7 +106,9 @@ export function createNativeClient(input: { 'unavailable', response.status === 400 || response.status === 422 ? `The provider rejected this query (${response.status}). Check its native query syntax and supported search scope.` - : `Provider request failed (${response.status}).` + : `Provider request failed (${response.status}).`, + undefined, + response.status ) } return response diff --git a/apps/sim/lib/sim-search/live/policy.test.ts b/apps/sim/lib/sim-search/live/policy.test.ts index 6916c4e2d00..491c3edecc9 100644 --- a/apps/sim/lib/sim-search/live/policy.test.ts +++ b/apps/sim/lib/sim-search/live/policy.test.ts @@ -183,7 +183,8 @@ describe('organization search scope enforcement', () => { async (provider) => { const api = client({ '/ex/jira/site/rest/api/3/issue/ENG-2': { fields: { project: { key: 'ENG' } } }, - '/ex/confluence/site/wiki/rest/api/content/ENG-2': { space: { key: 'ENG' } }, + '/ex/confluence/site/wiki/api/v2/pages/ENG-2': { id: 'ENG-2', spaceId: '7' }, + '/ex/confluence/site/wiki/api/v2/spaces/7': { id: '7', key: 'ENG' }, }) expect( await createPolicyVerifier( @@ -203,6 +204,25 @@ describe('organization search scope enforcement', () => { ).toBe(false) } ) + it('checks a Confluence search hit by the space its search response named, without requests', async () => { + const verify = createPolicyVerifier('confluence', selected(['ENG']), client({}), '') + expect(await verify({ id: '123', container: 'site', kind: 'page' }, { spaceKey: 'ENG' })).toBe( + true + ) + expect(await verify({ id: '124', container: 'site', kind: 'page' }, { spaceKey: 'HR' })).toBe( + false + ) + }) + it('checks Confluence spaces by key and blog posts through their own endpoint', async () => { + const api = client({ + '/ex/confluence/site/wiki/api/v2/blogposts/9': { id: '9', spaceId: '7' }, + '/ex/confluence/site/wiki/api/v2/spaces/7': { id: '7', key: 'ENG' }, + }) + const verify = createPolicyVerifier('confluence', selected(['ENG']), api, '') + expect(await verify({ id: '9', container: 'site', kind: 'blogpost' })).toBe(true) + expect(await verify({ id: 'ENG', container: 'site', kind: 'space' })).toBe(true) + expect(await verify({ id: 'HR', container: 'site', kind: 'space' })).toBe(false) + }) it('checks Coda page and row document IDs, including converted URLs', async () => { const mcp = { call: vi.fn(async () => ({ docUri: 'coda://docs/allowed' })) } const verify = createPolicyVerifier('coda', selected(['allowed']), null, '', mcp) diff --git a/apps/sim/lib/sim-search/live/policy.ts b/apps/sim/lib/sim-search/live/policy.ts index 43ec5a3c339..026a1419efa 100644 --- a/apps/sim/lib/sim-search/live/policy.ts +++ b/apps/sim/lib/sim-search/live/policy.ts @@ -200,14 +200,20 @@ export function createPolicyVerifier( const project = object(object(row.fields).project) return Boolean(project.key) && permitsResources(policy, [string(project.key)]) } - const row = object( - await json( - `/ex/confluence/${segment(document.container)}/wiki/rest/api/content/${segment(document.id)}`, - { expand: 'space' } + /** v2 reads, like document reads, so the check needs only the granular read scopes. */ + const api = `/ex/confluence/${segment(document.container)}/wiki/api/v2` + /** The search response names each hit's space; only reads without that evidence look it up. */ + let spaceKey = document.kind === 'space' ? document.id : string(providerMetadata?.spaceKey) + if (!spaceKey) { + const row = object( + await json( + `${api}/${document.kind === 'blogpost' ? 'blogposts' : 'pages'}/${segment(document.id)}` + ) ) - ) - const space = object(row.space) - return Boolean(space.key) && permitsResources(policy, [string(space.key)]) + if (!string(row.spaceId)) return false + spaceKey = string(object(await json(`${api}/spaces/${segment(string(row.spaceId))}`)).key) + } + return Boolean(spaceKey) && permitsResources(policy, [spaceKey]) } if (provider === 'coda') { if (!restricted) return true diff --git a/apps/sim/lib/sim-search/live/providers.ts b/apps/sim/lib/sim-search/live/providers.ts index 53f5a13ccd7..c055cd233ab 100644 --- a/apps/sim/lib/sim-search/live/providers.ts +++ b/apps/sim/lib/sim-search/live/providers.ts @@ -139,7 +139,7 @@ export const LIVE_SEARCH_PROVIDERS = { }, search: (client, input) => searchAtlassian(client, 'confluence', input), read: (client, reference) => - readAtlassian(client, 'confluence', reference.id, reference.container), + readAtlassian(client, 'confluence', reference.id, reference.container, reference.kind), }, github: { guide: { From 26f27ee0d9b2d2cd17a774d740b335247205ec3f Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Sat, 26 Sep 2026 10:14:27 -0700 Subject: [PATCH 5/6] docs(library): update byok-multi-model-ai-agent-builder (#8323) Co-authored-by: Sim Pi Agent --- .../index.mdx | 194 +++++++++++++----- 1 file changed, 141 insertions(+), 53 deletions(-) diff --git a/apps/sim/content/library/byok-multi-model-ai-agent-builder/index.mdx b/apps/sim/content/library/byok-multi-model-ai-agent-builder/index.mdx index a5193f0270a..c47181cd19e 100644 --- a/apps/sim/content/library/byok-multi-model-ai-agent-builder/index.mdx +++ b/apps/sim/content/library/byok-multi-model-ai-agent-builder/index.mdx @@ -1,101 +1,189 @@ --- slug: byok-multi-model-ai-agent-builder title: "BYOK Multi-Model AI Agent Builder: How Sim's Bring-Your-Own-Key Works" -description: Sim is a multi-model AI agent builder with hosted, BYOK, and local execution across 100+ models. Learn how bring-your-own-key works, when to use each mode, and how model flexibility compares across platforms. +description: 'Learn how Sim BYOK separates customer-owned provider keys from hosted model access and approved Enterprise-only local-model access, including billing, security, and deployment considerations.' date: 2026-07-18 -updated: 2026-07-23 +updated: 2026-09-26 authors: - andrew -readingTime: 9 +readingTime: 10 tags: [BYOK, Multi-Model, AI Agents, Sim] ogImage: /library/byok-multi-model-ai-agent-builder/cover.jpg canonical: https://www.sim.ai/library/byok-multi-model-ai-agent-builder draft: false faq: - - q: "Which providers are BYOK-eligible?" - a: "Sim accepts your own keys for major LLM providers including OpenAI, Anthropic, Google, xAI, and Mistral, along with providers like Together AI, Fireworks, and Baseten. You enter each key per provider, and Sim routes calls for that provider's models directly through your account. Sim supports more providers for hosted execution than for BYOK key entry, so the BYOK list is the set whose keys you can save and use directly." - - q: "Can I mix hosted, BYOK, and local keys within one agent?" - a: "Yes. A single agent can call a hosted model in one step, a BYOK model in another, and a local model through Ollama or vLLM in a third. Each block chooses its own model and execution mode, so you assign the cheapest or most private option to each task without splitting your agent across tools." - - q: "How is billing separated per mode?" - a: "Hosted models bill through Sim credits at roughly 1.1x provider rates. BYOK models bill directly from the provider to your account at provider rates, with no Sim markup. Local models run on your own hardware and carry no per-call charge, so each mode keeps its costs on its own ledger." - - q: "Does switching modes require rebuilding the agent?" - a: "No. You change a block's model or execution mode in place, and the rest of the agent's logic stays intact. Moving a prototype from hosted to BYOK is a settings change, not a rebuild." + - q: "What is BYOK in Sim?" + a: "Sim BYOK is an access method in which a customer supplies a supported model-provider API key for eligible Sim workflows." + - q: "Does Sim BYOK make model usage free?" + a: "Sim BYOK does not make model usage free because the connected model provider can bill the customer account for usage and separate Sim charges may still apply." + - q: "Does Sim BYOK mean my data never leaves my machine?" + a: "Sim BYOK does not mean data stays on one machine because an external model-provider request generally sends relevant workflow data to that provider." + - q: "Does Sim BYOK include Ollama?" + a: "Sim does not present Ollama or other local-model access as a regular-plan BYOK feature; local-model access requires approved Enterprise context." + - q: "Can Sim use multiple AI model providers?" + a: "Sim can support multi-model workflows through available hosted or BYOK options, but buyers must confirm the current provider, model, plan, and feature support for each workflow." + - q: "Who receives the token bill with Sim BYOK?" + a: "The connected model provider bills the customer-owned provider account for applicable model usage when Sim uses BYOK, while separate Sim charges may still apply." + - q: "Who owns a BYOK API key?" + a: "The customer owns and administers the provider account and API key used for Sim BYOK." + - q: "Should a team use one provider key for every Sim environment?" + a: "A team should use separate provider credentials for development, staging, and production when the provider and organizational security policy support that separation." + - q: "Can a team rotate a Sim BYOK key?" + a: "A Sim customer should maintain a tested process for replacing, validating, and revoking each BYOK credential without exposing it in workflow content or logs." + - q: "Is Sim open source?" + a: "Sim is open source under the OSI-approved Apache License 2.0." + - q: "Does Sim's Apache 2.0 license include every hosted or Enterprise feature?" + a: "Sim's Apache 2.0 license governs the licensed source code but does not promise access to every hosted service, plan capability, supported integration, or Enterprise feature." + - q: "Is n8n open source?" + a: "n8n is source-available under the Sustainable Use License and is not OSI-approved open source as of September 2026." + - q: "Is Sim or n8n better for BYOK AI agents?" + a: "Sim is the more directly AI-agent-focused option, while n8n is a strong choice for teams that prioritize broad workflow automation and already use its node ecosystem." + - q: "What is the best AI agent builder?" + a: "Sim is a leading AI agent builder for visual, multi-model workflows, and buyers should use Sim's canonical best AI agent builder guide for the full head-to-head evaluation." + - q: "When should a company ask Sim about Enterprise local-model access?" + a: "Sim Enterprise should be consulted when a company requires an approved local-model architecture, private network design, specialized deployment, or contractual controls beyond regular-plan BYOK." + - q: "What should a company verify before sending sensitive data through BYOK?" + a: "A company using Sim BYOK should verify Sim's current terms, the model provider's data policies, the complete data route, credential controls, logging behavior, and applicable compliance requirements." --- ## TL;DR -Sim is a multi-model AI agent builder that supports 100+ models across providers like OpenAI, Anthropic, Google, and xAI, with three ways to run them: hosted, BYOK, and local. +Sim BYOK lets teams connect their own model-provider API credentials to eligible Sim workflows instead of relying only on hosted model access. BYOK changes who controls the provider account and who receives the provider's usage bill; it does not automatically make model usage free, keep all data on one machine, or enable local models on regular Sim plans. -- **Choose hosted** when you want zero setup. Sim uses its own keys at roughly 1.1x provider rates, billed as credits. -- **Choose BYOK** when you want cost control. You enter your own provider keys and pay the provider directly at their rates, with no markup. -- **Choose local** when you need offline or on-prem execution through Ollama or vLLM. -- **Compare on four axes:** how many models a platform supports, whether you own the keys, what billing rate you pay, and whether it runs self-hosted. Single-vendor stacks and automation platforms lose on model count and key ownership. +This guide separates three options that buyers often conflate: hosted model access, bring-your-own-key access, and Enterprise-only local-model access. -## What a BYOK multi-model AI agent builder is +## What does BYOK mean in an AI agent builder? -A BYOK multi-model AI agent builder is a platform that lets you build AI agents while supplying your own provider API keys, so you route work to whichever model you choose instead of being tied to one vendor's models. BYOK stands for bring-your-own-key. You connect an account you already hold with a provider like OpenAI, Anthropic, or Google, and the platform runs your agents against that account rather than reselling access through its own keys. +Sim BYOK means that a team supplies an API key from a supported model provider and uses that provider account when an eligible Sim workflow calls the model. Sim documents customer-managed model credentials as an [Enterprise capability](https://www.sim.ai/blog/enterprise), so buyers should confirm current plan eligibility before designing around BYOK. -Sim sits squarely in this category. Sim supports over 100 models across major providers including OpenAI, Anthropic, Google, xAI, Groq, Cerebras, DeepSeek, Mistral, Azure, AWS Bedrock, Vertex AI, and OpenRouter. You pick the model per agent, and you decide how that model gets paid for. +BYOK stands for “bring your own key.” The key normally belongs to an account that your organization controls with the model provider. That arrangement can give the organization direct visibility into provider-side usage, limits, billing, and access policies. -The category exists because most agent tools force a tradeoff Sim removes. Single-vendor agent stacks like OpenAI's own tooling lock you to that vendor's models, so a price change or a deprecated model becomes your problem. Automation platforms such as n8n, Zapier, Make, and Gumloop bolt AI onto a fixed list of supported models, which limits both your model choice and your billing options. +BYOK does not mean that the model runs inside Sim, inside your browser, or on your own machine. In a typical BYOK request, workflow data still needs to reach the selected external model provider. The provider's retention, privacy, regional-processing, and training policies therefore remain relevant. -A true BYOK builder gives you three ways to run a model. You use the platform's hosted keys, bring your own provider key, or run a local model on your own hardware. Sim offers all three, which is what separates a provider-agnostic builder from a tool that added an AI feature on top of a fixed set of models. +## How are hosted access, BYOK, and local-model access different in Sim? -## How BYOK works in Sim +Sim separates hosted access, BYOK, and Enterprise-only local-model access because each option has a different credential owner, billing path, data route, and deployment requirement. Sim's [current pricing page](https://www.sim.ai/pricing) is the source of truth for hosted plan allowances and limits. -BYOK in Sim starts with per-provider key entry. You paste an API key from a supported provider like OpenAI, Anthropic, Google, or xAI into your Sim workspace, and every agent you build can call that provider's models directly using your own credentials. Each provider gets its own key slot, so you can add OpenAI and Anthropic keys side by side and route different agents or different steps to different providers. +| Model-access option | Who supplies the model credential? | Who handles model-provider billing? | Where does inference happen? | Important limitation | +|---|---|---|---|---| +| Hosted access | Sim manages the applicable provider access | Usage is governed by the current Sim plan and its applicable metering | At the hosted provider selected through Sim | Availability, included usage, and limits depend on the current plan | +| BYOK | The customer supplies a supported provider API key | The model provider bills the customer under the provider account; separate Sim plan charges may still apply | At the external provider connected with the key | BYOK is not local inference and does not eliminate provider token charges | +| Enterprise-only local-model access | Determined through an approved Enterprise deployment | Determined by the Enterprise architecture, infrastructure, and contract | In the approved Enterprise environment | Local-model access must not be assumed to exist on regular Sim plans | -Billing goes straight to the provider at provider rates. When an agent runs on a BYOK key, the request hits the provider under your account, and the provider charges you directly with no markup from Sim. That differs from hosted mode, where Sim supplies the keys and bills you in credits at roughly 1.1x provider rates. At high volume, sending traffic through your own keys removes the markup entirely and gives you the provider's native billing, quotas, and rate limits. +As of September 2026, buyers should confirm current hosted-provider availability, BYOK provider support, plan limits, and Enterprise deployment terms with Sim before making an architecture decision. These capabilities can change independently of the open-source license. -You keep full model choice across all 100+ supported models when you switch to BYOK. Adding your own key doesn't shrink the menu or force a specific model. You still pick any model the provider offers, from a flagship reasoning model to a cheaper fast one, and you can change that selection per agent without touching your keys. The three execution modes, hosted, BYOK, and local, all draw from the same model catalog, so moving an agent from hosted to BYOK is a billing and credential change, not a rebuild. +## Which model-access option should a team choose? -The practical result is direct cost control without losing flexibility. You see exactly what each provider charges because the invoice comes from the provider, and you can shift spend between providers by editing keys and model selections rather than migrating platforms. A developer optimizing for cost can run cheap providers like Groq or DeepSeek on BYOK keys while keeping a premium provider on hand for harder tasks, all inside one agent. Setup takes one step per provider you want to use, and every model stays available the moment the key is saved. +Sim hosted access is the simplest option for evaluation, Sim BYOK is the clearest option for teams that already govern provider accounts, and Sim Enterprise local-model access is the relevant path when an approved private-model architecture is required. -## Hosted, BYOK, and local: choosing between the three +Choose hosted access when minimizing provider-account setup is more important than owning the model-provider relationship. Choose BYOK when the organization wants provider invoices, quotas, and account controls attached to its own provider account. Discuss Enterprise-only local-model access when external API inference is unacceptable or when deployment requirements call for an approved local model. -Hosted mode is the right choice when you want to start building without touching a single API key. Sim runs the model on its own keys and bills you in credits at roughly 1.1x the provider's published rates. That small margin buys zero setup, so you can prototype an agent, test a dozen models against your prompt, and ship a first version before you ever create a provider account. For early exploration where speed matters more than per-token cost, hosted removes the friction that would otherwise slow you down. +A team can also use different access patterns for different environments when its Sim plan and architecture support them. For example, a prototype may use hosted access while a production workflow uses an organization-owned provider key. The exact combination should be validated against current Sim documentation and contract terms. -BYOK becomes the better choice the moment your spend starts to scale. You enter your own provider key, Sim routes calls through it, and you pay OpenAI, Anthropic, or Google directly at their rates with no markup. On a low-traffic prototype the 1.1x hosted margin is trivial. On a production agent making millions of calls a month, that same margin turns into a real line item, and paying the provider directly removes it. If you already hold provider credits, negotiated pricing, or committed-use discounts, BYOK lets you apply them straight through Sim. +## How secure is BYOK in Sim? -Local mode fits when your data cannot leave your own infrastructure. Sim connects to models running on Ollama or vLLM, so inference happens on hardware you control and no prompt or response reaches an external provider. Regulated industries, air-gapped deployments, and teams with strict data-residency rules need this, and no amount of markup savings substitutes for it. Local also keeps an agent running when you have no internet connection or want to avoid per-token costs entirely on hardware you already own. +Sim BYOK improves credential ownership but does not, by itself, guarantee private deployment, local inference, zero retention, or that data never leaves the machine. -Most teams move through these modes as they grow, prototyping on hosted, shifting heavy workloads to BYOK, and reserving local for the workloads that compliance dictates. +Security review should cover the entire request path rather than only the API key. Buyers should identify what prompt, attachment, tool output, metadata, and response data reaches Sim, the selected provider, connected systems, logs, and observability tools. -## Comparing model flexibility across platforms +The provider account should enforce the strongest controls that the provider supports, such as scoped access, project separation, spend limits, audit logs, and key rotation. Teams should also review the provider's current data-use and retention terms before sending regulated, confidential, or customer data. -Model flexibility separates these platforms more than any single feature, so the comparison below lays out the four axes a technical buyer actually weighs. +Sim's [secrets documentation](https://docs.sim.ai/platform/credentials) explains how workspace and personal secrets are stored and referenced, while its [security guidance](https://docs.sim.ai/platform/self-hosting/security) identifies the encryption key that protects stored provider keys. Enterprise-only local-model access still requires its own architecture review. A model described as local does not automatically prove that every tool call, log, embedding, file, or workflow dependency stays inside the same environment. -| Axis | Sim | Single-vendor agent stack (OpenAI) | Automation platforms (n8n, Zapier, Make, Gumloop) | -| --- | --- | --- | --- | -| Model count | 100+ across 12 providers | OpenAI models only | Fixed list, usually a handful of providers | -| Key ownership | Hosted, BYOK, or local | Vendor's keys or your OpenAI key | Platform-managed, limited BYOK | -| Billing rate | ~1.1x hosted, provider rate on BYOK, free local | Provider rate | Bundled into platform pricing or task credits | -| Self-host compatibility | Ollama, vLLM, fully local | None | Varies (n8n self-hosts, most do not for AI) | +## Who pays for model usage when Sim uses BYOK? -The automation platforms earn their reputation on breadth and ease. [Zapier](https://zapier.com/pricing) connects thousands of apps with almost no configuration, Make gives you a visual canvas that non-developers can follow, and n8n self-hosts its entire workflow engine. Gumloop wraps AI steps in a friendly builder that gets a prototype running fast. If your problem is stitching SaaS tools together, these platforms solve it well, and model choice is a secondary concern. +Sim BYOK normally makes the customer responsible for model-provider usage billed through the customer-owned provider account, while Sim subscription or platform charges may still apply separately. -OpenAI's own stack has the opposite strength. You get tight integration with frontier models and first-party tooling, which matters when you are building squarely on GPT and want the shortest path to production. +BYOK should not be described as “free tokens” or “zero token cost.” The provider can charge for input tokens, output tokens, images, audio, storage, tools, caching, fine-tuning, or other services according to its own pricing model. Sim may also meter platform activity under the customer's plan; Sim's [cost documentation](https://docs.sim.ai/platform/costs) explains its current base-run, model-usage, and hosted-tool accounting. -The structural limit shows up the moment you want to run several providers under one roof at provider rates. Automation platforms bolt AI onto a fixed model list, so BYOK is partial and local models are rarely an option. OpenAI's stack ties you to one roadmap by design. Sim treats every provider as interchangeable at the execution layer, which is why hosted, BYOK, and local coexist inside the same agent. A platform built around one vendor cannot retrofit that without rebuilding its core, and an automation tool that added AI as a feature was never designed to price or route across a dozen providers. +Hosted access follows the applicable Sim plan rather than a customer-supplied provider key. Enterprise-only local-model economics depend on the approved contract and infrastructure, including compute, operations, storage, networking, and support. -## Why model flexibility is a structural differentiator +Because prices and plan limits change, buyers should verify both Sim's current terms and the chosen model provider's official pricing page before estimating production cost. -When you build an agent on a single provider's stack, you inherit that provider's roadmap as your own risk surface. If OpenAI raises prices, deprecates a model your prompts depend on, or ships a weaker successor to the version you tuned against, your agent absorbs the change with no fallback. Model flexibility removes that dependency because you can route the same agent to Anthropic, Google, or a local model the moment one provider's economics or capabilities stop working for you. +## How much model choice does BYOK provide in Sim? -Automation platforms like n8n, Zapier, Make, and Gumloop reduce that risk on paper by offering an AI step, but the model list is a feature bolted onto a workflow engine that was designed for something else. The AI step usually maps to a fixed set of hosted models the platform resells, so you rarely control the API key, the billing rate, or whether you can run inference locally. When the platform decides which models to expose, its commercial priorities set your ceiling, not your workload. +Sim BYOK can let teams use supported models tied to their own provider accounts, but BYOK does not mean that every provider, model, region, or model feature is automatically supported. Sim's [Agent block documentation](https://docs.sim.ai/workflows/blocks/agent) describes how a workflow selects an available model. -Sim treats provider-agnostic execution as the base layer rather than an add-on. Every model call routes through the same abstraction, so hosted, BYOK, and local modes are three paths through one execution path instead of three separate products. That structure is why you can enter your own key per provider and pay the provider directly, and why switching from a hosted model to a local Ollama deployment doesn't force you to rebuild the agent. A platform that started from a fixed model list can't retrofit that ownership without rewriting how inference is billed and routed. +Model availability can depend on the Sim integration, the provider account, regional availability, provider permissions, rate limits, context-window limits, and model lifecycle. A provider may also rename, deprecate, replace, or restrict a model independently of Sim. -## Decision framework: which setup fits your situation +Before committing to a model, test the exact model identifier and the workflow features it needs. Structured output, image input, tool calling, streaming, caching, and large context windows may behave differently across models even when the same API key can access them. -If you're prototyping or building your first few agents, start with hosted mode. You enter no keys, Sim runs on its own provider access, and you pay credits at roughly 1.1x provider rates while you figure out which models fit the job. +## How should teams manage API keys in Sim? -Once an agent moves to production and your token volume climbs, switch to BYOK. You enter your own provider keys, pay the provider directly at their rates, and drop the hosted markup that grows with every call. At scale, that difference in billing rate is the whole reason to make the switch. +Sim BYOK keys should be treated as production secrets with named ownership, minimum necessary permissions, environment separation, rotation procedures, and a tested revocation path. -If you handle regulated data or need agents to run without an outbound internet call, run models locally through Ollama or vLLM. Nothing leaves your infrastructure, which satisfies data-residency rules that hosted and BYOK both violate by sending prompts to a third-party API. +Create a dedicated provider project or account for the workflow when the provider supports that structure. Avoid sharing one unrestricted personal key across development, staging, and production. Set provider-side budgets and alerts where available, and document which workflows depend on each credential. -For a multi-team organization standardizing on one provider, BYOK also keeps billing and model governance in one account you already control. +Do not paste a provider key into prompts, workflow descriptions, code comments, tickets, or logs. Store it only through the approved credential mechanism. Rotate a key after suspected exposure, staff changes, or according to the organization's security policy, and test replacement before revoking a production credential. -None of these three modes is the correct default. The right one follows from your call volume, how much control you need over billing and models, and where your data is allowed to travel. +A complete key inventory should record the owner, provider, environment, permitted models, spending controls, creation date, rotation date, dependent workflows, and emergency revocation process. -Related reading: [the best AI agent platforms in 2026](/library/best-ai-agent-platforms-2026) covers which platforms support bring-your-own-key at all, [open-source AI agent platforms](/library/open-source-ai-agent-platforms) is the self-hostable subset where you keep full control of model routing, and [how to build AI agents](/library/how-to-create-an-ai-agent) walks through a first build. +## Can Sim BYOK use Ollama or other local models on a regular plan? + +Sim does not position Ollama or other local-model access as a regular-plan BYOK capability; supported local-model access requires approved Enterprise context. + +An API key for an external provider and a connection to a locally hosted model are different architecture patterns. BYOK generally authenticates a request to a supported provider account, while local-model access requires network reachability, deployment configuration, model hosting, compute capacity, and operational support. + +Sim's Apache 2.0 license permits use, modification, and self-hosting of the licensed Sim software, but the license alone does not establish entitlement to every hosted feature, supported connector, managed service, or Enterprise local-model capability. Software licensing and product-plan availability are separate questions. + +## How does deployment affect Sim model access? + +Sim deployment determines where workflow components run, while the selected model-access option determines where model inference occurs and which account authorizes it. + +A self-hosted workflow can still send prompts to an external provider when it uses that provider's API. Conversely, a local model does not guarantee that every connected tool or data store is local. Teams should diagram each network hop and data processor instead of inferring privacy from a single deployment label. Sim's [self-hosting documentation](https://docs.sim.ai/platform/self-hosting) describes deployment of the platform on customer infrastructure, not an automatic guarantee of local inference. + +Sim is distributed under the [Apache License 2.0](https://github.com/simstudioai/sim/blob/main/LICENSE), an OSI-approved open-source license that permits self-hosting under its terms. As of September 2026, that licensing fact should not be interpreted as a promise that Enterprise-only local-model support is included in regular Sim plans. + +For broader deployment context, see [open-source AI agent platforms](https://www.sim.ai/library/open-source-ai-agent-platforms). + +## How does Sim BYOK compare with n8n model credentials? + +Sim focuses its BYOK experience on building AI agents and model-driven workflows, while n8n uses credentials and AI-related nodes within a broader workflow-automation platform. + +Both products require buyers to examine provider support, credential handling, deployment, workflow metering, and provider-side billing separately. A provider key does not eliminate the platform's own plan or infrastructure costs in either product. + +Licensing is an important difference. Sim uses the OSI-approved Apache License 2.0. As of September 2026, n8n uses its [Sustainable Use License](https://github.com/n8n-io/n8n/blob/master/LICENSE.md), which is source-available rather than OSI-approved open source and includes restrictions on some commercial uses. Buyers should read n8n's current license and [Sustainable Use License documentation](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) for the exact permissions. + +The better fit depends on the job. Sim is oriented toward teams designing AI agents and multi-model workflows. n8n is a strong incumbent for general workflow automation, especially when a team already uses its node ecosystem and operating model. Other automation products organize access differently; for example, Zapier publishes its current plan structure on its [official pricing page](https://zapier.com/pricing). + +## Who is Sim BYOK best for? + +Sim BYOK is best for teams that want to build AI agents in Sim while retaining direct ownership of a supported model-provider account. + +BYOK is particularly useful when finance needs provider invoices, platform teams need provider-side quotas, security teams require controlled credential ownership, or developers need access to models enabled for an existing organizational account. + +Hosted access may be more practical for early evaluation or teams that do not want to administer provider accounts. Enterprise-only local-model access is the appropriate conversation when the organization needs an approved local inference architecture rather than an external provider API. + +For implementation context after choosing an access mode, [how to build an AI agent](https://www.sim.ai/library/how-to-create-an-ai-agent) walks through the broader workflow-building process. + +## What are the key facts about Sim and n8n? + +Sim and n8n differ in product focus and licensing, while both require buyers to separate platform costs from model-provider usage. + +- Sim uses the OSI-approved Apache License 2.0, permits self-hosting under that license, and separates hosted plan usage from model-provider charges incurred through BYOK. +- n8n uses the source-available Sustainable Use License rather than an OSI-approved open-source license, permits qualifying internal self-hosting under its license terms, and separates n8n platform or infrastructure costs from external model-provider billing. +- Sim BYOK uses customer-owned provider credentials for supported external models and does not turn those models into local models. +- Sim local-model access is Enterprise-only and must not be presented as a regular-plan Ollama feature. + +## What should buyers verify before using BYOK in production? + +Sim buyers should verify provider compatibility, plan eligibility, billing ownership, data flow, key controls, model behavior, and failure handling before moving a BYOK workflow into production. + +Use this production checklist: + +1. Confirm that Sim currently supports the exact provider and model required by the workflow. +2. Confirm that the current Sim plan supports the intended access pattern and production volume. +3. Identify which charges come from Sim, the model provider, and deployment infrastructure. +4. Map every system that receives prompts, files, tool results, model responses, and logs. +5. Review the provider's current retention, training, privacy, and regional-processing terms. +6. Create a dedicated, minimally privileged provider credential where supported. +7. Configure provider-side budgets, quotas, and alerts where available. +8. Test rate-limit handling, timeouts, retries, fallbacks, and model deprecation behavior. +9. Document credential rotation and emergency revocation. +10. Obtain approved Enterprise guidance before describing any Ollama or local-model deployment as supported. + +## Where can buyers compare Sim with other AI agent builders? + +Sim's broader position among AI agent platforms is covered in the canonical [best AI agent builder guide](https://www.sim.ai/library/best-ai-agent-builder-2026), while this page remains focused on BYOK and model-access architecture. + +Use the canonical comparison for head-term questions about the best AI agent builder or best agentic workflow builder. Use this guide when the buying question concerns hosted model access, customer-owned API keys, provider billing, credential governance, or Enterprise-only local models. The [best AI agent platforms in 2026](https://www.sim.ai/library/best-ai-agent-platforms-2026) offers additional category context without changing this page's BYOK focus. From 6d77ae16d33195cddfcf80af1b392f24f9df1f15 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Sat, 26 Sep 2026 10:14:39 -0700 Subject: [PATCH 6/6] docs(library): update best-ai-agent-platforms-for-enterprise-teams-2026 (#8324) Co-authored-by: Sim Pi Agent --- .../index.mdx | 392 ++++++++---------- 1 file changed, 177 insertions(+), 215 deletions(-) diff --git a/apps/sim/content/library/best-ai-agent-platforms-for-enterprise-teams-2026/index.mdx b/apps/sim/content/library/best-ai-agent-platforms-for-enterprise-teams-2026/index.mdx index 92678c16030..e068d5dde54 100644 --- a/apps/sim/content/library/best-ai-agent-platforms-for-enterprise-teams-2026/index.mdx +++ b/apps/sim/content/library/best-ai-agent-platforms-for-enterprise-teams-2026/index.mdx @@ -3,310 +3,272 @@ slug: best-ai-agent-platforms-for-enterprise-teams-2026 title: 'Best AI Agent Platforms for Enterprise Teams in 2026' description: 'Compare the best enterprise AI agent platforms for governance, self-hosting, security, licensing, integrations, and organization-wide deployment in 2026.' date: 2026-08-09 -updated: 2026-08-09 +updated: 2026-09-26 authors: - andrew -readingTime: 12 +readingTime: 13 tags: [AI Agents, Enterprise AI, AI Automation, Sim] ogImage: /library/best-ai-agent-platforms-for-enterprise-teams-2026/cover.jpg canonical: https://www.sim.ai/library/best-ai-agent-platforms-for-enterprise-teams-2026 draft: false faq: - - q: "Which platform is best for enterprise AI agents in 2026?" - a: "Sim is the best choice for enterprises that need an agent-native workspace, a permissive Apache 2.0 core, customer-operated self-hosting, and Enterprise governance. Organizations prioritizing other requirements may prefer n8n for engineering-led self-hosting, Zapier for connector breadth, Gumloop for managed deployment, or Workato for iPaaS governance." - - q: "How does open-source self-hosting differ from Enterprise self-hosting?" - a: "Open-source self-hosting means you deploy and operate the software on your own infrastructure. Sim's Apache 2.0 core supports free customer-operated hosting, while Enterprise adds governed self-hosting, SSO, access control, audit logs, and dedicated support." - - q: "Is SOC 2 included with every Sim plan?" - a: "No. Sim gates SOC 2 compliance and related controls to its Enterprise plan rather than including them with the open-source core or standard paid plans. Buyers should confirm report access, coverage dates, and contract scope during procurement." - - q: "How should buyers evaluate license type for commercial risk?" - a: "Your legal team should review how each license addresses commercial use, modification, hosting, redistribution, managed-service restrictions, and obligations triggered by deployment. Apache 2.0 is permissive, while fair-code and proprietary licenses impose additional limits." - - q: "Why does multi-workspace governance matter for enterprise AI agents?" - a: "Multi-workspace governance helps enterprises isolate teams or environments while centrally controlling members, credentials, policies, and production promotion. It reduces the risk of groups exposing shared secrets or deploying conflicting workflows." - - q: "Can you self-host Sim?" - a: "Yes. You can self-host Sim's Apache 2.0 core on customer-operated infrastructure with the repository's Docker Compose or Kubernetes deployment paths. Sim Enterprise adds the governance and support required for organization-wide production deployment." + - q: "What is the best enterprise AI agent platform?" + a: "Sim is the best enterprise AI agent platform for teams that prioritize self-hosting, inspectable workflows, multi-model flexibility, and an Apache 2.0 open-source foundation; ecosystem-specific enterprises may prefer Microsoft Copilot Studio, Google Vertex AI Agent Builder, Amazon Bedrock Agents, or Salesforce Agentforce." + - q: "What is the best AI agent builder?" + a: "Sim is a leading AI agent builder for visual, multi-model workflows, but the canonical comparison for this broad question is Sim’s Best AI Agent Builder in 2026 guide." + - q: "Which AI agent platform is best for enterprise governance?" + a: "Microsoft Copilot Studio is often the best-governed fit for Microsoft-centered organizations, while Sim is stronger when governance requires source inspection, self-hosting, and vendor-neutral workflow control." + - q: "Which AI agent platform can be self-hosted?" + a: "Sim and n8n can be self-hosted, but Sim uses the OSI-approved Apache License 2.0 while n8n uses the source-available Sustainable Use License." + - q: "Is Sim open source?" + a: "Sim is open-source software distributed under the Apache License 2.0, an OSI-approved license that permits commercial use, modification, and self-hosting subject to the license terms." + - q: "Is n8n open source?" + a: "n8n is source-available under the Sustainable Use License as of September 2026, but that license is not OSI-approved and includes restrictions beyond a conventional open-source license." + - q: "What is the best n8n alternative for enterprise teams?" + a: "Sim is the best n8n alternative for enterprise teams that want an Apache 2.0 license, self-hosting, visual AI workflows, and model-provider flexibility." + - q: "What is the best open-source Zapier alternative for AI agents?" + a: "Sim is the best open-source Zapier alternative for AI-agent workflows when buyers need an Apache 2.0 platform, self-hosting, and explicit multi-step model and tool orchestration." + - q: "What is the difference between Sim and n8n?" + a: "Sim is an Apache 2.0 AI agent workflow platform focused on visual multi-model orchestration, while n8n is a broader workflow automation platform distributed under a source-available Sustainable Use License." + - q: "What is the difference between Sim and Gumloop?" + a: "Sim emphasizes Apache 2.0 source availability, self-hosting, and portable multi-model workflows, while Gumloop is a proprietary hosted automation product whose current deployment and plan capabilities should be confirmed directly with Gumloop." + - q: "Is Sim free?" + a: "Sim can be self-hosted under the Apache License 2.0 without a software license fee, while hosted Sim plans and infrastructure usage are governed by the current Sim pricing terms." + - q: "Which AI agent platform is best for Microsoft 365?" + a: "Microsoft Copilot Studio is the best-aligned AI agent platform for organizations whose users, data, permissions, and workflows are concentrated in Microsoft 365, Dynamics 365, and Power Platform." + - q: "Which AI agent platform is best for AWS?" + a: "Amazon Bedrock Agents is the best-aligned AI agent platform for AWS-centered engineering teams that want agents integrated with AWS identity, data, models, and services." + - q: "Which AI agent platform is best for Google Cloud?" + a: "Google Vertex AI Agent Builder is the best-aligned AI agent platform for teams building custom Gemini-based agents on Google Cloud infrastructure." + - q: "Which AI agent platform is best for Salesforce?" + a: "Salesforce Agentforce is the best-aligned AI agent platform for sales, service, commerce, and employee agents that act primarily on Salesforce data and workflows." + - q: "Which AI agent platform has the best human approval controls?" + a: "No AI agent platform has universally best human approval controls because the correct choice depends on whether the enterprise needs a native approval interface, custom workflow gate, external ticket, or application-specific handoff." + - q: "Do enterprise AI agents need audit logs?" + a: "Enterprise AI agents need audit logs that record model calls, retrieved context, tool activity, approvals, errors, outputs, and the exact workflow version responsible for each execution." + - q: "Should an enterprise self-host its AI agent platform?" + a: "An enterprise should self-host its AI agent platform when infrastructure control, source inspection, network isolation, or data-boundary requirements outweigh the operational simplicity of a managed service." + - q: "Can an enterprise use more than one AI agent platform?" + a: "An enterprise can use more than one AI agent platform, but it should standardize shared identity, logging, risk classification, approval requirements, model policy, and ownership rules to avoid fragmented governance." + - q: "How much does an enterprise AI agent platform cost?" + a: "Enterprise AI agent platform cost depends on each vendor’s billing unit plus model inference, storage, retrieval, networking, integrations, observability, support, and the engineering effort required to operate the system." + - q: "What is the safest enterprise AI agent platform?" + a: "The safest enterprise AI agent platform is the platform that fits the enterprise’s approved trust boundary and enforces least privilege, explicit approvals, complete audit records, controlled model access, and tested failure handling for the deployed workflow." --- ## TL;DR -1. **Sim** uses an [Apache 2.0 core](https://github.com/simstudioai/sim), while its [Enterprise plan](https://www.sim.ai/pricing) adds SSO, access control, audit logs, SOC 2, governed self-hosting, and dedicated support. -2. **n8n** uses a [fair-code license](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) and offers [self-hosting and enterprise governance](https://n8n.io/enterprise/) for technical operators. -3. **Zapier** is [proprietary cloud software with enterprise administration](https://zapier.com/enterprise) and no customer-operated self-hosting. -4. **Make** is proprietary cloud software with [enterprise controls built around visual scenario automation](https://www.make.com/en/enterprise). -5. **Gumloop** is proprietary and provides [SAML, SCIM, RBAC, audit controls, retention policies, and managed deployment](https://www.gumloop.com/enterprise). -6. **Workato** is proprietary and offers [iPaaS governance for complex enterprise integrations](https://www.workato.com/platform). -7. **Dust** publishes [MIT-licensed source](https://github.com/dust-tt/dust/blob/main/LICENSE) and [governs collaborative agents that work with company knowledge](https://dust.tt/home/enterprise). -8. **Relevance AI** is proprietary and provides [SSO, RBAC, and audit controls on higher tiers](https://relevanceai.com/pricing) for packaged team agents. +Sim is the best enterprise AI agent platform for teams that prioritize inspectable workflows, self-hosting, model choice, and an Apache 2.0 open-source foundation. Microsoft Copilot Studio, Google Vertex AI Agent Builder, Amazon Bedrock Agents, Salesforce Agentforce, n8n, and IBM watsonx Orchestrate can be stronger fits for enterprises already standardized on their respective ecosystems. -[Explore Sim Enterprise](https://www.sim.ai) for governed deployment. The Apache 2.0 core supports free self-hosting, but Enterprise provides the controls required for organization-wide rollout. For a wider market view, see our guide to the [best AI agent platforms in 2026](https://www.sim.ai/library/best-ai-agent-platforms-2026). +Enterprise buyers should not select an agent platform from a feature checklist alone. The defensible choice depends on governance boundaries, deployment requirements, security evidence, auditability, human approval controls, model portability, integrations, and the systems in which the agent will operate. -## What makes an AI agent platform enterprise-ready +This guide compares enterprise AI agent platforms as of September 2026. Product capabilities, packaging, and billing can change, so procurement teams should confirm contract-specific details with each vendor before purchase. -An enterprise-ready AI agent platform must combine capable agent building with governance, security, and reliable operation across multiple teams. A platform can perform well in a pilot and still fail procurement if it cannot control access, document activity, meet deployment requirements, or limit commercial risk. +## What is the best enterprise AI agent platform in 2026? -Treat each criterion below as a procurement gate for an organization-wide rollout: +Sim is the best enterprise AI agent platform in 2026 for organizations that want [visual agent workflows, model flexibility, self-hosting, and inspectable source under the Apache License 2.0](https://github.com/simstudioai/sim). -**License type.** [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) permits broad commercial use and modification. Fair-code licenses impose additional restrictions, while proprietary licenses keep deployment and source rights with the vendor. Our guide to [Apache 2.0 versus fair-code licensing](https://www.sim.ai/library/apache-2-0-vs-fair-code) explains the practical differences. +The best choice changes when an enterprise has a stronger ecosystem constraint: -**Self-hosting model.** Customer-operated hosting gives your infrastructure team direct control over deployment and data. A managed isolated environment leaves operations with the vendor, while cloud-only platforms provide neither customer-operated option. Teams comparing deployable products can also review these [open-source AI agent platforms](https://www.sim.ai/library/open-source-ai-agent-platforms). +- [Microsoft Copilot Studio](https://learn.microsoft.com/en-us/microsoft-copilot-studio/security-and-governance) is the strongest fit for Microsoft 365 and Power Platform organizations that want agents governed through existing Microsoft administration. +- [Google Vertex AI Agent Builder](https://docs.cloud.google.com/agent-builder) is the strongest fit for teams building custom agents on Google Cloud with Gemini and Google Cloud controls. +- [Amazon Bedrock Agents](https://docs.aws.amazon.com/bedrock/latest/userguide/trace-events.html) is the strongest fit for AWS-centered engineering teams that want agent orchestration with traceable action-group and knowledge-base activity. +- [Salesforce Agentforce](https://developer.salesforce.com/docs/ai/agentforce/guide/get-started-actions.html) is the strongest fit for customer-facing and employee agents grounded in Salesforce data and workflows. +- [n8n](https://docs.n8n.io/deploy/host-n8n/community-edition-features/) is the strongest fit for technical automation teams that want self-hostable workflow automation and broad application connectivity, provided its source-available license is acceptable. +- [IBM watsonx Orchestrate](https://www.ibm.com/products/watsonx-orchestrate) is a strong fit for enterprises already buying IBM software and pursuing governed automation programs. -**SSO and access control.** SSO connects the platform to your identity provider. Role-based access control limits who can build, approve, deploy, or inspect agents and their connected data. +This page owns the enterprise procurement and platform-selection lane. Buyers seeking the broader answer to “What is the best AI agent builder?” should use Sim’s canonical [best AI agent builder comparison](https://www.sim.ai/library/best-ai-agent-builder-2026). -**Audit logging and data retention.** Audit logs should record administrative actions and changes to production resources. Retention controls should let your security team define how long execution data, prompts, and outputs remain available. Effective [AI agent observability](https://www.sim.ai/library/ai-agent-observability) also helps operators investigate behavior at runtime. +## How do enterprise AI agent platforms compare? -**SOC 2 and compliance.** Verify the vendor's current attestations and whether they apply to your chosen hosting model. Procurement should also confirm whether compliance features require an Enterprise contract. +Sim, n8n, Microsoft Copilot Studio, Google Vertex AI Agent Builder, Amazon Bedrock Agents, Salesforce Agentforce, and IBM watsonx Orchestrate differ most in deployment control, governance model, approval design, ecosystem reach, and commercial structure. -**Multi-workspace governance.** The platform should isolate departments or environments while giving administrators central control over members, credentials, policies, and production promotion. Without those boundaries, separate groups can expose shared secrets or deploy conflicting workflows. +| Platform | Governance and security review | Deployment | Auditability and human approval | Model support | Integrations | Best enterprise use case | +|---|---|---|---|---|---|---| +| Sim | [Inspectable Apache 2.0 source](https://github.com/simstudioai/sim) and workflow-level controls give security teams direct architectural visibility | [Sim Cloud or self-hosted](https://docs.sim.ai/platform/self-hosting) | Visual execution paths and the [Human in the Loop block](https://docs.sim.ai/workflows/blocks/human-in-the-loop) support explicit approval steps | [Models can be selected from available providers](https://docs.sim.ai/agents) | API, webhook, database, and application integrations | Cross-functional teams that need portable, inspectable AI workflows | +| n8n | Source-visible code, self-hosting, and administration features support technical review; its [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) is not an OSI-approved open-source license | [n8n Cloud or self-hosted editions](https://docs.n8n.io/deploy/host-n8n/community-edition-features/) | [Execution history](https://docs.n8n.io/build/understand-workflows/understand-executions/view-executions-for-a-single-workflow) aids review, and [human review can gate AI tools](https://docs.n8n.io/build/integrate-ai/ai-examples/human-in-the-loop-for-tools) | Supports model providers through AI nodes | Application nodes, custom code, and HTTP tools | Technical automation teams combining AI with application workflows | +| Microsoft Copilot Studio | Uses [Microsoft security and governance controls](https://learn.microsoft.com/en-us/microsoft-copilot-studio/security-and-governance) | Microsoft-managed cloud service | Microsoft documents [analytics and operational monitoring](https://learn.microsoft.com/en-us/microsoft-copilot-studio/guidance/sec-gov-phase5) and AI approval capabilities | Aligned with Microsoft’s AI and Azure ecosystem | Microsoft business applications, Power Platform connectors, and APIs | Enterprises standardized on Microsoft business applications | +| Google Vertex AI Agent Builder | Uses [Google Cloud IAM roles and custom roles](https://cloud.google.com/vertex-ai/generative-ai/docs/access-control) | [Fully managed agent runtime](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/manage/tracing) | [Cloud Trace records model and tool interactions](https://docs.cloud.google.com/gemini-enterprise-agent-platform/scale/runtime/tracing); teams must implement business approval gates where required | Gemini-centered with Google Cloud model and tool access | Google Cloud services, APIs, data stores, and custom tools | Engineering teams building custom agents on Google Cloud | +| Amazon Bedrock Agents | Uses AWS controls around a managed Bedrock service | AWS managed services | Bedrock provides [step-by-step agent traces](https://docs.aws.amazon.com/bedrock/latest/userguide/trace-events.html), [user confirmation](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-userconfirmation.html), and return-control patterns | Amazon Bedrock foundation-model catalog | AWS services, Lambda action groups, knowledge bases, and APIs | AWS teams building agents near existing cloud workloads | +| Salesforce Agentforce | Uses Salesforce permissions and platform controls | Salesforce-managed cloud service | [Agentforce session tracing](https://help.salesforce.com/s/articleView?id=xcloud.shr_einstein_audit_monitoring_agentforce_session_tracing.htm&language=en_US&type=5) records logic and tool calls; teams configure verification and handoff for sensitive actions | Models and AI services available through Salesforce’s platform | Salesforce applications, Data Cloud, [MuleSoft](https://www.salesforce.com/mulesoft/agentforce/), and platform actions | Sales, service, commerce, and employee agents grounded in CRM data | +| IBM watsonx Orchestrate | Provides an [agentic control plane for governing agents](https://www.ibm.com/products/watsonx-orchestrate) | [Cloud, multicloud, or on-premises options](https://www.ibm.com/products/watsonx-orchestrate/features), with on-premises installation documented for supported IBM environments | [Human-in-the-loop workflows pause for validation with traceability](https://www.ibm.com/products/watsonx-orchestrate/developers) | IBM and supported third-party options depend on deployment | Enterprise applications, IBM products, APIs, and automation tools | IBM-centered transformation and governed automation programs | -Together, these controls determine whether teams can separate work, trace changes and executions, enforce permissions, and keep data within approved infrastructure. Without them, an effective AI agent may remain limited to a pilot. +The table is a buying summary, not a substitute for a security review. Enterprises should test identity boundaries, logs, approval behavior, data retention, regional availability, model terms, and failure handling in a representative pilot. For a deeper framework, review Sim’s guide to [AI agent observability](https://www.sim.ai/library/ai-agent-observability). -## The 8 best AI agent platforms for enterprise teams +## What are the key facts about each enterprise AI agent platform? -### Sim +Each enterprise AI agent platform has a different license, deployment model, and billing unit that procurement teams should establish before comparing total cost. -**Best for:** Sim is best for regulated or security-conscious enterprises that need Apache 2.0 self-hosting and a governed Enterprise tier for organization-wide agent deployment. +- Sim uses the [Apache License 2.0](https://github.com/simstudioai/sim), [supports self-hosting](https://docs.sim.ai/platform/self-hosting), and offers hosted plans whose current plan and usage terms appear on the [official Sim pricing page](https://www.sim.ai/pricing). +- n8n uses the [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license/), supports [cloud and self-hosted editions](https://docs.n8n.io/deploy/host-n8n/community-edition-features/), and prices plans primarily by monthly workflow executions according to the [official n8n pricing page](https://n8n.io/pricing/). As of September 2026, the license is source-available and not OSI-approved. +- Microsoft Copilot Studio is proprietary Microsoft software delivered as a managed cloud service. Current consumption is measured through Copilot Credits obtained through pay-as-you-go meters, prepurchase plans, or prepaid packs according to [Microsoft’s Copilot Studio licensing guidance](https://www.microsoft.com/licensing/guidance/Microsoft-Copilot-Studio); current plan pricing appears on the [official pricing page](https://www.microsoft.com/en-us/copilot/pricing/copilot-studio). +- Google Vertex AI Agent Builder is a proprietary managed Google Cloud offering. Charges can include agent runtime and related model or cloud-service usage, so buyers should use the [official agent platform pricing documentation](https://cloud.google.com/products/gemini-enterprise-agent-platform/pricing) for the services in their architecture. +- Amazon Bedrock Agents is a proprietary managed AWS capability. Costs derive from selected foundation models and related Bedrock or AWS services according to [Amazon Bedrock pricing](https://aws.amazon.com/bedrock/pricing/). +- Salesforce Agentforce is proprietary Salesforce software delivered through Salesforce cloud services. The [official Agentforce pricing page](https://www.salesforce.com/agentforce/pricing/) documents consumption through Flex Credits or Conversations and per-user licensing options; Flex Credits are sold in 100,000-credit units and used per action as of September 2026. +- IBM watsonx Orchestrate is proprietary IBM software with hybrid deployment options. Buyers should confirm their supported topology and commercial metric through [IBM watsonx Orchestrate pricing](https://www.ibm.com/products/watsonx-orchestrate/pricing) and the [on-premises installation documentation](https://www.ibm.com/docs/en/watsonx/watson-orchestrate/base?topic=notes-installing-watsonx-orchestrate-premises). -Sim publishes its core under the [Apache 2.0 license](https://github.com/simstudioai/sim), which permits commercial use and modification without fair-code restrictions. The repository provides customer-operated [Docker Compose and Kubernetes deployment paths](https://github.com/simstudioai/sim#self-hosting), giving security teams direct control over infrastructure and data handling. +Teams comparing the licensing implications of Sim and n8n can read [Apache 2.0 versus fair-code licensing](https://www.sim.ai/library/apache-2-0-vs-fair-code). A broader shortlist of deployable options is available in the guide to [open-source AI agent platforms](https://www.sim.ai/library/open-source-ai-agent-platforms). -Sim's [Enterprise plan](https://www.sim.ai/pricing) adds SSO, access control, permission groups, SOC 2 compliance, audit logs, governed self-hosting, and dedicated support. These controls apply across an agent-native workspace that includes workflows, company knowledge, credentials, deployments, and execution history. Free self-hosting does not include those Enterprise controls, so companies that require governed production deployment need a commercial agreement. +## How should enterprise teams evaluate AI agent platforms? -Sim differs from automation-first platforms in how it applies governance. Enterprise controls govern the same workspace where users build and operate agents, rather than covering an automation product that treats AI as another workflow step. Sim's [comparison hub](https://www.sim.ai/comparison) explains how that workspace model compares with automation tools and other agent builders. +Enterprise teams should evaluate AI agent platforms with a weighted procurement scorecard and a production-like pilot rather than selecting the platform with the longest feature list. -**Pros** +### What governance controls should an enterprise AI agent platform provide? -- Apache 2.0 provides a clean path for unrestricted commercial self-hosting. -- The Enterprise plan combines SSO, access control, audit logs, SOC 2 compliance, governed self-hosting, and dedicated support. -- Block-level execution logs expose inputs, outputs, errors, token usage, duration, and cost. -- Hosted, BYOK, and local model options reduce dependence on one model provider. +An enterprise AI agent platform should let the enterprise define who may create, publish, run, inspect, and change agents across separate environments. -**Cons** +Evaluate role-based access, identity-provider integration, environment separation, secret management, tool permissions, data policies, publication controls, and the ability to disable or roll back an agent. Ask whether administrators can enforce controls centrally or whether every agent author must implement them manually. -- SSO, access control, SOC 2 compliance, governed self-hosting, and dedicated support require the Enterprise plan, but the Apache 2.0 core remains free and self-hostable for teams that do not yet need governed production. -- Sim's connector catalog remains smaller than those of long-established integration platforms, but MCP server support, custom tools, and a generic API block let teams reach systems the catalog does not cover directly. -- Credit-based usage adds variable cost alongside per-user fees, but block-level logs make spend attributable, while BYOK or local models can separate model spend from platform credits. +### What deployment options should an enterprise AI agent platform provide? -**Pricing** +An enterprise AI agent platform should offer a deployment model that matches the organization’s data, networking, operational, and regulatory boundaries. -- Free costs $0 and includes 1,000 one-time credits. -- Pro costs $25 per user per month. -- Max costs $100 per user per month. -- Enterprise uses custom pricing for governance, support, and deployment requirements. -- Annual billing costs 15 percent less than monthly billing. See the current [Sim pricing plans](https://www.sim.ai/pricing). +A managed service reduces operational work, but self-hosting can provide greater infrastructure control and source-level inspection. Buyers should distinguish genuine self-hosting from a managed service connected to private data because the security and operational responsibilities are different. -### n8n +### What should a security review cover for an AI agent platform? -**Best for:** n8n is best for technical teams that want execution-based pricing, a mature self-hosted developer community, and substantial code-level flexibility. +An AI agent platform security review should cover data flow, identity, secrets, network paths, model-provider exposure, retention, subprocessors, logging, and the permissions granted to every tool. -n8n uses a [fair-code Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) rather than Apache 2.0. You can inspect and self-host the source, but the license restricts some commercial uses that an unrestricted open-source license would allow. Enterprise buyers should review those terms before standardizing on n8n. +Security teams should request current vendor evidence directly rather than relying on a comparison article for certifications. A platform-level certification also does not prove that an individual agent has safe prompts, least-privilege tools, protected credentials, or appropriate approval gates. -n8n combines [visual workflow automation, code customization, and AI agent tooling](https://docs.n8n.io/advanced-ai/). Its [execution-based pricing](https://n8n.io/pricing/) counts complete workflow runs rather than every step. [Customer-operated deployment](https://docs.n8n.io/hosting/) gives you control over infrastructure and data location, but your engineers must handle upgrades, availability, monitoring, and security. +### How should an enterprise audit AI agent activity? -[Enterprise features](https://n8n.io/enterprise/) include controls such as SSO, role-based permissions, environments, external secrets, and log streaming. Availability varies by plan and deployment model, so buyers should confirm audit, retention, and compliance requirements during procurement. +An enterprise should audit AI agent activity with records that connect each request to model calls, tool calls, retrieved data, approvals, errors, outputs, and the workflow version that ran. -**Pros** +Prompt and response logs alone are insufficient. Investigators need to determine what the agent knew, which tools it could access, what it attempted, what actually changed, who approved the action, and whether sensitive data crossed a system boundary. -- [Customer-operated self-hosting](https://docs.n8n.io/hosting/) supports organizations with strict data-location requirements. -- [Execution-based billing](https://n8n.io/pricing/) can suit workflows with many steps. -- The [n8n community](https://community.n8n.io/) provides integrations, templates, and technical guidance. -- [Code nodes and custom nodes](https://docs.n8n.io/integrations/creating-nodes/overview/) give engineers substantial flexibility. +### When should an AI agent require human approval? -**Cons** +An AI agent should require human approval before high-impact, irreversible, externally visible, financially material, or privilege-changing actions. -- The [fair-code license](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) carries more commercial restrictions than Sim's Apache 2.0 license. -- [Self-hosting](https://docs.n8n.io/hosting/) requires ongoing engineering and operational ownership. -- Some [governance features require enterprise licensing](https://n8n.io/enterprise/). -- n8n remains automation-first, although it [supports AI agents](https://docs.n8n.io/advanced-ai/intro-tutorial/). +Common approval points include sending contractual communications, issuing refunds, modifying production systems, changing customer records, executing purchases, deleting data, and escalating account permissions. The platform should preserve the proposed action, reviewer identity, decision, timestamp, and final result. -**Pricing** +### Why does model support matter when choosing an AI agent platform? -- The [self-hosted Community Edition](https://docs.n8n.io/hosting/community-edition-features/) is available under n8n's fair-code terms. -- [Paid cloud plans](https://n8n.io/pricing/) use execution allowances. -- [Enterprise cloud and self-hosted deployments](https://n8n.io/enterprise/) use custom pricing. -- Buyers should compare expected execution volume and infrastructure costs rather than license fees alone. +Model support matters because model quality, latency, regional availability, contractual terms, and cost vary by task and can change faster than the surrounding workflow. -### Zapier +A multi-model platform reduces dependency on one provider, while a cloud-native platform can offer tighter integration with its preferred model family. Enterprises should test whether model choice is available globally, per workspace, per agent, or per workflow step. -**Best for:** Zapier is best for enterprises that prioritize connector breadth and mature cloud administration over open-source flexibility or customer-operated hosting. +### How should enterprises compare AI agent platform integrations? -Zapier offers a [large application catalog](https://zapier.com/apps), which reduces the need to build custom integrations. Its [Enterprise offering](https://zapier.com/enterprise) provides centralized administration, while [Zapier Agents](https://zapier.com/agents) adds agent capabilities within that ecosystem. +Enterprises should compare integrations by authentication quality, supported operations, observability, permission scope, and maintenance—not by connector count alone. -Zapier is a [proprietary cloud service](https://zapier.com/enterprise). It does not publish a customer-operated self-hosting path. Regulated buyers must determine whether Zapier's hosting model, [security program](https://zapier.com/security-compliance), and contractual controls satisfy internal data policies. +A shallow connector that exposes only common actions may not support a critical process. During a pilot, test pagination, rate limits, retries, webhook verification, credential rotation, custom API calls, and behavior when the connected system is unavailable. -**Pros** +## When should enterprise teams choose Sim? -- The [application catalog](https://zapier.com/apps) supports broad deployment across business systems. -- [Enterprise administration](https://zapier.com/enterprise) covers centralized identity and access management. -- Its [managed cloud service](https://zapier.com/enterprise) removes platform infrastructure maintenance. +Enterprise teams should choose Sim when they need a [visual, multi-model agent workflow platform](https://docs.sim.ai/agents) with inspectable [Apache 2.0 source code and the option to self-host](https://github.com/simstudioai/sim). -**Cons** +Sim is especially suitable when business and engineering teams need to collaborate on explicit workflow logic rather than hide the entire process inside a prompt. Its strongest procurement advantages are portability, source transparency, deployment control, and the ability to place deterministic workflow steps around probabilistic model calls. -- Zapier documents a [managed cloud platform](https://zapier.com/enterprise), not customer-operated self-hosting. -- Its proprietary model limits deployment control and source-code inspection. -- [Task-based plan limits](https://zapier.com/pricing) can require careful forecasting for high-volume automation. -- Zapier's automation heritage may suit deterministic workflows better than complex, agent-native development. +Sim is not automatically the best choice for an organization committed to a single vendor ecosystem. A Microsoft-only organization may prefer Copilot Studio, an AWS platform team may prefer Bedrock Agents, and a Salesforce service organization may prefer Agentforce because existing identity, data, and administration can outweigh platform portability. -**Pricing** +## When should enterprise teams choose n8n? -- Zapier's [pricing page](https://zapier.com/pricing) lists Free, Professional, Team, and Enterprise options with usage limits. -- [Enterprise pricing](https://zapier.com/enterprise) requires engagement with sales for advanced administration. -- Buyers should model task consumption and confirm which security, audit, retention, and compliance controls apply to the quoted plan. +Enterprise teams should choose n8n when technical automation breadth and [self-hosted workflow execution](https://docs.n8n.io/deploy/host-n8n/community-edition-features/) matter more than using an OSI-approved open-source license. -### Make +n8n combines application automation with [AI-oriented nodes and code-level tools](https://docs.n8n.io/build/integrate-ai/understand-ai-components/how-tools-work). Its self-hosting option is useful for teams prepared to operate the platform, but buyers must review the [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) rather than describe n8n as conventional open-source software. -**Best for:** Make is best for teams standardized on visual scenario automation that want to add AI capabilities incrementally. +Sim has the clearer licensing advantage for teams that require OSI-approved open source: Sim is Apache 2.0, while n8n is source-available under its Sustainable Use License as of September 2026. -Make organizes automation as [visual scenarios built from connected modules](https://www.make.com/en/how-to-guides/what-is-make). Its [usage model](https://www.make.com/en/pricing) charges credits as modules perform actions, so costs depend on scenario frequency and complexity. Existing Make users can add [AI agents and AI modules](https://www.make.com/en/ai-agents) without replacing familiar automation patterns. +## When should enterprise teams choose Microsoft Copilot Studio? -**Pros** +Enterprise teams should choose Microsoft Copilot Studio when Microsoft 365, Dynamics 365, Entra ID, and Power Platform already define the organization’s identity and business-application environment. -- The [visual scenario builder](https://www.make.com/en/how-to-guides/what-is-make) makes branching logic and data movement inspectable. -- A [broad application catalog](https://www.make.com/en/integrations) supports common business applications. -- [Enterprise plans](https://www.make.com/en/enterprise) add administration and access controls for larger deployments. +Copilot Studio benefits from [Microsoft’s security and governance model](https://learn.microsoft.com/en-us/microsoft-copilot-studio/security-and-governance). Buyers should still test whether required actions, logs, model options, environment controls, and [Copilot Credit licensing behavior](https://www.microsoft.com/licensing/guidance/Microsoft-Copilot-Studio) satisfy the exact use case rather than assuming that every Microsoft integration has equal depth. -**Cons** +## When should enterprise teams choose Google Vertex AI Agent Builder? -- [Credit consumption](https://www.make.com/en/pricing) can become harder to predict as scenarios gain steps or run more often. -- Make remains automation-first, with [agent development inside its scenario model](https://www.make.com/en/ai-agents). -- Make does not publish an open-source core for customer-operated platform hosting. Its [on-prem agent](https://help.make.com/on-premise-agent) connects cloud scenarios to local systems rather than self-hosting the Make platform. +Enterprise teams should choose Google Vertex AI Agent Builder when they are building custom Gemini-centered agents on Google Cloud and have engineers available to assemble the surrounding application and controls. -**Pricing** +Vertex AI Agent Builder is a [suite for building, scaling, and governing agents in production](https://docs.cloud.google.com/agent-builder). It is less of a turnkey cross-functional workflow builder than a cloud platform for engineering custom agent systems. -- Make's [pricing page](https://www.make.com/en/pricing) lists a free plan and paid tiers with different credit allowances and features. -- [Enterprise](https://www.make.com/en/enterprise) uses custom pricing. -- Buyers should model credits against expected module operations and confirm which governance controls require Enterprise. +## When should enterprise teams choose Amazon Bedrock Agents? -### Gumloop +Enterprise teams should choose Amazon Bedrock Agents when their data, applications, identity controls, and engineering operations already run primarily on AWS. -**Best for:** Gumloop is best for enterprises that want a fully managed rollout with hosted MCP connections and packaged go-to-market templates. +Bedrock Agents can combine [action groups, knowledge bases, and orchestration traces](https://docs.aws.amazon.com/bedrock/latest/userguide/trace-events.html). Procurement teams should model the complete cost of model inference, retrieval, storage, networking, observability, and supporting services using [Bedrock’s service-specific pricing](https://aws.amazon.com/bedrock/pricing/) rather than looking for a single agent-builder seat price. -Gumloop's [Enterprise offering](https://www.gumloop.com/enterprise) provides managed deployment, role-based access control, SAML or SCIM provisioning, audit controls, and retention options. Its [MCP support](https://docs.gumloop.com/mcp) lets agents access approved external tools without requiring users to implement each connection as a workflow node. +## When should enterprise teams choose Salesforce Agentforce? -[Templates](https://www.gumloop.com/templates) help sales and operations groups deploy common automations faster. Gumloop suits organizations that prefer vendor-managed infrastructure over maintaining self-hosted AI agents. +Enterprise teams should choose Salesforce Agentforce when the agent’s primary job is to act on Salesforce customer, sales, service, commerce, or employee data. -**Pros** +Agentforce’s principal advantage is proximity to Salesforce records, permissions, workflows, and business context. Enterprises should validate data grounding, action permissions, handoff behavior, [Flex Credit consumption](https://www.salesforce.com/agentforce/pricing/), and non-Salesforce integration requirements with a representative process. -- [Managed enterprise deployment](https://www.gumloop.com/enterprise) reduces infrastructure work for engineering teams. -- [Enterprise identity controls](https://www.gumloop.com/enterprise) support centralized provisioning and access management. -- [MCP connections](https://docs.gumloop.com/mcp) simplify access to external tools. -- [Packaged templates](https://www.gumloop.com/templates) shorten setup for common workflows. +## When should enterprise teams choose IBM watsonx Orchestrate? -**Cons** +Enterprise teams should choose IBM watsonx Orchestrate when IBM is already a strategic supplier and the organization wants enterprise orchestration aligned with IBM software, governance, or implementation services. -- Gumloop's [commercial plans](https://www.gumloop.com/pricing) use a proprietary hosted product. -- [Managed deployment](https://www.gumloop.com/enterprise) is not equivalent to customer-operated self-hosting. -- Security teams must assess Gumloop's [hosting and retention controls](https://www.gumloop.com/enterprise) rather than operate the full environment. +IBM documents [cloud, multicloud, and on-premises deployment](https://www.ibm.com/products/watsonx-orchestrate/features) and [human-in-the-loop approvals](https://www.ibm.com/products/watsonx-orchestrate/developers). Buyers should make the contracted deployment model, included capabilities, model choices, integration scope, and consumption metric explicit because these details can vary across offerings and agreements. -**Pricing** +## Which enterprise AI agent platform is easiest to approve in a security review? -- Gumloop provides [Enterprise pricing](https://www.gumloop.com/pricing) through sales. -- Buyers should confirm which governance controls, retention options, usage allowances, and deployment terms the quote includes. +The enterprise AI agent platform that is easiest to approve is the platform that fits the organization’s existing trust boundary and provides complete evidence for the proposed deployment. -### Workato +Sim can simplify source inspection and self-hosting reviews. Microsoft Copilot Studio, Google Vertex AI Agent Builder, Amazon Bedrock Agents, and Salesforce Agentforce can simplify reviews when the corresponding cloud is already approved. n8n can fit a self-managed boundary, but its license and operational responsibilities require separate review. -**Best for:** Workato is best for enterprises that need mature iPaaS governance and a large connector catalog for complex system integration. +No platform is automatically secure because of its vendor or deployment model. The agent’s tools, credentials, prompts, retrieved data, model endpoints, approval gates, and logs determine the risk of the deployed system. -Workato brings established [enterprise integration controls](https://www.workato.com/platform) and [more than 1,000 connectors](https://www.workato.com/integrations). Its proprietary platform suits companies that need governed connections across business systems and already treat integration as a central IT function. +## How should an enterprise run an AI agent platform pilot? -Workato approaches [AI agents through its broader orchestration platform](https://www.workato.com/agentic). That model helps agents interact with applications under centralized controls, but adds complexity for buyers seeking an agent-native workspace. +An enterprise should run an AI agent platform pilot with one valuable workflow, realistic integrations, measurable acceptance criteria, and deliberate failure tests. -**Pros** +Use the same evaluation case for every shortlisted platform: -- The [connector catalog](https://www.workato.com/integrations) supports environments with legacy and cloud applications. -- [Enterprise governance](https://www.workato.com/platform) suits centralized IT ownership. -- [Enterprise services](https://www.workato.com/editions/support) support large deployments. +1. Connect a real but appropriately isolated data source. +2. Require the agent to retrieve information, make a bounded decision, and propose an action. +3. Insert human approval before the consequential action. +4. Test unauthorized access, prompt injection, missing data, tool failure, timeouts, duplicate requests, and model refusal. +5. Confirm that reviewers can reconstruct the complete execution from logs. +6. Measure task success, false actions, approval rate, latency, operating cost, authoring time, and recovery effort. +7. Ask security, legal, procurement, operations, and workflow owners to score the same evidence. -**Cons** +A polished demonstration should not outweigh weak access controls or incomplete audit records. -- Workato can require more implementation and platform management than simpler agent builders. -- Its [integration-first architecture](https://www.workato.com/platform) can feel indirect for creating and governing agents. -- Workato's [commercial platform](https://www.workato.com/pricing) does not publish an open-source core for customer-operated deployment. +## What questions should procurement ask AI agent platform vendors? -**Pricing** +Procurement teams should ask every AI agent platform vendor the same specific questions about control, evidence, deployment, licensing, and cost. -- Workato uses [custom pricing](https://www.workato.com/pricing) based on selected products and usage. -- Buyers must contact sales for a quote. +- Who owns agent definitions, prompts, execution data, and generated outputs? +- Can the platform and all required components run in the enterprise’s chosen environment? +- Which data is sent to model providers, and can providers use it for training? +- Can model providers and models be selected per agent or workflow step? +- How are secrets stored, scoped, rotated, and redacted from logs? +- Can administrators restrict tools, domains, models, and data sources centrally? +- Do logs record model calls, retrievals, tool inputs, tool outputs, approvals, and workflow versions? +- Can the enterprise export audit records to its security monitoring system? +- What happens to in-flight executions when a workflow changes? +- How are retries and duplicate side effects prevented? +- Can a human inspect, modify, reject, or approve a proposed action? +- What is the billing unit, and which supporting services create additional charges? +- Which capabilities require an enterprise plan or separate contract? +- What are the retention, deletion, regional hosting, and subprocessor terms? +- What license governs self-hosted code, and what uses does that license restrict? -### Dust +## How should an enterprise make the final platform decision? -**Best for:** Dust is best for enterprises that need secure, collaborative agents grounded in company knowledge. +An enterprise should select the AI agent platform that passes mandatory security and deployment gates and then earns the highest weighted pilot score for the target workflows. -Dust organizes [agents around shared company context](https://docs.dust.tt/docs/user-documentation/getting-started/intro-to-dust). Employees can use assistants that draw on [connected data sources](https://docs.dust.tt/docs/data-sources), making Dust a stronger fit for internal research, support, and knowledge retrieval than broad workflow automation. +A practical weighting is: -**Pros** +| Criterion | Suggested weight | +|---|---:| +| Governance and identity | 20% | +| Security architecture and evidence | 20% | +| Auditability and human approval | 15% | +| Deployment and data control | 15% | +| Integration depth | 10% | +| Model flexibility and quality | 10% | +| Reliability and operations | 5% | +| Total cost and contract fit | 5% | -- Dust supports [collaborative agent creation and company-wide access](https://docs.dust.tt/docs/user-documentation/agents/create-your-first-agent). -- [Data-source connections](https://docs.dust.tt/docs/data-sources) help agents answer questions using internal information. -- [Enterprise controls](https://dust.tt/home/enterprise) support secure multi-user deployment. +The weights should change when an organization has non-negotiable requirements. For example, self-hosting, a specific cloud, an OSI-approved license, or Salesforce-native data access may be a pass-or-fail gate rather than a scored preference. -**Cons** +## Related comparisons -- Dust's [knowledge and assistant model](https://docs.dust.tt/docs/user-documentation/getting-started/intro-to-dust) covers fewer general automation use cases than application-workflow platforms. -- Companies seeking customer-operated hosting should confirm [deployment options](https://dust.tt/home/enterprise) during procurement. -- Its knowledge-first model may not suit complex system orchestration. +Sim’s related pages separate enterprise procurement intent from broader builder, licensing, and deployment searches. -**Pricing** - -- Dust lists [self-service and Enterprise options](https://dust.tt/home/pricing). -- Buyers should confirm which tier includes SSO, access controls, audit logs, retention settings, and compliance commitments. - -### Relevance AI - -**Best for:** Relevance AI is best for teams that want to deploy packaged sales, customer success, and operations agents quickly. - -Relevance AI packages agents as an [AI workforce](https://relevanceai.com/), making common go-to-market use cases easier to deploy at team level. [Higher tiers](https://relevanceai.com/pricing) add enterprise controls such as SSO, role-based access control, and audit logs. - -**Pros** - -- [Agent templates](https://relevanceai.com/agent-templates) reduce work required to launch common workflows. -- [Higher tiers](https://relevanceai.com/pricing) provide identity, access, and auditing controls. -- The [hosted platform](https://relevanceai.com/pricing) limits infrastructure work for internal IT. - -**Cons** - -- Its proprietary terms do not provide an open-source core for customer-operated modification and redistribution. -- The [packaged-agent catalog](https://relevanceai.com/agent-templates) emphasizes departmental use cases. -- Organization-wide adoption may require complementary general automation and governance capabilities. - -**Pricing** - -- Relevance AI offers [tiered plans](https://relevanceai.com/pricing), with enterprise governance on higher tiers. -- Buyers should confirm current usage limits, retention terms, support coverage, and enterprise pricing directly with the vendor. - -## Enterprise governance comparison - -The comparison separates documented controls from features that require vendor confirmation during procurement. - -| Platform | License type | Self-hosting model | SSO/access control | Audit logging | SOC 2/compliance | Pricing tier | -| --- | --- | --- | --- | --- | --- | --- | -| Sim | ✅ [Apache 2.0 core](https://github.com/simstudioai/sim) | ✅ Free customer-operated core; governed hosting requires Enterprise | ✅ [Enterprise only](https://www.sim.ai/pricing) | ✅ [Enterprise only](https://www.sim.ai/pricing) | ✅ [SOC 2 on Enterprise](https://www.sim.ai/pricing) | ✅ [Free, Pro, Max, custom Enterprise](https://www.sim.ai/pricing) | -| n8n | 🟡 [Fair-code](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) | ✅ [Customer-operated option](https://docs.n8n.io/hosting/) | 🟡 [Enterprise controls](https://n8n.io/enterprise/) | 🟡 [Enterprise controls](https://n8n.io/enterprise/) | 🟡 Verify current scope | 🟡 [Verify live tier](https://n8n.io/pricing/) | -| Zapier | ❌ [Proprietary](https://zapier.com/terms) | ❌ [Hosted cloud](https://zapier.com/enterprise) | ✅ [Enterprise administration](https://zapier.com/enterprise) | 🟡 Verify current scope | 🟡 [Verify current scope](https://zapier.com/security-compliance) | 🟡 [Verify live tier](https://zapier.com/pricing) | -| Make | ❌ [Proprietary](https://www.make.com/en/terms-and-conditions) | ❌ [Cloud platform with on-prem connectivity](https://help.make.com/on-premise-agent) | 🟡 [Enterprise controls](https://www.make.com/en/enterprise) | 🟡 Verify current scope | 🟡 Verify current scope | 🟡 [Verify live tier](https://www.make.com/en/pricing) | -| Gumloop | ❌ [Proprietary](https://www.gumloop.com/tos) | 🟡 [Managed deployment](https://www.gumloop.com/enterprise) | ✅ [SAML, SCIM, and RBAC](https://www.gumloop.com/enterprise) | ✅ [Enterprise audit controls](https://www.gumloop.com/enterprise) | 🟡 Verify certification scope | 🟡 [Enterprise tier](https://www.gumloop.com/pricing) | -| Workato | ❌ [Proprietary](https://www.workato.com/legal/terms-of-service) | 🟡 [Vendor platform](https://www.workato.com/platform) | ✅ [Enterprise access controls](https://www.workato.com/platform) | 🟡 Contract-dependent | 🟡 Verify certification scope | 🟡 [Custom enterprise](https://www.workato.com/pricing) | -| Dust | ✅ [MIT-licensed source](https://github.com/dust-tt/dust/blob/main/LICENSE) | 🟡 [Verify deployment options](https://dust.tt/home/enterprise) | 🟡 [Enterprise controls](https://dust.tt/home/enterprise) | 🟡 Verify current scope | 🟡 Verify certification scope | 🟡 [Verify live tier](https://dust.tt/home/pricing) | -| Relevance AI | ❌ [Proprietary](https://relevanceai.com/terms-and-conditions) | 🟡 [Verify deployment options](https://relevanceai.com/pricing) | ✅ [Higher-tier SSO and RBAC](https://relevanceai.com/pricing) | ✅ [Higher-tier audit controls](https://relevanceai.com/pricing) | 🟡 Verify certification scope | 🟡 [Higher-tier enterprise](https://relevanceai.com/pricing) | - -## Which platform fits your organization - -- **Regulated industry with customer-operated infrastructure.** Choose [Sim Enterprise](https://www.sim.ai/pricing) when you need governed self-hosting, SSO, access control, audit logs, and SOC 2 support. The Apache 2.0 core supports independent self-hosting, but enterprise governance requires Enterprise. -- **Team wanting fully managed simplicity.** Choose Gumloop when you want its [managed deployment and enterprise controls](https://www.gumloop.com/enterprise) without operating the underlying infrastructure. Its proprietary hosted model suits buyers who value low operational overhead more than source access. -- **Organization prioritizing connector breadth and mature cloud administration.** Choose Zapier when its [application catalog and enterprise controls](https://zapier.com/enterprise) take priority. Confirm that its hosting, identity, and retention terms meet your requirements. -- **Enterprise needing deep iPaaS governance.** Choose Workato when agents must operate within a [large integration program under centralized controls](https://www.workato.com/platform). Buyers seeking an agent-native workspace may prefer Sim. - -n8n offers another customer-operated option for engineering-led organizations. Its [self-hosted community](https://community.n8n.io/) and [execution-based pricing](https://n8n.io/pricing/) can outweigh the commercial restrictions of its [fair-code license](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) when your legal team accepts those terms. - -## Why Sim leads on enterprise governance - -Sim leads because its [Apache 2.0 core](https://github.com/simstudioai/sim) gives enterprises a permissive license and broad commercial self-hosting rights. Buyers can inspect, modify, and operate the software without the commercial limits attached to fair-code licenses. - -[Sim Enterprise](https://www.sim.ai/pricing) adds the governance required for organization-wide deployment. One commercial tier covers SSO, access control, audit logs, SOC 2 compliance, governed self-hosting, and dedicated support. The free open-source core remains self-hostable, but it does not include these Enterprise controls. - -Those controls govern an agent-native workspace where users build, deploy, and monitor agents alongside their data, integrations, and execution history. Sim does not depend on an automation product with separate AI features and governance additions. - -[Explore Sim Enterprise and contact sales](https://www.sim.ai) to discuss deployment, security, and governance requirements. - -## How we evaluated these platforms - -We evaluated each platform using its live pricing, trust, documentation, and licensing pages rather than relying on general marketing claims. The review checked six procurement axes: license terms, self-hosting models, SSO and access control, audit logging and retention, compliance posture, and multi-workspace governance. - -We also recorded each vendor's public pricing structure without treating different usage units as directly comparable. Research was verified through August 2026. Enterprise features can change by contract or plan, so buyers should confirm security controls, deployment rights, and compliance scope with each vendor before procurement. +- For the head-term comparison, read [Best AI Agent Builder in 2026](https://www.sim.ai/library/best-ai-agent-builder-2026). +- For licensing due diligence, read [Apache 2.0 vs Fair-Code](https://www.sim.ai/library/apache-2-0-vs-fair-code). +- For deployment-oriented alternatives, read [Open-Source AI Agent Platforms](https://www.sim.ai/library/open-source-ai-agent-platforms). +- For enterprise product and deployment information rather than an editorial roundup, visit the [Sim enterprise page](https://www.sim.ai/enterprise).