Skip to content
Docs

Pass state to AI SDK tools and agents with context

Use runtimeContext, toolsContext, and contextSchema in the AI SDK to pass tenant data, credentials, and other server-side state through a generation or agent loop without putting it in the prompt.

6 min read
Last updated June 25, 2026

Context lets you pass server-side state through a generation or agent loop without putting that state into the prompt. The AI SDK keeps shared runtime state separate from per-tool state, so an agent can track its own progress while each tool receives only the values it needs. Use context for tenant information, feature flags, session data, request IDs, API credentials, or access tokens, the kind of values that shape how your code runs but that the model shouldn't reason about. runtimeContext carries state for the whole loop, while toolsContext and contextSchema scope state to an individual tool.

In this guide, you'll learn how to:

  • Tell runtimeContext and toolsContext apart, and know when to reach for each
  • Pass shared state through a generation or agent loop with runtimeContext
  • Scope state to a single tool with toolsContext and a contextSchema
  • Keep sensitive values out of telemetry with context filtering

The AI SDK splits context into two layers. runtimeContext is shared across the whole generation or agent loop, and toolsContext holds values scoped to individual tools. Each tool declares the shape of the context it expects, and the SDK validates and passes only that tool's context to it, so one tool can't read another tool's values.

ConceptWhere you set itWhere you read itUse it for
runtimeContextgenerateText, streamText, or a ToolLoopAgent callprepareStep, lifecycle callbacks, step results, and telemetryShared generation or agent state
toolsContextgenerateText, streamText, or a ToolLoopAgent callprepareStep, approval callbacks, and tool context resolutionMap of per-tool context values, keyed by tool name
Tool contextEach tool's toolsContext entry, validated by its contextSchemaThe tool's execute, description function, needsApproval, and input lifecycle callbacksValues needed by one tool

Both layers start from the same generateText, streamText, or ToolLoopAgent call. Runtime context is the shared state for the loop, and you can read or update it in prepareStep between model calls. Tool context works differently. The SDK resolves it from toolsContext into each tool's own validated context before that tool runs, so a tool only ever sees the values meant for it. Telemetry receives a filtered copy of both, which you control with the filters covered below.

Pass runtimeContext when you need shared state for the whole generation or agent loop. The AI SDK doesn't add runtimeContext to the model prompt, so it's a safe place for values that should affect execution without reaching the model. Use it to configure step preparation, track server-side state, or correlate lifecycle events.

app/api/trip/route.ts
import { generateText } from 'ai';
const result = await generateText({
model: 'openai/gpt-5.2',
prompt: 'Help me plan a trip.',
runtimeContext: {
tenantId: 'tenant_123',
plan: 'enterprise',
requestId: 'req_abc',
},
prepareStep: async ({ runtimeContext }) => {
if (runtimeContext.plan === 'enterprise') {
return { temperature: 0.2 };
}
return {};
},
});

prepareStep can return a new runtimeContext. The new value applies to the current step and every step after it, which makes prepareStep the right place to update agent state between turns of the loop.

Use toolsContext for values that belong to a specific tool. Each tool declares the context it expects with contextSchema, and the AI SDK validates the matching toolsContext entry and passes it to the tool as context. A tool receives only its own context, not the full toolsContext map, so an untrusted or third-party tool can't read another tool's credentials.

app/api/weather/route.ts
import { generateText, tool } from 'ai';
import { z } from 'zod';
const weatherTool = tool({
description: 'Get the weather in a location',
inputSchema: z.object({
location: z.string(),
}),
contextSchema: z.object({
weatherApiKey: z.string(),
defaultUnit: z.enum(['celsius', 'fahrenheit']),
}),
execute: async ({ location }, { context }) => {
return fetchWeather({
location,
apiKey: context.weatherApiKey,
unit: context.defaultUnit,
});
},
});
const result = await generateText({
model: 'openai/gpt-5.2',
tools: { weather: weatherTool },
toolsContext: {
weather: {
weatherApiKey: process.env.WEATHER_API_KEY!,
defaultUnit: 'fahrenheit',
},
},
prompt: 'What is the weather in San Francisco?',
});

