The definition is static, the caller is not
One Mastra agent definition serves every user, sovendoMastraTools takes no principal. Each call reads one off Mastra’s request context, and a vendo_* call that finds none fails closed.
app/api/chat/route.ts
resolvePrincipal is the lib/vendo.ts export from the quickstart, unchanged here.
A context you build and never pass is a context the tools never see. Skip the params.requestContext assignment and every vendo_* call fails, which reads at first glance like a broken install.
Set VENDO_SESSION_KEY on the same context to carry your own session id into the audit trail. Leave it out and each call mints one.
vendoMastraTools returns a Promise, which is why the agent takes the tools-as-function form.
src/mastra/agents/your-agent.ts
Warm the store
Everyvendo_* call runs the schema check before it executes, so a guarded tool that fires before any wire request still works. Call ensureSchema once at module scope to move that one-time cost off the first turn.
src/mastra/index.ts
Render the parts
Mastra streams tool calls asdynamic-tool or as tool-<name>, depending on how the tool was declared. Match both.
Where that match lives is yours. The path below is a name, not a contract — only your own chat imports it, so a components/ directory you do not have is a directory you do not need. examples/mastra-agent inlines the same branch in src/app/page.tsx instead.
components/vendo-part.tsx

Open input schemas ride a bridge
Extraction emits an open object schema for a route whose body shape it cannot type. Mastra’s provider compat layers hard-close every object node, so an open schema reaches the model as “this tool takes no arguments”, and the model then calls it with{}.
The shim routes those tools through one declared args property instead, a JSON object or that object as a JSON string, and unwraps it before the guard. Nothing on your side changes.
The model pin
Multi-turn tool use with GPT-5 reasoning models breaks on history replay. Mastra’s memory drops the Responses API’s reasoning items and the second turn errors. mastra-ai/mastra#9005 is closed, but it still reproduces on@mastra/core 1.51.0, retested 2026-07-20, so the example pins openai/gpt-4.1-mini.
Your agent’s model is your call. Vendo’s own turns take a seat of their own, filled through the Cloud gateway on your VENDO_API_KEY: Model credentials.
The full example
examples/mastra-agent is the stock create-mastra weather starter, fronted with Next.js per Mastra’s guide, with this diff applied. Every added line sits between --- vendo and --- /vendo markers, about sixty of them in total.