feat(comparison): add Microsoft Copilot Studio, OpenClaw, Dust, CrewAI, and LangChain (#5384)

* feat(comparison): add Microsoft Copilot Studio, OpenClaw, Dust, CrewAI, and LangChain

- 5 new "Sim vs Competitor" profiles (now 20 total), each with ~58
  independently sourced facts, standout features, and limitations,
  researched against each vendor's own docs/pricing/GitHub
- New brand icons: MicrosoftCopilotIcon, OpenClawIcon, DustIcon,
  LangChainIcon, CrewAIIcon
- isWorkflowBuilder: false for OpenClaw, CrewAI, and LangChain since
  they're a personal agent runtime and code-first frameworks rather
  than visual workflow builders, so their FAQ asks a
  category-clarifying question instead of a peer feature-gap one
- Independent tone audit (no over-praising competitors, no unflattering
  Sim framing) and a fresh accuracy re-verification pass (50 highest-
  stakes facts across all 5 profiles, all confirmed against live
  sources) both came back clean

* fix(comparison): fix two more FAQ text-mangling bugs found during final audit

- lowercaseFirst only guarded against 2+ CONSECUTIVE leading capitals
  (acronyms like "AI"/"SSO"), so CamelCase brand names with a single
  leading capital (LangChain, OpenClaw, CrewAI) got their first letter
  wrongly lowercased ("langChain provides..."). Now checks for 2+
  uppercase letters anywhere in the leading word, which covers both
  acronyms and CamelCase brand names.
- parseFactValue and summarizeFact's boolean-prefix stripping only
  recognized "Yes:"/"No:" (colon), but "Yes, ..."/"No, ..." (comma) is
  an equally common phrasing already used across ~15 existing facts
  (stackai, pipedream, workato, zapier, etc.), so those facts kept
  their leading comma when stitched into an FAQ answer (e.g. "StackAI:
  , broad support..."). Both now accept either separator.

Found by systematically sweeping every "Sim vs X" FAQ answer across
all 20 competitor pages for garbled/mis-cased text, not just the 5
newly added ones.

* feat(comparison): add sub-workflow composition and loop-block facts

- Two new universal comparison facts across all 20 profiles:
  subWorkflows (calling a saved workflow as a reusable step inside
  another) and loopIteration (a dedicated sequential for-each/while
  loop container, distinct from concurrent Parallel execution)
- Both are real Sim capabilities (Workflow block, Loop block) verified
  directly against the codebase and docs.sim.ai
- Findings are genuinely mixed, not uniformly favorable: n8n, Zapier,
  Make, Workato, Retool, Power Automate, Gumloop, Vellum, Stack AI,
  Tines, Langflow, Flowise, Microsoft Copilot Studio, and LangChain all
  have some form of sub-workflow calling; Zapier and Gumloop's loop
  primitives run concurrently rather than sequentially (marked
  "Partial", not "No"); Pipedream, OpenAI AgentKit, Claude Cowork,
  CrewAI, Dust, and OpenClaw genuinely lack one or both

* feat(comparison): add third-party integration vetting fact

New universal comparison fact across all 20 profiles: thirdPartyVetting,
whether a platform's integrations/tools/skills come from a vetted
first-party catalog vs. an open marketplace where any third party can
publish executable code with lighter or no vendor security review.

Directly relevant given OpenClaw's ClawHub marketplace has documented
incidents (283 skills, ~7.1% of the registry, found leaking credentials;
24 accounts distributing 600+ malicious skills before scanning existed).

Findings are honest and mixed, not uniformly favorable: Gumloop, Retool,
and Tines are first-party-only like Sim (marked "Yes"); n8n, Zapier,
Make, Workato, and OpenAI AgentKit have partial vetting on an open or
semi-open ecosystem; Pipedream and OpenClaw are open marketplaces with
documented security incidents.

* fix(comparison): correct n8n supply-chain attack download count

Independently re-verified the cited Hacker News article: the primary
malicious package had 4,241 downloads listed (not "3,400 weekly" as
previously written, a number not actually supported by the source).

* fix(comparison): fix duplicated competitor name in first FAQ answer

Every competitor's oneLiner is already a complete "{Name} is ..."
sentence, so prepending "${name} is " before it was always redundant.
Before this session's lowercaseFirst fix, the duplication rendered in
mixed case ("Zapier is zapier is a cloud-based...") and was easy to
miss; the CamelCase-name fix made it fully literal and obvious
("CrewAI is CrewAI is..."), which is what Cursor Bugbot caught.

Fixed by using the oneLiner directly (via ensurePeriod) instead of
re-prepending the name. Verified fixed across all 20 pages via live
curl, not just the CrewAI case Cursor flagged.

* improvement(comparison): cite Sim's own docs alongside code for 4 facts

Added docs.sim.ai citations (Roles and Permissions, BYOK, Debugging
retrieval, Function block) as primary sources for rbac, byok,
kbChunkVisibility, and customCodeSteps, which previously cited only
GitHub source code with no user-facing documentation reference.
Verified all 4 doc URLs resolve (200).
This commit is contained in:
Waleed
2026-07-03 11:29:13 -07:00
committed by GitHub
parent de110e02eb
commit 0cc290eeb7
27 changed files with 6837 additions and 12 deletions
@@ -67,6 +67,7 @@ export const COMPARISON_SECTIONS: ComparisonSectionDef[] = [
{ key: 'versionControlDepth', label: 'Version control' },
{ key: 'realtimeCollaboration', label: 'Realtime collaboration' },
{ key: 'nativeFileStorage', label: 'Native file storage' },
{ key: 'subWorkflows', label: 'Sub-workflows (composition)' },
],
}),
defineSection({
@@ -91,6 +92,7 @@ export const COMPARISON_SECTIONS: ComparisonSectionDef[] = [
{ key: 'modelAndToolGovernance', label: 'Model & tool governance' },
{ key: 'credentialGovernance', label: 'Credential governance' },
{ key: 'sso', label: 'Single sign-on (SSO)' },
{ key: 'thirdPartyVetting', label: 'Vetted first-party integrations' },
{ key: 'piiRedaction', label: 'PII redaction' },
{ key: 'dataRetention', label: 'Custom data retention' },
{ key: 'whiteLabeling', label: 'White-labeling' },
@@ -114,6 +116,7 @@ export const COMPARISON_SECTIONS: ComparisonSectionDef[] = [
{ key: 'nativeChatDeployment', label: 'Native chat deployment' },
{ key: 'parallelExecution', label: 'Parallel execution' },
{ key: 'a2aProtocol', label: 'Agent2Agent (A2A) protocol' },
{ key: 'loopIteration', label: 'Loop / iteration block' },
],
}),
defineSection({
@@ -10,15 +10,17 @@ export interface ParsedFact {
// The negative lookahead (?![a-zA-Z]) requires the "Yes"/"No" token to end at a word
// boundary, so values like "Not documented" or "Not publicly documented" (which start
// with the letters "No" but aren't the boolean token) fall through to 'neutral' instead
// of being misread as a "No" status.
const STATUS_PREFIX = /^(Yes|No)(?![a-zA-Z])(?::\s*)?(.*)$/s
// of being misread as a "No" status. The separator group accepts either a colon
// ("Yes: ...") or a comma ("Yes, but ...") since both are used throughout the dataset.
const STATUS_PREFIX = /^(Yes|No)(?![a-zA-Z])(?:[:,]\s*)?(.*)$/s
/**
* Splits a {@link Fact.value} string into a status (for a compact icon) and
* the remaining descriptive text. Every fact in `apps/sim/lib/compare/data`
* that represents a yes/no capability is written as `"Yes: ..."` / `"No:
* ..."`. This is the single place that convention is parsed, so the
* comparison table and the key-differences strip render it identically.
* that represents a yes/no capability is written as `"Yes: ..."` / `"No: ..."`,
* or occasionally `"Yes, ..."` / `"No, ..."` as a more natural continuation.
* This is the single place that convention is parsed, so the comparison table
* and the key-differences strip render it identically.
*/
export function parseFactValue(value: string): ParsedFact {
const match = value.match(STATUS_PREFIX)
+25 -7
View File
@@ -1,12 +1,17 @@
import {
type CompetitorProfile,
claudeCoworkProfile,
crewaiProfile,
dustProfile,
flowiseProfile,
gumloopProfile,
langchainProfile,
langflowProfile,
makeProfile,
microsoftCopilotProfile,
n8nProfile,
openaiAgentkitProfile,
openClawProfile,
pipedreamProfile,
powerAutomateProfile,
retoolProfile,
@@ -40,6 +45,11 @@ export const ALL_COMPETITORS: CompetitorProfile[] = [
claudeCoworkProfile,
langflowProfile,
flowiseProfile,
microsoftCopilotProfile,
openClawProfile,
dustProfile,
crewaiProfile,
langchainProfile,
]
const COMPETITOR_BY_SLUG = new Map(ALL_COMPETITORS.map((c) => [c.id, c]))
@@ -108,7 +118,7 @@ export function buildComparisonFaqs(competitor: CompetitorProfile): ComparisonFa
const faqs: ComparisonFaq[] = [
{
question: `Is Sim a good alternative to ${name}?`,
answer: `Sim is an open-source AI workspace where teams build, deploy, and manage AI agents visually, conversationally, or with code. ${name} is ${lowercaseFirst(competitor.oneLiner)} Teams considering a switch typically weigh licensing (Sim is Apache 2.0 and self-hostable), pricing model, and how AI-native the platform's agent-building experience is.`,
answer: `Sim is an open-source AI workspace where teams build, deploy, and manage AI agents visually, conversationally, or with code. ${ensurePeriod(competitor.oneLiner)} Teams considering a switch typically weigh licensing (Sim is Apache 2.0 and self-hostable), pricing model, and how AI-native the platform's agent-building experience is.`,
},
{
question: `What is the main difference between Sim and ${name}?`,
@@ -194,21 +204,29 @@ export function ensurePeriod(value: string): string {
return /[.!?]$/.test(value) ? value : `${value}.`
}
/** Lowercases the first letter of `value`, unless it starts with an acronym (e.g. "AI", "SSO", "MCP"). */
/**
* Lowercases the first letter of `value`, unless its leading word is an acronym
* (e.g. "AI", "SSO", "MCP") or a CamelCase brand name (e.g. "LangChain",
* "OpenClaw", "CrewAI") - detected by 2+ uppercase letters anywhere in that
* word, not just consecutive at the start, since lowercasing either would
* mangle a proper noun ("langChain", "openClaw").
*/
export function lowercaseFirst(value: string): string {
if (value.length === 0) return value
// Leave a leading acronym (2+ consecutive capitals, e.g. "AI", "SSO", "MCP") alone.
if (/^[A-Z]{2,}/.test(value)) return value
const leadingWord = value.match(/^[A-Za-z]+/)?.[0] ?? ''
const upperCaseCount = (leadingWord.match(/[A-Z]/g) ?? []).length
if (upperCaseCount >= 2) return value
return value.charAt(0).toLowerCase() + value.slice(1)
}
/**
* Composes {@link firstSentence} + {@link lowercaseFirst} + {@link ensurePeriod} for
* stitching a fact value mid-sentence. Strips a leading "Yes:"/"No:" token first so
* boolean facts don't produce mid-sentence "yes: ..."/"no: ..." fragments.
* stitching a fact value mid-sentence. Strips a leading "Yes:"/"No:" (or the
* comma-separated "Yes,"/"No,") token first so boolean facts don't produce
* mid-sentence "yes: ..."/"no: ..." fragments.
*/
function summarizeFact(value: string): string {
const stripped = value.replace(/^(Yes|No)(?![a-zA-Z])(?::\s*)?/, '').trim()
const stripped = value.replace(/^(Yes|No)(?![a-zA-Z])(?:[:,]\s*)?/, '').trim()
const base = stripped.length > 0 ? stripped : value
return ensurePeriod(lowercaseFirst(firstSentence(base)))
}
File diff suppressed because one or more lines are too long
@@ -309,6 +309,26 @@ export const claudeCoworkProfile: CompetitorProfile = {
},
],
},
subWorkflows: {
value:
"No: Claude Cowork has no visual workflow builder and no feature to call one saved task as a reusable step inside another task. Anthropic's own scheduled-tasks documentation describes each scheduled task as its own independent Cowork session with no documented composition or nesting mechanism.",
detail:
"Cowork's closest analog is model-driven 'sub-agent coordination', where Claude itself decides to break a single task into parallel sub-agent workstreams at run time. That is not a user-authored, reusable sub-workflow the way a workflow platform lets you call a saved flow as a step with explicit parent-waits-for-child data passing.",
shortValue: 'No: no task composition, only same-session sub-agents',
confidence: 'estimated',
sources: [
{
url: 'https://support.claude.com/en/articles/13854387-schedule-recurring-tasks-in-claude-cowork',
label: 'Schedule recurring tasks in Claude Cowork',
asOf: '2026-07-02',
},
{
url: 'https://support.claude.com/en/articles/13345190-get-started-with-claude-cowork',
label: 'Get started with Claude Cowork',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -534,6 +554,26 @@ export const claudeCoworkProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
"No: Claude Cowork has no visual builder and no dedicated for-each/while loop container that iterates a set of steps over a list or fixed count. Anthropic's documentation describes scheduled tasks re-running on a time cadence (hourly/daily/weekly), not a loop node iterating over items within a single run.",
detail:
"The closest documented mechanism is Claude's own model-driven 'parallel workstreams' for breaking one task into concurrent sub-agents, which is the opposite of sequential per-item iteration and is not user-configurable as a loop primitive.",
shortValue: 'No: no loop/for-each container, only time-based re-runs',
confidence: 'estimated',
sources: [
{
url: 'https://support.claude.com/en/articles/13854387-schedule-recurring-tasks-in-claude-cowork',
label: 'Schedule recurring tasks in Claude Cowork',
asOf: '2026-07-02',
},
{
url: 'https://support.claude.com/en/articles/13345190-get-started-with-claude-cowork',
label: 'Get started with Claude Cowork',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -834,6 +874,31 @@ export const claudeCoworkProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
'Partial: Anthropic maintains first-party catalogs (anthropics/skills, anthropics/knowledge-work-plugins, the 11 plugins bundled into Cowork), but the plugin/skill ecosystem is open by design. Any developer can host a plugin marketplace as a git repo and users add it via `/plugin marketplace add`, with no Anthropic approval queue or review gate before installation.',
detail:
'Third-party community sites (ClawHub, skills.sh, and others) distribute unvetted, community-authored skills for Claude Code/Cowork. Security researchers have found real, documented incidents in this ecosystem: Snyk\'s ToxicSkills audit of ~3,984 skills on ClawHub and skills.sh found 1,467 with security flaws and confirmed 76 active malicious payloads built for credential theft, backdoors, and data exfiltration; Koi Security separately audited all 2,857 skills on ClawHub and flagged 341 as malicious, 335 tied to one coordinated campaign ("ClawHavoc"). These incidents are in the broader Claude Skills/plugin ecosystem rather than Anthropic\'s own first-party catalog.',
shortValue: 'Partial: first-party catalog + open, unvetted plugin ecosystem',
confidence: 'verified',
sources: [
{
url: 'https://code.claude.com/docs/en/plugin-marketplaces',
label: 'Create and distribute a plugin marketplace',
asOf: '2026-07-02',
},
{
url: 'https://github.com/anthropics/skills',
label: 'anthropics/skills: Public repository for Agent Skills',
asOf: '2026-07-02',
},
{
url: 'https://snyk.io/blog/toxicskills-malicious-ai-agent-skills-clawhub/',
label: 'Snyk: ToxicSkills - malicious AI agent skills on ClawHub',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -225,6 +225,19 @@ export const flowiseProfile: CompetitorProfile = {
confidence: 'unknown',
sources: [],
},
subWorkflows: {
value:
"Yes: Flowise's Execute Flow node calls another saved Chatflow or Agentflow as a step, passes it input, waits for the child flow to finish, and receives its final output back to continue the parent flow.",
shortValue: 'Yes, via the Execute Flow node',
confidence: 'verified',
sources: [
{
url: 'https://docs.flowiseai.com/using-flowise/agentflowv2',
label: 'Flowise Docs: Agentflow V2 (Execute Flow node)',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -431,6 +444,19 @@ export const flowiseProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
"Yes: Flowise's Agentflow V2 has a dedicated Iteration node that takes an array and executes a nested sub-flow of steps once per item, running sequentially. Its separate Loop node instead jumps backward to re-run an earlier node (a retry cycle, not a collection iterator).",
shortValue: 'Yes, via the Iteration node (separate Loop node is retry-only)',
confidence: 'verified',
sources: [
{
url: 'https://docs.flowiseai.com/using-flowise/agentflowv2',
label: 'Flowise Docs: Agentflow V2 (Iteration and Loop nodes)',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -693,6 +719,33 @@ export const flowiseProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
"Yes: Flowise's nodes (LLMs, tools, vector stores, document loaders) live in the packages/components/nodes folder of the core FlowiseAI/Flowise monorepo. New nodes are contributed via GitHub pull request and reviewed/merged by the Flowise team before shipping in an official release, rather than published independently by third parties into an open, unreviewed marketplace. The separate Marketplace feature distributes JSON chatflow/agentflow templates, not installable executable code packages.",
detail:
'Flowise has still had first-party security issues: CVE-2025-59528 (CVSS 10.0) was a critical unauthenticated remote code execution flaw in the official CustomMCP node, where user-supplied mcpServerConfig input was passed into a JavaScript Function() constructor; patched in 3.0.6, but VulnCheck observed in-the-wild exploitation starting April 2026 against thousands of still-exposed instances. This was a bug in vetted, first-party code, not a malicious third-party community node.',
shortValue:
'Yes, nodes are PR-reviewed into the core repo, no open community-node marketplace',
confidence: 'verified',
sources: [
{
url: 'https://docs.flowiseai.com/contributing/building-node',
label: 'Flowise Docs: Building Node',
asOf: '2026-07-02',
},
{
url: 'https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-3gcm-f6qx-ff7p',
label: 'GitHub Security Advisory GHSA-3gcm-f6qx-ff7p (CVE-2025-59528)',
asOf: '2026-07-02',
},
{
url: 'https://www.csoonline.com/article/4155680/hackers-exploit-a-critical-flowise-flaw-affecting-thousands-of-ai-workflows.html',
label:
'CSO Online: Hackers exploit a critical Flowise flaw affecting thousands of AI workflows',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -326,6 +326,26 @@ export const gumloopProfile: CompetitorProfile = {
confidence: 'unknown',
sources: [],
},
subWorkflows: {
value:
"Yes: a dedicated 'Subflow' feature lets any saved workflow be dropped in as a reusable node inside another workflow, with Input/Output nodes to pass parameters in and return values out",
detail:
"Gumloop docs describe Subflows as workflows that 'show up in your node library just like native nodes' once built, so they can be dragged onto the canvas of any other flow, wired to Input nodes for parameters and Output nodes for return values. When a list is connected to a Subflow node it runs once per list item (Loop Mode) rather than a single time. Public docs do not explicitly state whether the parent execution blocks until the subflow completes, but since a Subflow is embedded as a node in the parent's directed graph (not invoked over a separate async webhook call), later nodes depending on its outputs necessarily wait for it to resolve.",
shortValue: 'Yes: Subflow node calls a saved workflow as a step',
confidence: 'verified',
sources: [
{
url: 'https://docs.gumloop.com/core-concepts/subflows',
label: 'Subflows - Gumloop docs',
asOf: '2026-07-02',
},
{
url: 'https://www.gumloop.com/university/lessons/subflows',
label: 'Gumloop University: Subflows',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -566,6 +586,26 @@ export const gumloopProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
"Partial: Gumloop's only documented iteration primitive is 'Loop Mode', the same mechanism already covered under parallelExecution, which auto-triggers when a list is connected to a node or Subflow and runs that node once per list item. Per Gumloop's own docs this is concurrent (2 items at once on Free, 15 on Pro), not a strictly one-at-a-time sequential container, and there is no separate while-loop or fixed-iteration-count node documented, only iteration over an existing list.",
detail:
"Gumloop docs describe Loop Mode as processing 'multiple items simultaneously' with concurrency capped by plan tier, distinct from a classic for-each node that guarantees one iteration finishes before the next starts. No dedicated while-loop (condition-based) or fixed-count repeat node was found in public docs; all iteration is driven by connecting a list as input.",
shortValue: 'Partial: list-driven Loop Mode is concurrent, not a sequential loop node',
confidence: 'estimated',
sources: [
{
url: 'https://docs.gumloop.com/core-concepts/loop_mode',
label: 'Loop Mode - Gumloop docs',
asOf: '2026-07-02',
},
{
url: 'https://www.gumloop.com/university/lessons/lists-loop-mode',
label: 'Gumloop University: Lists & Loop mode',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -891,6 +931,26 @@ export const gumloopProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
"Yes: Gumloop's 100+ built-in integrations are first-party nodes authored and maintained by Gumloop. Custom Nodes (user-written code steps) are built privately per account or team and shared only with named teammates or an org/link, not published to a public, searchable registry of third-party installable nodes. The separate Community Templates gallery is workflow templates (built from Gumloop's own nodes), and submissions go through a Gumloop content-quality review before listing.",
detail:
"No public marketplace was found where an unaffiliated third-party developer publishes a Custom Node for arbitrary other users to discover and install, unlike an open community-node ecosystem. No documented security incidents involving Gumloop's Custom Nodes or Community Templates were found in public sources as of this check.",
shortValue: 'Yes: first-party nodes, private custom nodes, reviewed templates',
confidence: 'verified',
sources: [
{
url: 'https://docs.gumloop.com/nodes/custom_node_details',
label: 'Custom Node Builder - Gumloop docs',
asOf: '2026-07-02',
},
{
url: 'https://www.gumloop.com/blog/announcing-community-templates',
label: 'Announcing Community Templates - Gumloop blog',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
File diff suppressed because it is too large Load Diff
@@ -251,6 +251,19 @@ export const langflowProfile: CompetitorProfile = {
confidence: 'unknown',
sources: [],
},
subWorkflows: {
value:
"Yes: Langflow's Run Flow component runs another saved flow as a subprocess of the current flow, dynamically generating input and output fields from the target flow's graph so the parent flow passes data in and receives the child flow's outputs back. It can also be attached to an Agent component as a callable tool.",
shortValue: 'Yes, via the Run Flow component',
confidence: 'verified',
sources: [
{
url: 'https://docs.langflow.org/run-flow',
label: 'Langflow Docs: Run Flow component',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -465,6 +478,19 @@ export const langflowProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
'Yes: Langflow ships a dedicated Loop component that takes a list of JSON or Table items (for example CSV rows), passes items one at a time through its Item output port to a chain of connected components, and loops back until every item is processed sequentially, before emitting the aggregated result from its Done port.',
shortValue: 'Yes, via the Loop component (sequential, Item/Done ports)',
confidence: 'verified',
sources: [
{
url: 'https://docs.langflow.org/loop',
label: 'Langflow Docs: Loop component',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -736,6 +762,37 @@ export const langflowProfile: CompetitorProfile = {
confidence: 'unknown',
sources: [],
},
thirdPartyVetting: {
value:
'Partial: most built-in integration bundles are contributed as pull requests to the official langflow-ai/langflow codebase and merged by the core maintainers, but Langflow also ships a community Store where users can share and install flows and components with lighter, informal vetting, plus a custom-component system that lets any user author and run their own Python code with full server access. Langflow has disclosed a real security incident tied to this code-execution model: CVE-2025-3248, an unauthenticated remote code execution flaw in the custom-component code-validation endpoint (fixed in 1.3.0), which was actively exploited in the wild to deploy the Flodrix botnet on unpatched instances.',
detail:
'Langflow documents that it does not enforce isolation between users or restrict local disk/network access, so both bundle and custom-component code run with the same trust level as the core server.',
shortValue:
'Partial: reviewed bundles plus a lighter-vetted community Store and custom code',
confidence: 'verified',
sources: [
{
url: 'https://docs.langflow.org/components-bundle-components',
label: 'Langflow Docs - About bundles',
asOf: '2026-07-02',
},
{
url: 'https://docs.langflow.org/components-custom-components',
label: 'Langflow Docs - Create custom Python components',
asOf: '2026-07-02',
},
{
url: 'https://docs.langflow.org/security',
label: 'Langflow Docs - Security',
asOf: '2026-07-02',
},
{
url: 'https://github.com/langflow-ai/langflow/security/advisories/GHSA-vwmf-pq79-vjvx',
label: 'GitHub Security Advisory GHSA-vwmf-pq79-vjvx (CVE-2025-3248)',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -372,6 +372,26 @@ export const makeProfile: CompetitorProfile = {
},
],
},
subWorkflows: {
value:
"Yes: Make's 'Call a Scenario' subscenario module lets a parent scenario invoke a saved sub-scenario as a step, passing structured inputs and, in synchronous mode, pausing until the sub-scenario finishes and returns outputs via a 'Return outputs' module.",
detail:
"Make's Subscenarios feature supports two modes: synchronous, where the parent calls the sub-scenario and pauses execution until it completes and returns output; and asynchronous, where the parent continues immediately without waiting. Each call creates its own separately logged run, and an error in the sub-scenario propagates back to the parent's error handling. This is a dedicated composition feature, distinct from triggering an unrelated scenario via a plain webhook.",
shortValue: 'Yes: Call a Scenario module runs a sub-scenario as a step',
confidence: 'verified',
sources: [
{
url: 'https://help.make.com/subscenarios',
label: 'Subscenarios - Make Help Center',
asOf: '2026-07-02',
},
{
url: 'https://help.make.com/scenario-inputs-and-scenario-outputs',
label: 'Scenario inputs and scenario outputs - Make Help Center',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -599,6 +619,26 @@ export const makeProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
'Yes: Make has two dedicated Flow Control loop modules. The Iterator takes an existing array and outputs each element as a separate bundle, running every downstream module once per item, sequentially. The Repeater generates a fixed number of bundles from scratch (a numeric counter, no source array needed), also processed one at a time.',
detail:
"Per Make's Help Center, the Iterator splits an array into individual bundles that flow through the rest of the scenario one item at a time, while the Repeater runs a specified number of repetitions (its 'repeats' field) with each bundle carrying an incrementing counter item. Both are sequential, item-by-item execution; Make's separate Router feature (used for branching, not looping) is also documented as processing routes sequentially rather than in parallel.",
shortValue: 'Yes: Iterator (array loop) and Repeater (counted loop)',
confidence: 'verified',
sources: [
{
url: 'https://help.make.com/iterator',
label: 'Iterator - Make Help Center',
asOf: '2026-07-02',
},
{
url: 'https://www.make.com/en/help/tools/flow-control',
label: 'Flow control - Make Help Center',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -978,6 +1018,26 @@ export const makeProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
'Partial: any developer can build a custom Make app, but publishing it to the public Apps Marketplace requires passing a Make QA code review before it becomes available to all users',
detail:
"Make's Developer Hub documents an open custom-app development model (any third-party developer can build and privately use a custom app), combined with a gated marketplace: to share an app with all Make users, the developer must request an app review, and Make's QA team examines the app's code against app standards and best practices (including sanitization of sensitive data such as API keys/tokens) before publishing it publicly. This is a lighter-touch, code-reviewed model rather than either a fully closed first-party catalog or a fully open, unreviewed community marketplace. No publicly documented security incident specifically involving malicious or credential-leaking third-party Make apps/marketplace listings was found.",
shortValue: 'Partial: open custom apps, but QA-reviewed before public marketplace listing',
confidence: 'verified',
sources: [
{
url: 'https://developers.make.com/custom-apps-documentation/app-review/overview',
label: 'App review overview - Make Developer Hub',
asOf: '2026-07-02',
},
{
url: 'https://developers.make.com/custom-apps-documentation/apps-marketplace/terms-and-conditions',
label: 'Apps Marketplace terms and conditions - Make Developer Hub',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
File diff suppressed because it is too large Load Diff
@@ -338,6 +338,21 @@ export const n8nProfile: CompetitorProfile = {
},
],
},
subWorkflows: {
value:
"Yes: the Execute Sub-workflow node calls a saved workflow as a step in another workflow, with a 'Wait for Sub-Workflow Completion' option so the parent pauses until the child finishes, passing data in via the child's trigger and receiving data back from the child's last node.",
detail:
"The child workflow starts with a 'When Executed by Another Workflow' trigger that defines the expected input fields. When 'Wait for Sub-Workflow Completion' is enabled, the parent blocks until the sub-workflow finishes and receives whatever data the sub-workflow's final node outputs; disabling it lets the parent continue without waiting.",
shortValue: 'Yes, Execute Sub-workflow node with wait-for-completion option',
confidence: 'verified',
sources: [
{
url: 'https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow/',
label: 'Execute Sub-workflow | Nodes | n8n Docs',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -618,6 +633,21 @@ export const n8nProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
"Yes: the Loop Over Items (Split in Batches) node iterates a list in fixed-size batches, running each batch sequentially through a 'loop' output and combining results through a 'done' output once all batches complete.",
detail:
"Loop Over Items processes a configurable batch size per iteration and re-enters the loop until every input item has passed through, rather than fanning items out concurrently. n8n's docs note this is the primary built-in mechanism for iterative processing, distinct from the Parallel-style concurrent fan-out other flow-logic nodes provide.",
shortValue: 'Yes, Loop Over Items node, sequential batch iteration',
confidence: 'verified',
sources: [
{
url: 'https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches/',
label: 'Loop Over Items (Split in Batches) | Nodes | n8n Docs',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -973,6 +1003,31 @@ export const n8nProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
'Partial: n8n ships built-in first-party nodes plus an open community-node ecosystem published to public npm, where only a subset carry an official "verified" review',
detail:
"Beyond its built-in nodes, n8n lets any developer publish a community node as a public npm package that other users install by name; only nodes n8n manually reviews for quality and security (and which forgo runtime dependencies) earn the verified shield icon and are installable/discoverable from n8n Cloud, while unverified community nodes can still be installed on self-hosted instances (or disabled via N8N_COMMUNITY_PACKAGES_ENABLED). n8n's own docs warn that community nodes run with the same level of access as n8n itself, including decrypted credentials during execution. In January 2026, researchers documented a real supply-chain attack in which malicious npm packages posing as n8n community nodes (one mimicking a Google Ads integration) stole OAuth tokens from the credential store; the primary malicious package had 4,241 downloads listed before removal.",
shortValue: 'First-party nodes plus an open, lightly-vetted npm community marketplace',
confidence: 'verified',
sources: [
{
url: 'https://docs.n8n.io/integrations/community-nodes/risks',
label: 'Risks when using community nodes | n8n Docs',
asOf: '2026-07-02',
},
{
url: 'https://docs.n8n.io/integrations/creating-nodes/build/reference/verification-guidelines/',
label: 'Verification guidelines | n8n Docs',
asOf: '2026-07-02',
},
{
url: 'https://thehackernews.com/2026/01/n8n-supply-chain-attack-abuses.html',
label: 'n8n Supply Chain Attack Abuses Community Nodes to Steal OAuth Tokens',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -319,6 +319,26 @@ export const openaiAgentkitProfile: CompetitorProfile = {
},
],
},
subWorkflows: {
value:
"No: Agent Builder's node reference (Start, Agent, Note, File search, Guardrails, MCP, If/else, While, Human approval, Transform, Set state) has no node that calls a separate saved workflow as a nested step and waits for it to finish. Composition across agents happens via handoffs between Agent nodes within the same workflow canvas, not by invoking another independently saved workflow as a reusable child step.",
detail:
'A workflow can call other agents through handoffs (execution transfers to another Agent node, carrying conversation state), but that is agent-to-agent handoff inside one workflow graph, not a documented call-another-workflow-and-return block. The only way to reuse a workflow elsewhere is to export it as Agents SDK code and call that code from other code, which is a code-level reuse pattern rather than a visual sub-workflow step.',
shortValue: 'No dedicated call-sub-workflow node found',
confidence: 'estimated',
sources: [
{
url: 'https://developers.openai.com/api/docs/guides/node-reference',
label: 'Node reference | OpenAI API',
asOf: '2026-07-02',
},
{
url: 'https://developers.openai.com/api/docs/guides/agent-builder',
label: 'Agent Builder | OpenAI API',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -556,6 +576,26 @@ export const openaiAgentkitProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
"Yes: Agent Builder has a dedicated 'While' logic node that loops on a custom Common Expression Language (CEL) condition, re-running the connected steps sequentially each pass until the condition is false.",
detail:
"The While node is condition-based rather than an explicit for-each-over-a-list container: iterating over a list means writing a CEL expression that checks an index or remaining-items condition against a Set-state variable, and incrementing that variable each pass, rather than dropping in a purpose-built for-each block. Iterations run one after another (sequential), matching the node palette's lack of any fan-out/parallel node.",
shortValue: 'Yes, via the While logic node (condition-based, sequential)',
confidence: 'verified',
sources: [
{
url: 'https://developers.openai.com/api/docs/guides/node-reference',
label: 'Node reference | OpenAI API',
asOf: '2026-07-02',
},
{
url: 'https://community.openai.com/t/agent-builder-while-loop-transform-and-set-state-an-example/1362386',
label: 'OpenAI Community: Agent Builder - While Loop, Transform and Set State example',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -913,6 +953,36 @@ export const openaiAgentkitProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
"Partial: pre-built Connector Registry entries (Dropbox, Google Drive, SharePoint, Teams) and the ChatGPT Apps directory go through OpenAI identity verification and app review, but Agent Builder's MCP node and the Agents SDK can connect to any third-party MCP server with no vendor vetting pipeline documented",
detail:
"OpenAI's own Connector Registry connectors and ChatGPT Apps directory submissions require developer identity verification and pass through an OpenAI app-review process before listing, per the App submission guidelines. But Agent Builder's MCP node and the Agents SDK let a builder point at any hosted MCP server, first-party or community-run, with no described OpenAI review of that server's code. This client-only MCP model mirrors the wider MCP ecosystem, where unreviewed community servers have shipped malicious behavior elsewhere (for example, an unofficial third-party Postmark MCP server was found in September 2025 silently BCC'ing all outgoing email to an attacker). No security incident specific to OpenAI's own Connector Registry, Apps directory, or Agent Builder MCP integration was found in public reporting as of this writing.",
shortValue: 'Partial: reviewed first-party catalog, but open MCP server connections',
confidence: 'estimated',
sources: [
{
url: 'https://developers.openai.com/apps-sdk/app-submission-guidelines',
label: 'App submission guidelines | Apps SDK | OpenAI Developers',
asOf: '2026-07-02',
},
{
url: 'https://developers.openai.com/apps-sdk/guides/security-privacy',
label: 'Security & Privacy | Apps SDK | OpenAI Developers',
asOf: '2026-07-02',
},
{
url: 'https://openai.com/index/developers-can-now-submit-apps-to-chatgpt/',
label: 'Developers can now submit apps to ChatGPT | OpenAI',
asOf: '2026-07-02',
},
{
url: 'https://authzed.com/blog/timeline-mcp-breaches',
label: 'A Timeline of Model Context Protocol (MCP) Security Breaches',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
File diff suppressed because it is too large Load Diff
@@ -309,6 +309,21 @@ export const pipedreamProfile: CompetitorProfile = {
},
],
},
subWorkflows: {
value:
'No: Pipedream\'s documented mechanism for connecting workflows is $.send.emit(), which is explicitly asynchronous ("Destination delivery is asynchronous: emits are sent after your workflow finishes"). This triggers a separate listener workflow after the emitting workflow completes; it is not a step that calls a saved workflow synchronously, waits for it, and receives its return value.',
detail:
'No Pipedream documentation describes a "call workflow" or "execute sub-workflow" step. Community help threads confirm the emit-and-listen pattern is the standard workaround for chaining workflows, not true parent-waits-for-child composition.',
shortValue: 'No, only async emit-to-listener chaining',
confidence: 'estimated',
sources: [
{
url: 'https://pipedream.com/docs/destinations/emit',
label: 'Pipedream Docs: Destinations (emit)',
asOf: '2026-07-03',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -495,6 +510,21 @@ export const pipedreamProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
'No: Pipedream\'s control flow docs list If/Else, Delay, Filter, and End Workflow as available operators, and the control flow overview page states "more operators (including parallel and looping) are coming soon" even after the Parallel operator itself shipped, indicating a dedicated sequential Loop/Repeat/For Each container is still not released as of this check.',
detail:
'No page exists for a Loop or Repeat control-flow operator (a guessed docs URL for it 404s), and long-running community threads confirm the standard workaround is iterating over an array inside a Node.js or Python code step rather than using a native loop block.',
shortValue: 'No native loop block; only code-step iteration workaround',
confidence: 'estimated',
sources: [
{
url: 'https://pipedream.com/docs/workflows/building-workflows/control-flow',
label: 'Pipedream Docs: Control Flow overview',
asOf: '2026-07-03',
},
],
},
},
integrations: {
integrationCount: {
@@ -838,6 +868,26 @@ export const pipedreamProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
'No: Pipedream is built around an open component registry where any developer can publish integration components to the public pipedreamhq/pipedream GitHub repo for anyone else to run, and users can also write and execute their own arbitrary custom code steps.',
detail:
'Community-contributed components go through automated checks (linting and other CI checks a contributor can also run locally via pnpm) rather than a documented manual first-party security review before a submission becomes runnable by other users. No publicly documented security incident specific to a malicious or compromised Pipedream component was found as of this check.',
shortValue: 'No, open community component registry',
confidence: 'estimated',
sources: [
{
url: 'https://pipedream.com/docs/components/guidelines',
label: 'Pipedream Docs: Components Guidelines & Patterns',
asOf: '2026-07-02',
},
{
url: 'https://pipedream.com/community',
label: 'Pipedream Community',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -340,6 +340,21 @@ export const powerAutomateProfile: CompetitorProfile = {
confidence: 'estimated',
sources: [],
},
subWorkflows: {
value:
'Yes: Power Automate supports child flows via the built-in "Run a Child Flow" action, which calls another flow as a step, waits for it to finish, and can pass inputs and receive its outputs back into the parent flow.',
detail:
'Child flows must use the "Manually trigger a flow" trigger and must be part of a solution to be callable this way; this is distinct from firing an independent flow asynchronously via HTTP/webhook.',
shortValue: 'Yes, via the "Run a Child Flow" action',
confidence: 'verified',
sources: [
{
url: 'https://learn.microsoft.com/en-us/power-automate/create-child-flows',
label: 'Create child flows - Power Automate | Microsoft Learn',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -595,6 +610,26 @@ export const powerAutomateProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
'Yes: Power Automate provides built-in loop containers, the "Apply to each" action iterates over a list/array and the "Do until" action repeats a set of actions until a condition or state is met, each running its iterations sequentially by default.',
detail:
'Apply to each can optionally run with concurrency (parallel iteration) via a setting, but sequential execution is the default behavior; Do until requires a defined exit condition and has a configurable iteration/timeout limit.',
shortValue: 'Yes, via "Apply to each" and "Do until" actions',
confidence: 'verified',
sources: [
{
url: 'https://learn.microsoft.com/en-us/power-automate/apply-to-each',
label: 'Use the Apply to each action - Power Automate | Microsoft Learn',
asOf: '2026-07-02',
},
{
url: 'https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-control-flow-loops',
label: 'Repeat actions with loops in workflows - Azure Logic Apps | Microsoft Learn',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -963,6 +998,27 @@ export const powerAutomateProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
"Partial: the certified connector catalog (1,400+ connectors, including third-party 'Independent Publisher' submissions) goes through a Microsoft Certification team review, identity/credential verification of the publisher, and swagger/endpoint/security validation before being listed. However, any user or org can also build and share 'custom connectors' that call arbitrary APIs, and these bypass the certification catalog entirely with no Microsoft security review. Security researchers at Zenity documented that custom connectors can be used to reach connectors otherwise blocked by Data Loss Prevention (DLP) policies, a real, publicly documented DLP-bypass finding tied to the custom-connector path specifically.",
detail:
"This is not an open, install-anything marketplace like n8n community nodes: independent publishers must pass identity verification and a Microsoft-run technical/security review to appear in the shared connector catalog. The gap is the separate custom-connector mechanism, which lets any maker define and use an unreviewed connector inside their own environment, and which Zenity's research showed can be abused to bypass connector-level DLP blocks.",
shortValue: 'Certified catalog is vetted; custom connectors bypass review and DLP',
confidence: 'verified',
sources: [
{
url: 'https://learn.microsoft.com/en-us/connectors/custom-connectors/certification-submission-ip',
label: 'Independent publisher certification process - Microsoft Learn',
asOf: '2026-07-02',
},
{
url: 'https://zenity.io/blog/research/microsoft-power-platform-dlp-bypass-uncovered-finding-3-custom-connectors',
label:
'AI Agent Security | Microsoft Power Platform DLP Bypass Uncovered - Finding #3 - Custom Connectors | Zenity',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -320,6 +320,26 @@ export const retoolProfile: CompetitorProfile = {
},
],
},
subWorkflows: {
value:
'Yes: the Workflow block runs another saved workflow as a step, passing data to it and receiving its returned data back, so the parent workflow can compose child workflows rather than duplicating logic.',
detail:
'The Workflow block supports two execution modes: Finished, where the calling workflow pauses until the triggered workflow run completes, and Queued, where the calling workflow continues immediately while the triggered run is queued.',
shortValue: 'Yes, Workflow block calls and waits on another workflow',
confidence: 'verified',
sources: [
{
url: 'https://docs.retool.com/workflows/guides/blocks/run-workflow',
label: 'Run another workflow with the Workflow block | Retool Docs',
asOf: '2026-07-02',
},
{
url: 'https://docs.retool.com/workflows/reference/objects/block/run-workflow',
label: 'The Workflow block | Retool Docs',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -549,6 +569,21 @@ export const retoolProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
'Yes: a dedicated Loop block runs an embedded set of blocks once per item in an array, referencing each item and its index via value and index.',
detail:
'The Loop block supports Sequential mode (each iteration completes before the next starts, with an optional delay to avoid rate limits), Parallel mode (all iterations run simultaneously), and Batch mode (a configurable number of iterations run in parallel per batch, default batch size 10) before moving to the next batch.',
shortValue: 'Yes, Loop block with sequential, parallel, and batch modes',
confidence: 'verified',
sources: [
{
url: 'https://docs.retool.com/workflows/guides/blocks/logic/loop',
label: 'Loop block | Retool Docs',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -858,6 +893,26 @@ export const retoolProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
"Yes: Retool's built-in integrations (Resources) are a first-party catalog of roughly 50 databases/APIs/cloud services built and maintained by Retool itself, not an open marketplace of third-party-submitted connectors. Retool separately offers Custom Component Libraries, which let a customer's own developers pull in npm packages to build custom UI components, but these are private to the authoring organization by default (or explicitly made public by that org) and are not a shared registry where other Retool customers install code published by unrelated third parties.",
detail:
"Retool documents that a custom component loads into a sandboxed iframe, and its own custom-component-guide plus a community forum thread ('Custom Component Vulnerabilities') flag that developers should run npm audit on the dependencies they pull into their own component libraries. This is a supply-chain caution for self-authored code, not a documented incident involving a shared marketplace, since no such public component marketplace exists.",
shortValue: 'Yes, first-party integration catalog, no public component marketplace',
confidence: 'verified',
sources: [
{
url: 'https://retool.com/integrations',
label: 'Retool Integrations',
asOf: '2026-07-02',
},
{
url: 'https://docs.retool.com/apps/guides/custom/custom-component-libraries/',
label: 'Build custom React components',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -280,6 +280,21 @@ export const stackaiProfile: CompetitorProfile = {
confidence: 'unknown',
sources: [],
},
subWorkflows: {
value:
"Yes: an AI Agent node can invoke a separately saved StackAI workflow as a Subflow Tool. The parent agent passes input into the subflow, waits for it to run to completion, and receives the subflow's output node result back before continuing, rather than only firing an async webhook-triggered run.",
detail:
'Subflow Tools are configured on the AI Agent node; each must connect to an output node to complete, and the docs describe subflows running "collaboratively" where one subflow\'s output can inform whether/how another is invoked. Whether a Subflow Tool can be reused unmodified across multiple different parent workflows was not independently confirmed.',
shortValue: 'Yes, via Subflow Tools on the AI Agent node',
confidence: 'estimated',
sources: [
{
url: 'https://docs.stackai.com/workflow-builder/core-nodes/ai-agent-node/subflow-tools',
label: 'Subflow Tools docs',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -484,6 +499,21 @@ export const stackaiProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
'Yes: the Loop Subflow node iterates over a list of inputs, running its Loop branch once per item sequentially, with the current item exposed via a current_item variable. A separate Done branch runs once after all iterations finish, collecting any outputs explicitly emitted inside the loop.',
detail:
'This is a sequential, one-item-at-a-time iterator distinct from the parallel/concurrent execution StackAI exposes separately through parallel Subflow Tool calls or parallel Project runs inside a loop.',
shortValue: 'Yes, via the Loop Subflow node',
confidence: 'verified',
sources: [
{
url: 'https://docs.stackai.com/workflow-builder/utils-logic-and-others/logic/loop-subflow',
label: 'Loop Subflow docs',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -762,6 +792,26 @@ export const stackaiProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
"Yes: StackAI's 70+ app integrations (databases, cloud storage, CRMs, communication tools) are built and maintained by StackAI's own team, not an open community marketplace. Users needing an unlisted service fall back to a built-in Custom API node or connect their own MCP servers, rather than installing code published by other third-party users.",
detail:
'No public marketplace or community-node registry (like n8n community nodes) was found where outside developers publish installable integrations for other StackAI users. MCP support lets a workspace point at third-party MCP servers, but that is a user-configured connection to an external server the user chooses, not a shared plugin store with lighter vendor review. No StackAI-specific security incident involving its integrations or MCP connections was found in public sources.',
shortValue: 'Yes, first-party catalog only',
confidence: 'estimated',
sources: [
{
url: 'https://docs.stackai.com/workflow-builder/apps',
label: 'StackAI Apps documentation',
asOf: '2026-07-02',
},
{
url: 'https://docs.stackai.com/workflow-builder/apps/mcp',
label: 'StackAI MCP documentation',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -322,6 +322,26 @@ export const tinesProfile: CompetitorProfile = {
},
],
},
subWorkflows: {
value:
"Yes: Tines' Send to Story action lets a parent Story call a separate sub-Story as a reusable step. The sub-story is configured with a webhook input action and a message-only output action; the parent's Send to Story action passes a payload, execution blocks until the sub-story finishes, and the sub-story's output event is returned to the calling action.",
detail:
'This is synchronous parent-waits-for-child composition with data passed in and returned, distinct from firing an independent story asynchronously via a plain webhook.',
shortValue: 'Yes: Send to Story calls a sub-story, waits, returns data',
confidence: 'verified',
sources: [
{
url: 'https://www.tines.com/docs/stories/send-to-story/',
label: 'Send to Story | Docs | Tines',
asOf: '2026-07-02',
},
{
url: 'https://www.tines.com/docs/stories/apis/',
label: 'Workflows as APIs | Docs | Tines',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -530,6 +550,26 @@ export const tinesProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
'Yes: Tines actions (including Event Transform in message-only mode and Send to Story) support a Loop attribute that points at a list or object field on the incoming event and invokes the action once per element, exposing a LOOP object for the current item on each pass. This is a per-action for-each attribute rather than a separate visual loop container block, and executes one item at a time rather than concurrently, distinct from the separate Explode/Implode parallel fan-out mechanism.',
detail:
'Tines caps a single loop at fewer than 20,000 elements. The dedicated concurrent-fan-out counterpart is Explode/Implode, documented separately as parallelExecution.',
shortValue: 'Yes: per-action Loop attribute, for-each over a list',
confidence: 'estimated',
sources: [
{
url: 'https://www.tines.com/university/advanced/looping/',
label: 'Looping in Tines | Tines University',
asOf: '2026-07-02',
},
{
url: 'https://www.tines.com/docs/actions/types/send-to-story/',
label: 'Send to Story | Docs | Tines',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -857,6 +897,26 @@ export const tinesProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
"Yes: Tines' executable actions (HTTP Request, webhooks, email, Send to Story, AI Agent, etc.) are a fixed, first-party set built and maintained by Tines itself, not a plugin/node marketplace; integrations with third-party tools are done by pointing the generic HTTP Request action at that tool's API, or by importing a pre-built 'Story' (a workflow template/JSON config, not installable code) from the community Story Library. No mechanism exists for a third party to publish executable custom actions/nodes that other tenants install.",
detail:
"The public Story Library has a 'Community selection' of user-submitted Story templates alongside Tines-authored ones, but these are shareable workflow configurations built from the same fixed first-party action set, not third-party executable plugins with their own code/dependencies (unlike n8n community nodes or a skill/plugin registry). No public vetting process for community Story submissions is documented, and no publicly documented security incident involving Tines' Story Library or action set was found.",
shortValue: 'Yes: fixed first-party action set, no plugin marketplace',
confidence: 'verified',
sources: [
{
url: 'https://www.tines.com/library',
label: 'Story Library | Tines',
asOf: '2026-07-02',
},
{
url: 'https://www.tines.com/docs/actions/overview',
label: 'Actions overview | Docs | Tines',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -280,6 +280,26 @@ export const vellumProfile: CompetitorProfile = {
confidence: 'unknown',
sources: [],
},
subWorkflows: {
value:
'Yes: Vellum has a Subworkflow node that executes a deployed or inline workflow as a step inside a parent workflow, waiting for it to finish and passing/receiving data through defined inputs and outputs.',
detail:
'Both "Deployed Subworkflows" (calling a separately versioned, released workflow) and "Inline Subworkflows" (defined within the parent workflow for modularization/reuse) are documented; the Agent Node can also register subworkflows as callable tools.',
shortValue: 'Dedicated Subworkflow node',
confidence: 'verified',
sources: [
{
url: 'https://docs.vellum.ai/developers/workflows-sdk/api-reference/nodes/subworkflow-deployment-node',
label: 'Subworkflow Deployment Node - Vellum Documentation',
asOf: '2026-07-02',
},
{
url: 'https://docs.vellum.ai/product/workflows/nodes/agent-node',
label: 'Agent Node - Vellum Documentation',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -504,6 +524,21 @@ export const vellumProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
"No: Vellum's only documented list-iteration mechanism is the Map Node, which executes a subworkflow once per array item concurrently (up to 96 parallel executions) rather than as a dedicated sequential for-each/while container; no separate While/loop node is documented.",
detail:
'The Map Node is already the mechanism counted under parallelExecution (concurrent fan-out plus Merge Strategy join). Vellum documentation does not describe a way to force single-lane sequential iteration or a distinct while/repeat-until construct.',
shortValue: 'Only a concurrent Map Node, no sequential loop',
confidence: 'estimated',
sources: [
{
url: 'https://docs.vellum.ai/product/workflows/nodes/map-node',
label: 'Map Node - Vellum Documentation',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -797,6 +832,26 @@ export const vellumProfile: CompetitorProfile = {
confidence: 'unknown',
sources: [],
},
thirdPartyVetting: {
value:
"Yes: Vellum's tool ecosystem is closed and vendor/partner controlled, not an open marketplace. Its own 100+ native integrations are built and maintained by Vellum, its Composio partnership adds access to Composio's curated tool library (not third-party developer submissions reviewed loosely), and 'Custom Nodes' are authored by the customer's own team for internal reuse rather than published to a shared public marketplace for other tenants to install.",
detail:
"No documentation was found describing a public marketplace or community-node/plugin registry where independent third-party developers publish executable code that other Vellum customers can browse and install, unlike ecosystems such as n8n community nodes. Custom Nodes extend a single customer's own workflows and are not distributed to other organizations. No publicly documented security incidents involving Vellum's integration or tool ecosystem were found.",
shortValue: 'Closed first-party/partner catalog, no open plugin marketplace',
confidence: 'estimated',
sources: [
{
url: 'https://www.vellum.ai/blog/vellum-composio-new-partnership-for-ai-agent-building',
label: 'Vellum + Composio: Build Powerful AI Agents Faster',
asOf: '2026-07-02',
},
{
url: 'https://docs.vellum.ai/developers/workflows-sdk/tutorials/custom-nodes',
label: 'Custom Nodes - Vellum Documentation',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -330,6 +330,26 @@ export const workatoProfile: CompetitorProfile = {
confidence: 'unknown',
sources: [],
},
subWorkflows: {
value:
"Yes: Recipe Functions' Call Recipe Function (Synchronously) action adds a step that calls another saved recipe as a child, passing input via that recipe's Input schema, waiting for it to finish, and returning its output through the Response schema back into the parent recipe's data pills; an asynchronous 'fire-and-forget' variant is also available for cases where the parent should not wait.",
detail:
"This supersedes the older Callable Recipes connector (legacy recipes still run, but new ones must use Recipe Functions). The synchronous call is subject to a timeout, after which Workato's docs recommend the async variant instead.",
shortValue: 'Yes: Call Recipe Function step, sync or async, with I/O',
confidence: 'verified',
sources: [
{
url: 'https://docs.workato.com/features/callable-recipes/call-recipe-action.html',
label: 'Callable Recipes - Call Recipe Actions | Workato Docs',
asOf: '2026-07-02',
},
{
url: 'https://docs.workato.com/connectors/recipe-functions/actions/call-recipe-function-synchronously.html',
label: 'Recipe Functions - Call Recipe Function Synchronously | Workato Docs',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -590,6 +610,26 @@ export const workatoProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
"Yes: a dedicated 'Repeat for each' loop block executes a nested set of steps once per item in a given list, sequentially rather than concurrently, with each iteration's data pills scoped to that item; Workato also offers a separate 'Repeat while' loop for condition-based looping, and 'Repeat for each in batches' for grouping items into fixed-size batches (default 100) per iteration when downstream systems can't accept single-record calls.",
detail:
'Docs explicitly frame Repeat for each as sequential, one item at a time, contrasting it with bulk/batch transfer; concurrent/parallel execution of loop iterations is not offered by this construct.',
shortValue: 'Yes: Repeat for each/while loop blocks, sequential',
confidence: 'verified',
sources: [
{
url: 'https://docs.workato.com/recipes/repeat-for-each.html',
label: 'Repeat for each loop | Workato Docs',
asOf: '2026-07-02',
},
{
url: 'https://docs.workato.com/recipes/loops.html',
label: 'Repeat while loop | Workato docs',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -967,6 +1007,31 @@ export const workatoProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
'Partial: Workato has a large first-party catalog of native, Workato-built connectors, plus an open Community Library where any developer with Connector SDK access can build and publish a connector that other users install with no formal Workato security review, alongside an invite-only Partner Connector tier that does get Workato code review.',
detail:
"Workato's own docs distinguish three tiers: native connectors are built and maintained by Workato directly; Partner Connectors go through Workato's partnership program with dedicated developer accounts and code review by Workato engineers on the initial version and subsequent updates; and Community Connectors are built by any community member and published to the Community Library with no formal Workato security review, explicitly labeled 'intended as examples only.' Installing a community connector requires full Connector SDK privileges, and Workato's own guidance tells users to independently evaluate and test a community connector's code before releasing it workspace-wide, since 'notwithstanding any Security Review conducted or any label provided by Workato, Workato does not certify, warrant or support any Community Listings, Partner Connectors or No Code Connectors.' No specific publicly documented incident (e.g., a malicious published community connector or a credential leak traced to one) was found; a Workato blog post on general AI/MCP security risk raises malicious lookalike marketplace tools as a theoretical/industry-wide concern, not a confirmed Workato-specific incident.",
shortValue: 'Partial: first-party catalog plus open, lightly-vetted community library',
confidence: 'verified',
sources: [
{
url: 'https://docs.workato.com/developing-connectors/community/community.html',
label: 'Community connectors | Workato Docs',
asOf: '2026-07-02',
},
{
url: 'https://docs.workato.com/developing-connectors/community/community-listing.html',
label: 'Contributing your connector | Workato Docs',
asOf: '2026-07-02',
},
{
url: 'https://www.workato.com/product-hub/community-connectors/',
label: 'Workato Community Connectors: What you need to know',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
@@ -323,6 +323,26 @@ export const zapierProfile: CompetitorProfile = {
},
],
},
subWorkflows: {
value:
'Yes: Sub-Zaps by Zapier let a Zap call a saved Sub-Zap as a dedicated step ("Call a Sub-Zap" action). The parent Zap waits for the Sub-Zap to finish, sends data into it via a "Start a Sub-Zap" trigger, and receives data back via a "Return from Sub-Zap" step.',
detail:
'Sub-Zaps are built once and reused across multiple parent Zaps, avoiding copy-paste duplication of the same step sequence.',
shortValue: 'Yes, via Sub-Zaps (Call a Sub-Zap action)',
confidence: 'verified',
sources: [
{
url: 'https://help.zapier.com/hc/en-us/articles/32283713627533-Understanding-Sub-Zaps',
label: 'Understanding Sub-Zaps',
asOf: '2026-07-02',
},
{
url: 'https://help.zapier.com/hc/en-us/articles/8496308527629-Create-reusable-Zap-steps-with-Sub-Zaps',
label: 'Create reusable Zap steps with Sub-Zaps',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -553,6 +573,26 @@ export const zapierProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
"Partial: Looping by Zapier provides a dedicated loop step that repeats a set of follow-up actions over a text list, line items, or a numeric range, up to 500 iterations. Zapier's own documentation states iterations execute concurrently in parallel by default, not sequentially, and this holds even when the loop is nested inside a Path configured to run sequentially. There is no official setting to force strictly sequential iteration order.",
detail:
'Zapier\'s help center: "All iterations of the loop execute in parallel (simultaneously), not one after another" and "Loops always run in parallel (simultaneously). This happens even if the loop is nested within a Path configured to run sequentially." Community workarounds (incremental delay steps, webhook-based looping) exist but are not a native sequential mode.',
shortValue: 'Yes, but iterations run in parallel by default, not sequentially',
confidence: 'verified',
sources: [
{
url: 'https://help.zapier.com/hc/en-us/articles/42969233918477-Understanding-Looping-by-Zapier',
label: 'Understanding Looping by Zapier',
asOf: '2026-07-02',
},
{
url: 'https://help.zapier.com/hc/en-us/articles/8496106701453-Loop-your-Zap-actions',
label: 'Loop your Zap actions',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -902,6 +942,31 @@ export const zapierProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
"Partial: Zapier's App Directory is an open developer ecosystem, not a closed first-party catalog. Any developer can build an integration on the Zapier Developer Platform and submit it for public listing; Zapier's review checks publishing/technical requirements (HTTPS-only endpoints, no hardcoded credentials, OAuth verification) rather than a deep security audit, and Zapier explicitly tells customers these apps are 'owned and operated by third parties' and that users are responsible for evaluating trust in the developer.",
detail:
"Zapier's own Partner Program docs describe review turnaround of up to 21 business days against publishing standards, and OAuth verification is framed as 'a helpful start' rather than a guarantee of an app's suitability. No documented security incident specifically tied to a malicious third-party app published in the App Directory was found; separate publicly reported incidents (a 2025 repository breach exposing debug logs, and a 2025 npm supply-chain compromise of Zapier's own published packages) involved Zapier's internal infrastructure and package registry, not the App Directory's third-party integration ecosystem.",
shortValue: 'Partial: open app directory, lighter technical review',
confidence: 'verified',
sources: [
{
url: 'https://platform.zapier.com/publish/integration-publishing-requirements',
label: 'Integration publishing requirements',
asOf: '2026-07-02',
},
{
url: 'https://docs.zapier.com/platform/publish/partner-program',
label: 'Partner Program',
asOf: '2026-07-02',
},
{
url: 'https://help.zapier.com/hc/en-us/articles/17709950386573-Data-safety-when-using-Zapier-embedded-in-other-apps',
label: 'Data safety when using Zapier embedded in other apps',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
+5
View File
@@ -1,10 +1,15 @@
export { claudeCoworkProfile } from '@/lib/compare/data/competitors/claude-cowork'
export { crewaiProfile } from '@/lib/compare/data/competitors/crewai'
export { dustProfile } from '@/lib/compare/data/competitors/dust'
export { flowiseProfile } from '@/lib/compare/data/competitors/flowise'
export { gumloopProfile } from '@/lib/compare/data/competitors/gumloop'
export { langchainProfile } from '@/lib/compare/data/competitors/langchain'
export { langflowProfile } from '@/lib/compare/data/competitors/langflow'
export { makeProfile } from '@/lib/compare/data/competitors/make'
export { microsoftCopilotProfile } from '@/lib/compare/data/competitors/microsoft-copilot'
export { n8nProfile } from '@/lib/compare/data/competitors/n8n'
export { openaiAgentkitProfile } from '@/lib/compare/data/competitors/openai-agentkit'
export { openClawProfile } from '@/lib/compare/data/competitors/openclaw'
export { pipedreamProfile } from '@/lib/compare/data/competitors/pipedream'
export { powerAutomateProfile } from '@/lib/compare/data/competitors/power-automate'
export { retoolProfile } from '@/lib/compare/data/competitors/retool'
+62
View File
@@ -298,6 +298,20 @@ export const simProfile: CompetitorProfile = {
},
],
},
subWorkflows: {
value:
"Yes: a Workflow block calls another saved workflow as a step, waits for it to finish, runs its latest deployed version, and maps parent variables into the child's input form",
detail: 'Self-references are blocked to prevent infinite recursion.',
shortValue: 'Workflow block calls a saved workflow as a reusable step',
confidence: 'verified',
sources: [
{
url: 'https://docs.sim.ai/workflows/blocks/workflow',
label: 'Sim Docs: Workflow block',
asOf: '2026-07-02',
},
],
},
},
aiCapabilities: {
multiLlmSupport: {
@@ -497,6 +511,11 @@ export const simProfile: CompetitorProfile = {
shortValue: 'Chunk-level search results and a dedicated chunk editor',
confidence: 'verified',
sources: [
{
url: 'https://docs.sim.ai/knowledgebase/debugging-retrieval',
label: 'Sim Docs: Debugging retrieval',
asOf: '2026-07-02',
},
{
url: 'https://github.com/simstudioai/sim/blob/main/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/chunk-editor/chunk-editor.tsx',
label: 'Sim codebase: chunk editor',
@@ -532,6 +551,19 @@ export const simProfile: CompetitorProfile = {
},
],
},
loopIteration: {
value:
'Yes: a Loop container block runs the blocks inside it repeatedly (For a fixed count, ForEach over a collection, While a condition holds, or Do-While), running iterations one after another; concurrent fan-out is a separate Parallel block',
shortValue: 'Native Loop block: For, ForEach, While, Do-While',
confidence: 'verified',
sources: [
{
url: 'https://docs.sim.ai/workflows/blocks/loop',
label: 'Sim Docs: Loop block',
asOf: '2026-07-02',
},
],
},
},
integrations: {
integrationCount: {
@@ -577,6 +609,11 @@ export const simProfile: CompetitorProfile = {
shortValue: 'Code-execution block for custom logic',
confidence: 'verified',
sources: [
{
url: 'https://docs.sim.ai/workflows/blocks/function',
label: 'Sim Docs: Function block',
asOf: '2026-07-02',
},
{
url: 'https://github.com/simstudioai/sim/blob/main/apps/sim/blocks/registry-maps.ts',
label: 'Sim codebase: block registry',
@@ -684,6 +721,11 @@ export const simProfile: CompetitorProfile = {
shortValue: 'BYOK exempts credit caps; multi-key round-robin rotation',
confidence: 'verified',
sources: [
{
url: 'https://docs.sim.ai/platform/costs#bring-your-own-key-byok',
label: 'Sim Docs: Bring Your Own Key (BYOK)',
asOf: '2026-07-02',
},
{
url: 'https://github.com/simstudioai/sim/blob/main/apps/sim/lib/billing/calculations/usage-monitor.ts',
label: 'Sim codebase: BYOK usage-monitor logic',
@@ -739,6 +781,11 @@ export const simProfile: CompetitorProfile = {
shortValue: 'Workspace and org-level role permissions',
confidence: 'verified',
sources: [
{
url: 'https://docs.sim.ai/platform/permissions',
label: 'Sim Docs: Roles and Permissions',
asOf: '2026-07-02',
},
{
url: 'https://github.com/simstudioai/sim/blob/main/packages/db/schema.ts',
label: 'Sim codebase: permissionTypeEnum, role columns',
@@ -872,6 +919,21 @@ export const simProfile: CompetitorProfile = {
},
],
},
thirdPartyVetting: {
value:
"Yes: every one of Sim's 302 blocks is first-party authored and code-reviewed through the standard pull-request process in the main Sim repository; there is no public marketplace where an arbitrary third party can publish and have other users install executable tool code without going through Sim's own review",
detail:
"Custom code steps run inside Sim's own isolated-vm sandbox rather than as an installable third-party skill package, so the supply-chain trust boundary is Sim's codebase review, not an open registry.",
shortValue: 'All 302 blocks are first-party authored and code-reviewed',
confidence: 'verified',
sources: [
{
url: 'https://github.com/simstudioai/sim/tree/main/apps/sim/blocks/blocks',
label: 'Sim codebase: first-party block directory',
asOf: '2026-07-02',
},
],
},
},
observability: {
tracingDepth: {
+6
View File
@@ -64,6 +64,8 @@ export interface ComparisonFacts {
dataTables: Fact
/** An inline rich-text/WYSIWYG markdown editor for documents stored in the platform, versus a plain textarea or raw-source view only. */
richTextEditor: Fact
/** Calling one saved workflow as a reusable step inside another workflow (composition/nesting), versus only being able to duplicate or manually re-wire the same logic per workflow. */
subWorkflows: Fact
}
aiCapabilities: {
multiLlmSupport: Fact
@@ -90,6 +92,8 @@ export interface ComparisonFacts {
parallelExecution: Fact
/** Support for the Agent2Agent (A2A) protocol, the emerging open standard for one AI agent to discover and call another agent as a peer, distinct from ordinary MCP tool-calling. */
a2aProtocol: Fact
/** A dedicated for-each/while loop container that iterates a set of steps over a list or a fixed count, distinct from a Parallel block's concurrent fan-out. */
loopIteration: Fact
}
integrations: {
integrationCount: Fact
@@ -126,6 +130,8 @@ export interface ComparisonFacts {
piiRedaction: Fact
/** SAML/OIDC single sign-on with organization auto-provisioning on first login. */
sso: Fact
/** Whether integrations/tools/skills come from a vetted first-party catalog authored and reviewed by the vendor, versus an open marketplace where any third party can publish and users install executable code from unvetted authors. */
thirdPartyVetting: Fact
}
/**
* Production-readiness signals that matter once feature parity is