Tool Context
How a tool gets workspace, services, and identity without ctx.identity.
A tool only sees ctx.context. That value is either:
- The agent's
runtimeContext, when it already matches the tool, or - The result of
mapContextat registration, when the tool needs a narrower shape.
There is no ambient caller. If the tool needs workspaceId, put it in context.
Declare what the tool needs
export const lookupCustomer = defineTool({
id: "lookupCustomer",
description: "Read a customer by id",
inputSchema: z.object({ customerId: z.string() }),
outputSchema: z.object({ name: z.string() }),
contextSchema: z.object({
customerStore: z.custom<CustomerStore>(),
}),
execute: async (ctx) => {
return ctx.context.customerStore.read(ctx.input.customerId);
},
});contextSchema is for TypeScript and for the runtime to reject a bad registration. It is not sent to the model.
Same shape as the agent
If runtimeContext is already { customerStore, … } and the extra fields are fine, register the tool directly:
defineAgent({
runtimeContext: async ({ identity }) => ({
customerStore: await stores.forWorkspace(identity.workspaceId),
}),
tools: { lookupCustomer },
});Narrower shape: mapContext
When the agent context is a bag of services and the tool only wants one:
defineAgent({
runtimeContext: async ({ identity }) => ({
workspaceId: identity.workspaceId,
stores: await loadStores(identity.workspaceId),
}),
tools: {
lookupCustomer: {
tool: lookupCustomer,
mapContext: ({ runtimeContext }) => ({
customerStore: runtimeContext.stores.customers,
}),
},
},
});mapContext also receives identity and clientData. Use that when the tool's context should include a tenant id the agent bag does not already have:
mapContext: ({ runtimeContext, identity }) => ({
customerStore: runtimeContext.stores.customers,
workspaceId: identity.workspaceId,
}),Registering a context tool without a compatible agent context is a type error. Dynamic tool maps fail at resolution before the model sees the tool.
What belongs where
| Put it in | Examples |
|---|---|
identity | userId, workspaceId — ids only |
runtimeContext | DB handles, permissions, "today" |
ctx.context | Exactly what this tool's execute needs |
clientData | Open document, current view — untrusted |
Do not put records on identity. Look records up in runtimeContext so they stay current. See Identity.