When at least one tool declares a contextSchema, toolsContext becomes required for the tools that need it. Tool description functions receive the same typed context before each model call, so a tool's description can change with its current context. Treat tool context as immutable inside a tool. To change it between steps, inspect the previous step in prepareStep and return an updated toolsContext.

Context often contains values that are useful within your application but shouldn't be sent to telemetry providers. Use telemetry.includeRuntimeContext to send selected top-level runtime context properties, and telemetry.includeToolsContext to send selected top-level tool context properties per tool.

app/api/support/route.ts
import { ToolLoopAgent, tool } from 'ai';
import { z } from 'zod';
const customerLookup = tool({
description: 'Look up customer account details',
inputSchema: z.object({
customerId: z.string(),
}),
contextSchema: z.object({
apiKey: z.string(),
region: z.string(),
}),
execute: async ({ customerId }, { context }) => {
return lookupCustomer({
customerId,
apiKey: context.apiKey,
region: context.region,
});
},
});
const agent = new ToolLoopAgent({
model: 'openai/gpt-5.2',
tools: { customerLookup },
});
const result = await agent.generate({
prompt: 'Check whether customer cust_123 is eligible for priority support.',
runtimeContext: {
requestId: 'req_abc',
tenantId: 'tenant_123',
userId: 'user_123',
},
telemetry: {
includeRuntimeContext: {
requestId: true,
},
includeToolsContext: {
customerLookup: {
region: true,
},
},
},
toolsContext: {
customerLookup: {
apiKey: process.env.CUSTOMER_API_KEY!,
region: 'us',
},
},
});

With this configuration, telemetry receives the customerLookup context with only region, and the runtime context with only requestId. The apiKey, tenantId, and userId values never leave your application.

Note: Context filters only affect telemetry integrations, including OpenTelemetry. Tool execution, lifecycle callbacks, and returned results still receive the full context values.

Filtering is shallow and applies only to top-level properties. When you omit telemetry.includeRuntimeContext, the SDK sends no runtime context properties; when you set it, the SDK sends only the properties you mark true. The same rule applies to telemetry.includeToolsContext. Use these filters to reduce telemetry exposure, not as a general security boundary.

Match each kind of state to where it's read:

  • Runtime context: Use runtimeContext for state shared by the whole generation or agent loop, such as request metadata, tenant settings, feature flags, or agent progress.
  • Tool context: Use toolsContext and contextSchema for values a single tool needs, such as API keys, scoped clients, user permissions, or default tool settings.
  • Prompt messages: Put information the model should reason about or mention in its answer into the prompt, not into context.
  • Telemetry filters: Use telemetry.includeRuntimeContext and telemetry.includeToolsContext to control what context reaches your telemetry provider.

Use this table to find where each kind of context is available as you build:

LocationruntimeContexttoolsContextTool context
prepareStepRead and updateRead and updateNot directly
Tool execute and description functionsNot passed directlyNot passed directlyRead the tool's validated context
Tool approval callbacksReadRead in generic callbacksRead as toolContext in per-tool callbacks
Step results and finish callbacksRead per-step or final stateRead per-step or final stateAvailable through toolsContext entries
TelemetryFiltered by telemetry.includeRuntimeContextFiltered by telemetry.includeToolsContextFiltered by telemetry.includeToolsContext
  • Read Tools and tool calling to define tools, input schemas, and multi-step tool calls.
  • See Building agents to use ToolLoopAgent and prepareStep for managing context across steps.
  • Explore Lifecycle callbacks to hook into each step where runtime context is available.
  • Check the Telemetry guide to configure tracing and control what context is recorded.

Was this helpful?

supported.