cd /news/developer-tools/learn-ai-sdk-7-scoped-tool-context-w… · home topics developer-tools article
[ARTICLE · art-63257] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

Learn AI SDK 7 Scoped Tool Context With a Two-Tool Secret Boundary

Vercel's AI SDK 7 introduces scoped tool context, allowing tools to declare a contextSchema and callers to supply per-tool values through toolsContext. This feature enables a two-tool secret boundary where each tool only receives the secrets it needs, improving security by preventing privilege expansion. A developer demonstrated the concept with lookupOrder and createTicket tools, showing that context validation rejects mismatched or missing secrets before execution.

read3 min views1 publishedJul 17, 2026

Vercel's AI SDK 7 adds scoped tool context: a tool can declare a contextSchema

, while the caller supplies per-tool values through toolsContext

. The purpose is practical—third-party tools do not need to receive every secret or configuration value held by an agent.

Primary source: Vercel, “AI SDK 7 is now available”.

Let's turn that feature into a tiny security exercise. We will create two tools:

lookupOrder

may receive an internal order-service URL;createTicket

may receive a support token;Use a fresh project and pin the versions you actually install in your lockfile:

mkdir scoped-tools && cd scoped-tools
npm init -y
npm install ai zod
npm install -D typescript tsx @types/node

Create demo.ts

:

import { tool } from 'ai';
import { z } from 'zod';

const lookupOrder = tool({
  description: 'Read the status of one order',
  inputSchema: z.object({ orderId: z.string().min(1) }),
  contextSchema: z.object({ baseUrl: z.string().url() }),
  execute: async ({ orderId }, { context }) => ({
    orderId,
    source: new URL(`/orders/${orderId}`, context.baseUrl).toString(),
    status: 'demo-only',
  }),
});

const createTicket = tool({
  description: 'Create a support ticket',
  inputSchema: z.object({ subject: z.string().min(3) }),
  contextSchema: z.object({ supportToken: z.string().min(12) }),
  execute: async ({ subject }, { context }) => ({
    subject,
    accepted: context.supportToken.startsWith('support_'),
  }),
});

const tools = { lookupOrder, createTicket };
const toolsContext = {
  lookupOrder: { baseUrl: 'https://orders.invalid' },
  createTicket: { supportToken: 'support_demo_token' },
};

async function run() {
  const order = await lookupOrder.execute!(
    { orderId: 'A-17' },
    { context: toolsContext.lookupOrder } as never,
  );
  const ticket = await createTicket.execute!(
    { subject: 'Order is delayed' },
    { context: toolsContext.createTicket } as never,
  );
  console.log(JSON.stringify({ order, ticket }, null, 2));
}

run().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

The exact execution callback types may evolve with SDK releases, so use the current AI SDK 7 documentation and your lockfile as the source of truth. The important shape is the boundary: each context object is validated for one tool.

Run it:

npx tsx demo.ts

Expected output is shaped like:

{
  "order": {
    "orderId": "A-17",
    "source": "https://orders.invalid/orders/A-17",
    "status": "demo-only"
  },
  "ticket": {
    "subject": "Order is delayed",
    "accepted": true
  }
}

No network request is made; this lesson tests data flow, not an external service.

Now deliberately provide the wrong context:

const wrong = { supportToken: 'support_demo_token' };
const parsed = z.object({ baseUrl: z.string().url() }).safeParse(wrong);
console.log(parsed.success); // false

The desired result is rejection before tool execution. If your orchestration layer silently supplies a global environment object, both tools may see both secrets and the exercise has failed.

Create this table during review:

Tool Allowed context Forbidden context Missing-context behavior
lookupOrder base URL support token reject before call
createTicket support token order URL, database credentials reject before call

process.env

? This is convenient but dangerous:

// Avoid this pattern
execute(input, { context: process.env })

It makes a future tool change an implicit privilege expansion. A package that only needed a weather API key could suddenly read database, deployment, and payment credentials.

Scoped context gives code reviewers a visible capability list. It does not encrypt secrets, prevent a permitted tool from leaking its own token, or replace sandboxing. You still need log redaction, outbound network controls, token rotation, and tests.

Add a sendEmail

tool with only:

{ senderId: string; allowedDomains: string[] }

Then test three cases:

allowedDomains

field fails schema validation.Print structured evidence for all three. Do not use a real email credential.

The broader lesson is that an AI tool is a capability boundary. AI SDK 7 makes that boundary easier to express, but the developer still decides whether the context is narrow, validated, and observable.

Which value in your current agent's global environment would be easiest to remove from most tool calls?

── more in #developer-tools 4 stories · sorted by recency
── more on @vercel 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/learn-ai-sdk-7-scope…] indexed:0 read:3min 2026-07-17 ·