Use this file to discover all available pages before exploring further.
Agent tools are functions that Notion Custom Agents can call. Use a tool when an agent needs to look up external data, call your own service, perform an action that is not built into Notion or available through MCP, or apply custom validation that an MCP server does not provide.This guide shows you how to add a tool to a worker, define its inputs, test it locally, and deploy it.
The first argument, "lookupCustomer", is the tool key. Use it when you run the tool from the CLI.Choose a key that is stable and specific. If you rename a tool key, existing agent configuration that refers to the old key needs to be updated.
The title and description help Notion Custom Agents and users understand the tool. Keep the title short and write the description as an instruction boundary: what the tool does, and when it should be used.
worker.tool("createSupportTicket", { title: "Create Support Ticket", description: "Create a support ticket when the user asks to escalate an issue to the support team.", // ...});
Avoid descriptions that are too broad, such as “Run support operations”. A narrow description makes the tool easier for the agent to choose correctly.
Use the j schema builder to define the values your tool accepts. The builder creates a JSON Schema and gives TypeScript types to the execute input. See the Schema and builders reference for all available types.
worker.tool("searchTickets", { // ... schema: j.object({ query: j.string().describe("The search query."), limit: j .number() .describe("The maximum number of results to return.") .nullable(), status: j.enum("open", "closed").describe("The ticket status to search."), }), // ...});
Use .describe() on every field. Field descriptions tell the agent what each value means.Use .nullable() for optional fields:
worker.tool("searchTickets", { // ... schema: j.object({ query: j.string().describe("The search query."), limit: j .number() .describe("The maximum number of results to return.") .nullable(), }), // ...});
The schema builder marks object properties as required and sets additionalProperties: false. Use .nullable() instead of omitting a property from the schema when a value is optional.
If a tool only reads data and has no side effects, set readOnlyHint:
worker.tool("previewAccountDeletion", { title: "Preview Account Deletion", description: "Inspect what would be affected if an account were deleted, without deleting or changing anything.", // ... hints: { readOnlyHint: true }, // ...});
Read-only tools are safe to call repeatedly and can be auto-executed under the default policy. Tools without this hint are treated as write tools, so the Custom Agent will ask for permission from the user before executing the tool unless the agent’s settings change that behaviour.
The second argument to execute is a context object. Use context.notion to call the Notion API with the worker’s authenticated Notion client. The client has the same permissions as the Custom Agent running the tool:
For external APIs, store credentials as worker secrets and read them from process.env. For APIs that require user authorization (GitHub, Google, Salesforce), use OAuth instead.For more on context.notion, see Using Notion API from a worker.
The Workers runtime injects a preauthenticated Notion SDK client when your
tool runs in Notion, but that client is not available during local execution.
When testing locally, we recommend setting NOTION_API_TOKEN to a
personal access token in your
.env file, which the SDK uses to create the client.
If you do not want to load a .env file, pass --no-dotenv:
When the tool works as expected, add it to a Notion Custom Agent from the agent’s tool configuration.See the CLI command reference for all ntn workers exec flags and options.