Back to writing
9 dead linksfound in Research
R
Attention is all you need
arxiv.org/abs/1706.03762
G
Google Reader
reader.google.com
dead
N
Nature briefing
nature.com/briefing
B
Bay Area house prices
blog.example.dev/2019
dead
H
HN: Show HN thread
news.ycombinator.com
L
Linkwarden docs
docs.linkwarden.app
vendo

An agent inside a bookmark manager

Blog
From the team · vendo.run
Blog

An agent inside a bookmark manager

We installed Vendo into Linkwarden — a real open-source product we didn't write — and published every file it took.

AIAmr Ibrahim
Amr Ibrahim
Engineering, Vendo
Aug 15, 20262 min read

Linkwarden is an open-source bookmark manager. People self-host it, sign in, and file links into collections. It has an API, a Prisma schema, and no idea what Vendo is.

That made it the right test. Every demo we ship was built by people who knew where the agent would go. A real install starts from the other side: someone's existing product, someone's existing auth, a workspace already full of opinions. So we forked Linkwarden and gave it an agent, the way you would give yours one.

Signed in, you click a launcher pill and ask for something the product has no page for. "Show my dead links by collection." "Tag everything I saved last week." The agent answers through Linkwarden's own API, as you, and draws the screen it needs. Nobody wrote a dead-links page. Nobody will have to.

The whole integration is four touched files and a handful of new ones. A route, a registry, a provider in the layout, one config line, and the contract vendo init writes. The interesting part is the walls, because your product will have its own.

Linkwarden speaks next-auth v4, which Vendo's presets cannot read — and Vendo refuses to guess who someone is. The fix is one honest function: the host resolves its own session and hands Vendo the user.

apps/web/app/api/vendo/[...vendo]/route.ts
auth: {
  principal: async (request: Request) => {
    const token = await getToken({ req: request as never });
    if (token?.sub == null) return null;
    return { kind: "user" as const, subject: `user_${token.sub}` };
  },
},

The workspace held two more surprises. The background worker pinned an older ai major than Vendo needs, and the app itself runs zod 4 while half of Vendo's packages expected their own zod 3. Both have one-line fixes now, both are documented, and the second is filed as a bug — because a real product found it and our own demos never could. That is the point of installing into software you didn't write.

The fork is public. Every commit is one wall and its fix, and the diff against upstream is the entire answer to "what does Vendo touch." Start with the walkthrough, or go straight to the fork.