Direct answer
Vercel AI SDK Agent Receipts
Add verifiable receipts to Vercel AI SDK tool calls and every step whose tool calls run through Zambo leaves a record anyone can check. The route is the SDK's own MCP support: create an MCP client pointed at the Zambo MCP at https://zambo.dev/mcp, pass its tools into generateText or streamText, and close the run with one workflow receipt. Capture happens server side when the call runs, outside the agent's control, so a claim with no receipt behind it is visible as a gap instead of being smoothed over by the final answer. Zambo is the verifiable work layer for AI, and this page wires it into a TypeScript agent.
Updated November 10, 2026.
Install: the MCP route
No Zambo package is required for this route. A package route exists too (the zambo npm package ships an AI SDK export; the sibling guide covers it), but the MCP route below needs no Zambo install at all. The AI SDK ships MCP client support in the @ai-sdk/mcp package: createMCPClient connects to a remote MCP server over HTTP, and client.tools() returns a tools object in exactly the shape generateText and streamText already accept. Point that client at Zambo and every tool call the model makes through it returns its result plus a verifiable receipt, published at a public https://zambo.dev/run/{id} URL.
npm install ai@^6 @ai-sdk/mcp@^1 @ai-sdk/openai@^3
import { createMCPClient } from "@ai-sdk/mcp";
const mcpClient = await createMCPClient({
transport: {
type: "http",
url: "https://zambo.dev/mcp",
},
});
const zamboTools = await mcpClient.tools();
Your local tools keep working beside them. A tool you define with the SDK's tool() helper, with a Zod inputSchema and an execute function, runs in your own process and gets no receipt, because Zambo never sees the call. A tool loaded from the MCP client runs at the Zambo endpoint, and that is the call that comes back receipted. Put the work you need to prove, lookups, writes, checks, payments, on MCP tools; keep purely local formatting helpers as local tools.
One lifecycle note from the SDK docs: an MCP client holds a live connection, so close it when the run ends. In a streamText route handler, the documented place is the onFinish callback or a try/finally around the work; in a generateText script, close it after the call resolves.
Wire the agent's tools through Zambo
The Zambo MCP at zambo.dev/mcp carries 153 tools total, 37 on the default surface, and every call through it returns its result plus a verifiable receipt, captured server side at execution. The record is made by the layer that ran the call, so the agent never gets to edit its own history. The pattern is the one described in MCP server receipts: per-call receipts answer what the agent did, in the order it did it.
import { generateText, stepCountIs } from "ai";
import { openai } from "@ai-sdk/openai";
const { text, steps } = await generateText({
model: openai("gpt-4o"),
tools: { ...zamboTools },
stopWhen: stepCountIs(10),
prompt: "Research this account and save a summary I can hand to a client.",
onStepFinish: ({ toolCalls, toolResults }) => {
for (const result of toolResults ?? []) {
console.log(result.toolName, result.output);
}
},
});
await mcpClient.close();
The SDK mechanics here are the documented ones. generateText runs the tool loop for you: the model calls a tool, the SDK executes it, and the result feeds the next step until a stop condition fires. stopWhen: stepCountIs(10) caps the run at ten steps. onStepFinish fires after each step with that step's tool calls and tool results, which is where you collect the receipt links as they land. The same tools object works unchanged in streamText when the answer needs to stream to a UI. Two properties do the receipt work: capture happens when the call executes at the endpoint, not when somebody later exports a log, and each receipt states its own limit plainly, describing what the endpoint recorded and observed rather than claiming an outside outcome it did not observe.
Make the first call a search, under your label
A demo tour is not an onboarding. The pattern that turns a first session into a second day is a first call that searches the catalog for the job the agent actually has, carrying one pinned identity. Zambo tools accept a caller label and a session id as call arguments; usage is counted under that label, and limits and any pass attach to it. With MCP tools the model passes arguments the same way it passes any other tool input, so instruct the agent in its system prompt to search first and to carry the label on its calls:
const { text } = await generateText({
model: openai("gpt-4o"),
tools: { ...zamboTools },
stopWhen: stepCountIs(10),
system:
"Start by calling capability_search for the job in your own words. " +
"Pass _caller_label 'your-app-or-project-name' and a stable " +
"_session_id on every Zambo tool call in this run.",
prompt: "the job you need done, in your own words",
});
Day two then starts by reading the same label back: the receipts, memory, and continuity saved under it are still there, and picking up a job in another AI is always free, so the second session proves continuity instead of starting cold.
Check the receipts
Every receipt lives at a public URL anyone can open, and checking one is free at zambo.dev/verify with no signup: paste the receipt link or ID and the verifier recomputes the commitment from the saved bytes and compares it with the commitment fixed when the call ran. A match means the saved record is the record made at execution. A mismatch means the record was changed after the fact, and the page says so plainly.
That gives the agent's owner an acceptance check with teeth, the Walk-Away Test: set the agent a countable multi-step job, walk away, and on return read the record before the summary. Claimed steps versus recorded steps is the whole audit. A step an agent claims but never ran has no receipt to point to.
Close the run with one workflow receipt
When the run finishes, call workflow_close through the same MCP tools. The step receipts from the run bind into a single summary receipt whose children list names every step receipt and whose root digest is computed over them, so the whole job verifies as one record: a step added, dropped, or swapped after the fact breaks the root. Per-call receipts answer what this step did; the closed record answers what the agent did, in full, and it is the link you hand a client or auditor. Need the job continued somewhere else instead? A handover moves the job, with its record, to another AI, and picking it up there is always free.
Cost stays small either way. The free tier gives you 20 calls plus 1 wrap-up free every day. A Day Pass is $0.99 one time and covers unlimited calls for 24 hours. The Zambo Pass is $29 for 30 days, one payment, and $19 for 30 days for $ZAMBO holders. A Lifetime Pass is $250, one payment for good. Humans pay by card or PayPal; agents pay USDC on Base via x402. Checking stays free for anyone you hand a receipt to.
Honest limits
A receipt proves the saved result was not changed since it was saved. It does not prove the agent's output was correct, the plan was good, or an outside outcome happened that the endpoint did not observe. It settles what ran, what it was given, and what came back, in a form the agent's owner does not have to take on trust. Judge the work itself against that record. Local tools defined with tool() and an execute function in your own process are also outside this record: only calls that actually pass through the Zambo MCP are receipted.
Frequently asked questions
How do I add execution receipts to a Vercel AI SDK agent?
Route the agent's tool calls through the Zambo MCP at https://zambo.dev/mcp. Create an MCP client with createMCPClient from @ai-sdk/mcp, load its tools with client.tools(), and pass those tools into generateText or streamText alongside any local tools you define with tool(). Every call the model makes through the MCP runs server side at Zambo and returns its result plus a verifiable receipt at a public https://zambo.dev/run/ URL. At the end of the run, call workflow_close through the same MCP connection so the step receipts bind into one chained record. No Zambo package is required for this route; the MCP connection is the integration.
Can I verify what each step of my AI SDK agent did?
Yes, step by step. The AI SDK already splits a run into steps: each step carries its tool calls and tool results, and onStepFinish fires after each one. When those tool calls go through the Zambo MCP, every call also gets its own receipt: what the endpoint was given, what it recorded and observed coming back, a timestamp, and a SHA-256 commitment fixed at execution, published at a URL anyone can fetch. Recompute the commitment from the receipt's saved bytes; a match means the saved record is the record made when the call ran. A step the agent claims but never ran has no receipt behind it, and that gap is visible in the record instead of hidden in the final text.
Do AI SDK tool results come with proof?
Not by default. generateText and streamText hand you the text, the steps array, and your own logs, and all of those are records your own process controls: a tool result can be edited, trimmed, or regenerated later and nothing in the SDK marks the change. Proof appears when the call is executed by a layer outside the agent's control and the result is committed under a hash at execution time: the result bytes saved as recorded, a digest over them, and a public URL where anyone can fetch the record and recompute the digest. That is the record a Zambo MCP call adds. It proves the saved result was not changed since it was saved; whether the result was correct remains a judgment the receipt does not make for you.
What does a Vercel AI SDK run receipt contain?
One receipt per MCP tool call, in the AER-1 format: the tool name, the arguments the endpoint was given, the result the endpoint recorded and observed, a timestamp, and the SHA-256 commitments that make the record checkable by recompute. Calling workflow_close at the end of the run adds a summary receipt whose children list names every step receipt and whose root digest is computed over them, so the whole run verifies as one record. AER-1 is an open IETF Internet-Draft, currently draft -26, so the format is public text, not a vendor schema.
What does it cost to receipt a Vercel AI SDK run?
The free tier gives you 20 calls plus 1 wrap-up free every day, and picking up a job in another AI is always free, so you can wire the MCP client and see real receipts before paying anything. A Day Pass is $0.99 one time and covers unlimited calls for 24 hours. Ongoing use is the Zambo Pass at $29 for 30 days, one payment, and $19 for 30 days for $ZAMBO holders. A Lifetime Pass is $250, one payment for good. Checking a receipt is always free at https://zambo.dev/verify/ with no signup, so clients and auditors never need a plan to check your agent's work.
Run it on a record instead
Reading about the record is one thing; having it under your own work is the point. Work run through the Zambo MCP endpoint at zambo.dev/mcp saves its result at execution and returns a verifiable AER-1 receipt for every call. The Day Pass is $0.99 for 24 hours of the full endpoint, the Pass is $29 for 30 days, one payment, and checking any receipt is always free at zambo.dev/verify.
Related
- How to add execution receipts to a LangChain agent
- How to add execution receipts to a CrewAI crew
- How to add execution receipts to an Agno agent
- How to add execution receipts to a Semantic Kernel agent
- How to add execution receipts to a Haystack pipeline
- Vercel AI SDK and Zambo: agent identity for TypeScript agents
- MCP server receipts: verifiable records for MCP tool calls
- The walk-away test: set your agent a job, walk away, then read the record
- How to verify an AER-1 receipt
- Verify a receipt right now
Proof works best when it travels with the work itself. The AER-1 badge kit turns verifiable receipts into an embeddable badge for project pages, docs, and profiles, so anyone who sees the claim can reach the check in one click.