# vendo: a customization layer your customers build on themselves

> vendo is an Apache-2.0 customization layer for B2B SaaS products. An embedded agent acts through your own API as the signed-in user, generates UI that runs inside an iframe with connect-src none, and puts policy, approvals and audit behind one execution choke point, without touching your source.

**runvendo/vendo** — Embedded agents your customers use to automate work, build views, and connect their tools.

- Repository: https://github.com/runvendo/vendo
- Website: https://vendo.run
- Stars: 627 · Forks: 107
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/runvendo-vendo

## The agent acts as the signed-in user, and your source stays untouched

The problem being addressed is specific to B2B software. Customers keep asking for bespoke features, and each request turns into a fork, a patch or a feature flag nobody wants to maintain. Vendo describes itself as an open-source customization layer on top of your product, where your users build their own features and micro-apps. The mechanism is an embedded agent with two properties worth separating. It acts through your product's own API as the signed-in user, so anything it does is already something that user was allowed to do. And it renders the UI it generates in a sandboxed, brand-native surface, with the claim that your source code is never touched stated in the same paragraph as both of those. Whether that holds depends on how the generated code reaches your build, but the design intent is clear: the customization layer sits beside your codebase rather than inside it. The three demos the project shows are real agent runs in a demo host app rather than mockups.

## Install is two commands, and the README also ships a prompt for your agent

The short path is:```bash
npm install @vendoai/vendo
npx vendo init
```The longer path is aimed at teams with a coding agent in the loop, and it is a prompt rather than a tutorial. The README tells the agent to read a machine-readable install document at vendo.run/agents.md and follow it exactly, to relay Vendo's setup questions back to the developer and use their answers, and to ask before creating any account or key, with Vendo Cloud named as the recommended option. The prompt also defines done: your app runs and the agent answers from your own API. Two details in the repository make that prompt maintainable. The text is canonical in a source file, with a comment in the README saying it is mirrored by the documentation AgentPrompt card and should be changed there first. That single source is why the readme version and the docs version do not drift. The optional checkup is `vendo doctor`, and its design choice is the useful part: every code it prints links to the exact fix for that code.

## Generated components run in an iframe with connect-src set to none

The generation step is where the security claim lives, and it is described in concrete browser terms rather than as a general promise. Vendo reads your API and turns it into tools the agent executes as the signed-in user, then composes views and user-owned apps from a format-tagged UI document. Components the agent generates run inside an iframe jail declared with `connect-src 'none'`, which means no outbound network from the frame at all. When a generated component genuinely needs a server, execution escalates to a sandboxed server, and only when it is needed. The consequence for an adopter is that most generated views should need no server, and the ones that do will feel different, so a demo that never escalates is not the whole picture. The agent itself runs streaming against any AI SDK `LanguageModel`, so the model layer is not locked in. The other demo worth noting is in-place UI editing: hover a component, describe the change, apply it in place, against the host's own components.

## Policy, approvals, grants, breakers and audit share one choke point

The guard step is a list of five nouns and one architectural commitment. Policy, approvals, grants, breakers and audit all sit at a single execution choke point, and app machines reach host tools only through the guarded tool proxy. That concentration is the part to evaluate, because a system with one choke point is easy to reason about only if everything really does go through it. The nouns themselves are worth unpacking. Approvals are what make the automation demo honest, since that pitch is plain language in and standing automation out with every tool gated by approval. Grants are what an approval becomes once given, and breakers are the mechanism that stops an automation from running away. Audit is what lets an operator answer afterwards who authorised what. Because the agent holds the signed-in user's own permissions, this layer is not an add-on to your authorization model, it is the thing standing between generated code and your customer's data.

## PGlite at .vendo/data in development, the same schema on Postgres

Storage is resolved by removing the question rather than answering it. PGlite at `.vendo/data` is the zero-config store, so a developer can run an embedded agent with no database to provision, and production runs the same schema on Postgres. The same-schema claim is the load-bearing part: it means the migration you skip locally is one you run once for real, rather than a different data model you discover during a launch. The store path is also where generated state lives, since user-owned apps are built at runtime rather than checked in, so `.vendo/data` is the directory to put in your ignore file and to think about before it contains anything a customer generated. The neighbouring concern is telemetry, which the project is explicit about rather than quiet on: a TELEMETRY.md sits at the repository root next to SECURITY.md, CREDITS.md, LICENSE and NOTICE. For a product whose agent runs against customer data, having that document at the root is a reasonable baseline to check before you evaluate anything else.

## Four entry points depending on where your agent already lives

