A workflow library is not a migration path
1,340 browsable templates is not the same claim as 1,340 workflows that run. We built real vendor connectors and an agent composer, then audited the whole library to find out exactly how far that got us.

Reason
AgentsQuoxMindAgentic TeamsMirrorQuoxLensRemember
QuoxMemoryBrain2CompoundingQuoxPlanCodebase MirrorAct
QuoxFlowQuoxEngineQuoxAgentQuoxChatAutonomyRun
EnterpriseOrganisationsPowers & ToolsmithQlusterQuoxBastionInterfaces
QuoxMCPQuoxCLIQuoxTerminalQuox ConsoleQuoxBoxGovern
HITL ApprovalsQuox SecurityAgent HonestyQuoxVaultAI GovernanceProve
For AuditorsVerifiable AI OpsLoggingEU AI ActCompliance SuiteChannels
Matrix RoomsDiscord ProTelegram ProQuoxSignalCoreCommsAll products A-ZGet started
OverviewArchitectureProtocols
AEEAOCLVOLTWARDReference
GlossaryAPI ReferencePlugin SDKDockerAll products A-Z1,340 browsable templates is not the same claim as 1,340 workflows that run. We built real vendor connectors and an agent composer, then audited the whole library to find out exactly how far that got us.

A library of 1,340 n8n workflows converted to QuoxFlow's JSON format is a search index. It is not proof that 1,340 workflows run. We had both claims sitting next to each other on the same page, and only one of them was true.
The Workflow Library plugin ships 1,340 workflows pulled from a real n8n community archive and converted into QuoxFlow's node format. Browse them, search them, read the structure on a WireMap diagram, copy the JSON. That part has been true for a while.
What wasn't true, or at least wasn't checked, was the implicit claim sitting underneath it: that a converted workflow is a working workflow. It isn't, automatically. n8n's importer maps node shapes onto QuoxFlow node types.
For anything QuoxFlow doesn't have an explicit mapping for, and for any vendor integration nobody has written a connector for yet, the converter falls back to a generic placeholder: a call node pointed at ${vars.integrationEndpoint}, with the original n8n parameters dumped in as a note. It looks like a workflow. It does not run like one.
So we spent an evening closing that gap where we honestly could, and auditing the rest so we'd know exactly how much was left.
The fix for the placeholder problem is a per-vendor connector library (src/n8n/connectors/ in the quoxflow repo). Nine n8n node types now resolve to a genuine vendor API call instead of the placeholder: real endpoint, real HTTP method, and the request body reshaped into that vendor's actual API format.
Each connector targets that vendor's dominant real-world operation, sampled from the workflow library itself rather than guessed. Slack and Telegram both default to "no explicit operation configured" in the vast majority of real samples, because both nodes treat "post a message" as their own default. Google Sheets splits almost evenly between append and read. Gmail is dominated by send.
We built to the shape the library actually contains, not to a spec sheet of every possible n8n operation.
Counted across every instance of that node type in the 1,340-workflow sample, not just whether the vendor is "supported" as a checkbox.
| Vendor | Operation(s) covered | Instances resolved |
|---|---|---|
| Email send | mail send (SendGrid-shaped) | 55 / 55 · 100% |
| Slack | chat.postMessage | 116 / 142 · 82% |
| Telegram | sendMessage | 165 / 228 · 72% |
| Google Sheets | append, read | 219 / 334 · 66% |
| OpenAI | chat, image-analyze | 103 / 167 · 62% |
| Gmail | messages.send | 78 / 156 · 50% |
| Notion | page create, update | 55 / 102 · 54% |
| Google Drive | files.get (download) | 61 / 161 · 38% |
| Airtable | create, search | 56 / 168 · 33% |
The remaining instances of each node type use an operation this pass didn't build (update, delete, list, upload) and still fall back to the generic placeholder.
Most connectors are a straightforward field-mapping exercise: read n8n's parameters, write the vendor's request shape. Gmail wasn't. Gmail's API takes one base64url-encoded raw RFC 2822 message, not separate to/subject/body fields, so the three source fields have to be combined into a single computed value at the point QuoxFlow's expression engine actually runs, not at conversion time (the values themselves are runtime expressions, not static strings).
We reused QuoxFlow's own ${...} expression syntax, which happens to be the same syntax a JavaScript template literal uses for its own placeholders, to splice the fields into a raw MIME message and base64-encode the whole thing inline.
The engine's own documented $.base64Encode() helper turned out to be dead code in the isolated-vm sandbox actually running expressions, and btoa isn't defined there either, so the connector carries its own small inlined base64 encoder rather than depending on either. Small detail, but it's the kind of detail that decides whether a "send an email" node sends an email or throws at runtime.
The second half of the work was n8n's LangChain family: Agent and Chain nodes, plus the Chat Model, Memory and Tool nodes that feed them. These don't use n8n's normal connections.main graph at all.
A Chat Model node points at the Agent node it configures, using an ai_*-typed connection keyed under the Chat Model's own entry in the workflow's connections object, the opposite direction from how every other edge in an n8n workflow reads.
Finding "what feeds this Agent node" means scanning every entry in connections for an ai_* link whose target is the node in question, which is what agent-resolver.ts does.
Once resolved, an n8n Agent node composes onto QuoxFlow's agent:invoke, and a Chain ("Basic LLM Chain") node composes onto assistant:invoke. The attached Chat Model and Memory nodes fold away entirely rather than surviving as orphaned, unrunnable standalone nodes: they're informational only, since the QuoxFlow agent or assistant you assign brings its own model.
Attached Tool nodes are named in an explicit warning rather than silently dropped, but not auto-wired: QuoxFlow's tool/action identifiers don't correspond to arbitrary n8n tool node types, and guessing a mapping would be worse than admitting the gap.
Here's the part that's easy to oversell: composing the Agent or Chain node correctly does not mean the whole workflow that contains it now runs. Of the 308 sampled workflows that use an Agent or Chain node, 0 are blocked by the agent piece itself anymore. But only 22 are fully clean or minor-polish end to end.
The other 286 are still blocked, just by something else entirely: a Merge node, a vector store, a document loader, an HTTP tool node, some other integration this pass didn't reach.
That's the honest shape of an "AI agent workflow" in the wild: the agent is rarely the only moving part. A RAG pipeline needs an embeddings node and a vector store before the agent ever runs. A support-ticket triage agent needs a ticketing integration on both sides of it. Fixing the agent composition was necessary.
It was never going to be sufficient on its own, and we didn't want to imply otherwise.
Same 1,340-workflow sample, one audit, run against the fully merged code (both the connector library and the agent composer).
The two most common reasons a workflow is still blocked have nothing to do with vendor connectors at all. Merge (339 instances in the sample) and Split In Batches (183 instances) are n8n's own data-shaping primitives, not integrations, and QuoxFlow doesn't yet have a mapped equivalent for either.
After that, it's a long tail of vendors this pass didn't reach: HubSpot, Redis, Microsoft Outlook, plus the RAG/vector-store family (embeddings, document loaders, text splitters, vector stores), which was explicitly out of scope for tonight.
That's a more useful finding than "88% blocked" sounds on its own. It means the next highest-leverage work on this importer probably isn't a tenth vendor connector. It's Merge and Split In Batches, because those two node types alone gate a meaningful share of the entire library, across every category, not just AI workflows.
Every connector authenticates by referencing a QuoxFlow workflow variable: ${vars.CREDENTIAL_SLACK_API} and so on. That variable is something you set yourself, today, as plain workflow configuration.
QuoxFlow has a CredentialResolver class built for vault-backed credential storage. It is not wired into the real execution path yet. Nothing in a live workflow run actually calls it. So we're not going to describe these connectors as vault-managed or securely stored, because they aren't, yet. They resolve from a workflow variable you configure, the same way any other QuoxFlow variable does.
Wiring the credential resolver into live execution is tracked as its own piece of work. Until it ships, this is the accurate description, not the flattering one.
The instinct when you build something is to lead with the biggest true-ish number. We'd rather lead with 154 (63 clean plus 91 minor-polish) and be right, than lead with 1,340 and be technically defensible. A vendor who tells you exactly where their coverage stops is one whose claims you can actually plan around.
On publishing the number that isn't 1,300
QuoxFlow's n8n importer, the vendor connector library, and the honest coverage numbers, all on one page.