vendo sync writes that file
by reading the API you already have — no server starts, and no code of yours
runs. Only what the file lists reaches your API.
1
Declare the source
Four extractors run in a fixed order — OpenAPI, tRPC, Next.js server actions,
then the route scan — and each skips itself when your app has nothing for it.
Most stacks need nothing added at all.
- OpenAPI — the highest-leverage file you can add, because it is what gives
every tool its parameter names, types, and output shape. Put an
openapi.jsonat your app root;openapi.yaml,public/openapi.json, and a copy underdocs/are read too, and the spec never has to be served. - tRPC — nothing to install. Sync sees
@trpc/serverin your dependencies and reads each router with the TypeScript compiler. The.input()schema is the declaration, and a mutation gradeswrite. - Server Actions — sync sees
nextin your dependencies and reads every exported"use server"function. Annotate the parameter, withz.infer<typeof Schema>or a plain type, and its shape comes across. - Routes — nothing to declare. The route scan always runs and finds your
handlers under
app/**/route.tsandpages/api/**. Add the OpenAPI spec when you want their shapes too. - By hand — for the capability that has no route to read: a calculation, a
vendor SDK, three of your services stitched together. The zod schema becomes
both the JSON Schema the model is shown and the parse that runs before
execute, so the two can never drift apart.
zod 4 shapes only. On zod 3.25 or later, import from
zod/v4. On zod 4,
the plain zod import is already the right shape.2
Run npx vendo sync
vendo init also hooks sync into predev
and prebuild in your package.json, so from here it runs on its own.3
Read the diff
Each tool arrives in
.vendo/tools.json, a tracked file — so a new capability
shows up as a reviewable change in git. Every entry carries the same fields..vendo/tools.json
description is written for the model: what the tool does for the user, not a
restatement of the path. risk is what the guard reads before the call.
binding is where the call lands — the runtime executes from it without
re-reading your spec.4
Ask the agent to use one
Open your surface and ask for the thing in plain language.
Delete invoice INV-2032.The agent picks
host_deleteInvoice, the guard reads its destructive grade
and puts an approval card in front of the user, and the call lands on your own
API as the signed-in user. One audit line, either way.Good to know
- Extraction grades from protocol facts only:
DELETEisdestructive, a tRPC mutation is at leastwrite, and a tool’s name decides nothing. Everything else landsungraded, which the guard asks about on every call. - The AI pass then reads the handler behind each tool and writes what it finds
to
.vendo/judgments.json. It runs on whatever credential you already have — Claude Code, the codex CLI, or your Vendo Cloud key. .vendo/tools.jsonis machine-authored and regenerated wholesale on every sync, so never hand-edit it. Corrections live in.vendo/overrides.json, which sync never touches.- Tools from your API are named
host_*. Vendo’s own —vendo_make,vendo_automate, and the rest — arevendo_*, and they always ride along. .vendo/overrides.jsonis the last word: re-grade a tool, make it confirm every run, hide it, or bundle a short sequence into one compound tool. See tool overrides.