The install page branches by what you already have, which is more useful than one default path. If you already have an agent, there is one tool pack for an AI SDK, for Mastra, or for a homegrown loop. If your product has no agent at all, one command brings the loop, the chat UI and the approvals together. If you want to expose your product over MCP, the page covers how the door works, and the named beneficiaries are Claude, ChatGPT, Cursor and Claude Code acting as the signed-in user. And if your agent lives in your backend, there is one package exposing `agent()` and `chat()`, explicitly with no CLI and no UI of Vendo's to mount, which is the path for a headless service. Four audiences means four sets of integration cost, and the examples directory mirrors them: an AI SDK agent, a Claude Code plugin, a demo bank and a Mastra agent. The demo bank is the one to study if you want to see the generated views on a product surface that is not a toy.

## Sharing and org overlays are cloud-gated, the blocks stay self-hosted

This is an open-core boundary and the README states it in one sentence, which is more than most projects manage. Cloud-gated features are sharing, publishing, organisation overlays and pinning, and they activate when `VENDO_API_KEY` is set. The open-source blocks remain self-hosted. If you are selling the customization layer into a product with its own compliance requirements, that sentence decides whether sharing a user-built app between workspaces is something you can offer or something you have to route through a vendor account. The package layout is built for composition rather than for one blob. `@vendoai/vendo` is the default composition, with `vendoai` as a thin alias, and the individual blocks are installable on their own: `/core` for shared types, schemas, formats, validators, seams and the browser-safe app-generation contract at `@vendoai/vendo/core/apps`, and `/ui` for headless React hooks, optional chrome, tree rendering and the in-jail component kit. The full package also carries the named blocks, including sandbox, persistence, telemetry, automations, MCP-door, guard and harness.

## Lint runs four commands and only two of them are ESLint

The root scripts describe a project with opinions about its own supply chain. `lint` is not one command. It runs a dependency guard, a citation guard and a portability gate as three separate Node scripts, and only then hands off to turbo for the package lint. Each of those names is a policy: dependencies are checked, citations are checked, and portability is checked. The ESLint side is split into two configurations, `eslint.blocking.config.mjs` and `eslint.report.config.mjs`, which is a way of saying some findings fail the build and others are collected, with `lint:report` producing the collected view. The test script is equally deliberate, pinning vitest to one or two forks and one or two threads and continuing past failures at concurrency four, so a large suite does not exhaust a laptop. A conformance target is filtered to the main package, and separate `corpus` and `genbench` harnesses exist for corpus runs and generation benchmarks. Around that sit knip for unused exports, renovate for updates, gitleaks for secrets, changesets with a version-sync script, and a root version of 0.0.0 that is never the shipped one.

## Conclusion

vendo fits a B2B product whose customers keep filing bespoke feature requests and whose team would rather not fork the codebase for each one, because the extraction step turns your existing API into tools and the generated surface never touches your source. Three cautions before you commit. Sharing, publishing, org overlays and pinning sit behind `VENDO_API_KEY`, so check which of your intended use cases are open source and which are cloud before you promise a customer self-hosting. The agent executes as the signed-in user, which means the guard layer is the whole security story and its choke point is worth reading rather than assuming. And the generated UI runs in an iframe with `connect-src 'none'` before escalating to a sandboxed server, so components that need real network access will behave differently from the ones that do not.

## FAQ

### How does the vendo agent get access to my product?

Vendo reads your API and turns it into tools, and the agent executes those tools as the signed-in user. Your source code is not touched, since the generated surface is rendered in a sandboxed, brand-native view.

### How are generated UI components sandboxed in vendo?

Generated components run in an iframe jail declared with connect-src set to none, and escalate to a sandboxed server only when a component needs one. They are composed from a format-tagged UI document.

### What requires a Vendo Cloud API key?

Sharing, publishing, organisation overlays and pinning are cloud-gated and activate with VENDO_API_KEY. The open-source blocks remain self-hosted, so those four capabilities are the ones to check against your compliance requirements.

### Do I need my own agent to use vendo?

No. There is a path for teams who already have an agent, one tool pack for an AI SDK or Mastra or a homegrown loop, and a path for products with no agent where one command brings the loop, chat UI and approvals. A fourth path mounts agent() and chat() in your own backend with no CLI or UI from Vendo.

### What does the vendo doctor command do?

It is an optional checkup after install, and every code it prints links to the exact fix for that code. Install itself is npm install @vendoai/vendo followed by npx vendo init.

## Sources

- [Issues](https://github.com/runvendo/vendo/issues)
- [License: Apache-2.0](https://github.com/runvendo/vendo/blob/main/LICENSE)
- [Project website](https://vendo.run)
- [README](https://github.com/runvendo/vendo/blob/main/README.md)
- [runvendo/vendo on GitHub](https://github.com/runvendo/vendo)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/runvendo-vendo
