Skip to main content
Vendo mints no identity of its own. You hand it your sign-in, and the subject it resolves scopes everything that request touches.
1

Hand your auth to createVendo

One key. The preset decodes the session already in the request and reads its own provider’s environment variable for the secret.
subject is the whole model, so use the immutable id from your own tables — never an email or a username someone can change.auth is one door with two spellings. A preset is a function that returns the object above, so anything a preset fills you can also write by hand — and every other identity seam is a sibling key in the same object:
  • principal — who is asking. The only required one.
  • facts — what you assert about them, rendered as the prompt’s [User] block (Context).
  • pools — shared meters their usage counts into (Limits).
  • memberships — their orgs and teams (Orgs).
  • actAs — how to mint scoped credentials for away runs.
  • oauth — how the MCP door reads that same session (Outside agents).
Spread a preset to keep its work and change one member — this is how you serve logged-out visitors without giving up the preset:
vendo init picks the preset off your package.json and writes this line for you. --auth authJs|clerk|supabase|auth0|jwt|none picks it without the prompt (vendo init).
2

Share the resolver with your own routes

Your own agent loop or surface has to land on the same subject the wire does. Hoist auth so both read one instance, and export its resolver beside vendo.
lib/vendo.ts
A hand-written door hoists identically — const auth = { principal: … } — so these three lines are the same either way. Your route imports one answer:
app/api/chat/route.ts
Tell vendo init you bring your own agent loop and it writes both lines for you.
3

Sign in and ask for something only your account can see

Sign in to your own app as a real user, open the panel, and ask:
The agent reaches your API as that person, so the answer is theirs — and so is every thread, app, and grant the turn creates.

Good to know

  • Your loop and your wire route have to resolve the same subject. A mismatch has no error; the embed just polls a screen it will never be shown.
  • Top-level principal, actAs, and oauth are deprecated aliases. They still work and will keep working through this major, but they are one seam each with nowhere to grow — auth is the key that holds all six. Mixing the two shapes throws at composition, and so does auth beside the top-level memberships seam.
  • The vendo: namespace is reserved. A resolver that returns one of those subjects is refused at the wire — vendo:webhook:<source> and vendo:org:<orgId> are minted by Vendo itself.
  • null refuses the request and the chrome goes quiet until a full page load — dispatch new Event("vendo:identity-changed") if you sign users in without one. Serve logged-out visitors with an ephemeral: true principal (Your users).
  • next-auth v4 is not supported. Its cookie names and JWE derivation are structurally unreadable here — move to v5, or stay on --auth none until you do.