Shipping Sulla's marketplace: what I learned the hard way
The marketplace was the hardest piece of the platform to ship — not because of code, but because of taxonomy. Workflows vs. recipes vs. functions vs. agents.
I assumed the marketplace would be the easy part of Sulla.
Wrong.
The code was straightforward. The hard part was taxonomy: what kinds of things live in the marketplace, what they’re called, and how a user understands the difference between them when they’re browsing.
The four primitives
Sulla has four kinds of installable things:
- Workflows — declarative YAML graphs. Run by the workflow engine.
- Recipes — Docker compose configs that install services (Twenty CRM, n8n, Postgres, etc.)
- Functions — Python/Node/Shell scripts called by workflows
- Agents — autonomous loops with their own context and channels
Each one solves a different problem. None of them is the same thing.
But from the buyer’s perspective, all four look like “things you install to make Sulla do more.” The conceptual distinction is meaningful to the platform but invisible to the user until they hit a wall.
Three taxonomies I tried
Attempt 1: One unified “Marketplace” tab. Show everything, filter by type. Result: users couldn’t tell what they were looking at. “Why is this Workflow named the same as that Recipe?” Failed.
Attempt 2: Four separate tabs. Workflows / Recipes / Functions / Agents. Result: nobody knew which tab to start in. The first-time experience was a paralysis menu. Failed.
Attempt 3 (current): Tasks-based grouping. Reframe by what the user is trying to do: “Run scheduled jobs” / “Add an integration” / “Build a custom workflow” / “Deploy an agent.” The four primitives still exist underneath, but the surface is verbs not nouns.
That’s working. Not perfect, but working.
The lesson I keep relearning
Platform abstractions are for the platform, not the user. Workflows / Recipes / Functions / Agents are the right primitives for the engine. They’re the wrong primitives for the marketplace UI.
I knew this. I’ve shipped this lesson three or four times in different contexts. I still got it wrong on Sulla. The pull toward exposing your internal model in the UI is strong, especially when the internal model is genuinely good.
If you’re building a developer platform with multiple primitives, write down what each one is for the user before you write down what each one is for the system. Two different sentences. Use them.
— J