{"slug": "learn-ai-sdk-7-scoped-tool-context-with-a-two-tool-secret-boundary", "title": "Learn AI SDK 7 Scoped Tool Context With a Two-Tool Secret Boundary", "summary": "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.", "body_md": "Vercel's AI SDK 7 adds scoped tool context: a tool can declare a `contextSchema`\n\n, while the caller supplies per-tool values through `toolsContext`\n\n. The purpose is practical—third-party tools do not need to receive every secret or configuration value held by an agent.\n\nPrimary source: [Vercel, “AI SDK 7 is now available”](https://vercel.com/changelog/ai-sdk-7).\n\nLet's turn that feature into a tiny security exercise. We will create two tools:\n\n`lookupOrder`\n\nmay receive an internal order-service URL;`createTicket`\n\nmay receive a support token;Use a fresh project and pin the versions you actually install in your lockfile:\n\n```\nmkdir scoped-tools && cd scoped-tools\nnpm init -y\nnpm install ai zod\nnpm install -D typescript tsx @types/node\n```\n\nCreate `demo.ts`\n\n:\n\n``` js\nimport { tool } from 'ai';\nimport { z } from 'zod';\n\nconst lookupOrder = tool({\n  description: 'Read the status of one order',\n  inputSchema: z.object({ orderId: z.string().min(1) }),\n  contextSchema: z.object({ baseUrl: z.string().url() }),\n  execute: async ({ orderId }, { context }) => ({\n    orderId,\n    source: new URL(`/orders/${orderId}`, context.baseUrl).toString(),\n    status: 'demo-only',\n  }),\n});\n\nconst createTicket = tool({\n  description: 'Create a support ticket',\n  inputSchema: z.object({ subject: z.string().min(3) }),\n  contextSchema: z.object({ supportToken: z.string().min(12) }),\n  execute: async ({ subject }, { context }) => ({\n    subject,\n    accepted: context.supportToken.startsWith('support_'),\n  }),\n});\n\nconst tools = { lookupOrder, createTicket };\nconst toolsContext = {\n  lookupOrder: { baseUrl: 'https://orders.invalid' },\n  createTicket: { supportToken: 'support_demo_token' },\n};\n\nasync function run() {\n  const order = await lookupOrder.execute!(\n    { orderId: 'A-17' },\n    { context: toolsContext.lookupOrder } as never,\n  );\n  const ticket = await createTicket.execute!(\n    { subject: 'Order is delayed' },\n    { context: toolsContext.createTicket } as never,\n  );\n  console.log(JSON.stringify({ order, ticket }, null, 2));\n}\n\nrun().catch((error) => {\n  console.error(error);\n  process.exitCode = 1;\n});\n```\n\nThe 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.\n\nRun it:\n\n```\nnpx tsx demo.ts\n```\n\nExpected output is shaped like:\n\n```\n{\n  \"order\": {\n    \"orderId\": \"A-17\",\n    \"source\": \"https://orders.invalid/orders/A-17\",\n    \"status\": \"demo-only\"\n  },\n  \"ticket\": {\n    \"subject\": \"Order is delayed\",\n    \"accepted\": true\n  }\n}\n```\n\nNo network request is made; this lesson tests data flow, not an external service.\n\nNow deliberately provide the wrong context:\n\n``` js\nconst wrong = { supportToken: 'support_demo_token' };\nconst parsed = z.object({ baseUrl: z.string().url() }).safeParse(wrong);\nconsole.log(parsed.success); // false\n```\n\nThe 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.\n\nCreate this table during review:\n\n| Tool | Allowed context | Forbidden context | Missing-context behavior |\n|---|---|---|---|\n| lookupOrder | base URL | support token | reject before call |\n| createTicket | support token | order URL, database credentials | reject before call |\n\n`process.env`\n\n?\nThis is convenient but dangerous:\n\n```\n// Avoid this pattern\nexecute(input, { context: process.env })\n```\n\nIt 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.\n\nScoped 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.\n\nAdd a `sendEmail`\n\ntool with only:\n\n```\n{ senderId: string; allowedDomains: string[] }\n```\n\nThen test three cases:\n\n`allowedDomains`\n\nfield fails schema validation.Print structured evidence for all three. Do not use a real email credential.\n\nThe 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.\n\nWhich value in your current agent's global environment would be easiest to remove from most tool calls?", "url": "https://wpnews.pro/news/learn-ai-sdk-7-scoped-tool-context-with-a-two-tool-secret-boundary", "canonical_source": "https://dev.to/magickong/learn-ai-sdk-7-scoped-tool-context-with-a-two-tool-secret-boundary-21g", "published_at": "2026-07-17 06:55:27+00:00", "updated_at": "2026-07-17 07:01:40.688292+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "ai-safety"], "entities": ["Vercel", "AI SDK 7"], "alternates": {"html": "https://wpnews.pro/news/learn-ai-sdk-7-scoped-tool-context-with-a-two-tool-secret-boundary", "markdown": "https://wpnews.pro/news/learn-ai-sdk-7-scoped-tool-context-with-a-two-tool-secret-boundary.md", "text": "https://wpnews.pro/news/learn-ai-sdk-7-scoped-tool-context-with-a-two-tool-secret-boundary.txt", "jsonld": "https://wpnews.pro/news/learn-ai-sdk-7-scoped-tool-context-with-a-two-tool-secret-boundary.jsonld"}}