Workers > sync:ZendeskChecking Zendesk...

Data Scout > tool:QueryConstructing query...

Claude CodeReceived user request...

## Sync any data source into Notion.

Continuously upsert external records into a Notion Database with Workers, a declarative schema, and a persistent cursor.

zendeskSync.ts [See example](https://github.com/makenotion/notion-cookbook/tree/main/workers/zendesk-sync)

```typescript
import { Worker } from "@notionhq/workers";

const worker = new Worker();

const tickets = worker.database("tickets", {
  type: "managed",
  initialTitle: "Support Tickets",
  primaryKeyProperty: "Tickets",
  schema: { properties: {
    "Tickets": Schema.title(),
    "CSAT score": Schema.select([{ name: "Very satisfied" }, ...]),
    "Feature tags": Schema.multiSelect([{ name: "Account access" }, ...]),
  }},
});

worker.sync("ticketsSync", {
  database: tickets,
  schedule: "5m",
  execute: async () => ({
    changes: (await zendesk.tickets.list()).map(t => ({
      type: "upsert" as const,
      key: t.id,
      properties: {
        "Tickets": Builder.title(t.subject),
        "CSAT score": Builder.select(t.csat),
        "Feature tags": Builder.multiSelect(...t.tags),
      },
    })),
  }),
})
```

```
Workers > sync:ticketsSync
Syncing 5 tickets...
```

### Support Tickets

| Tickets                           | CSAT score        | Feature tags        |
|-----------------------------------|-------------------|---------------------|
| Help setting up SSO              | Very satisfied     | Enterprise          |
| Invoice updated with correct details| Satisfied          | Billing & subscriptions |
| Login fails after password reset   | Dissatisfied       | Account access      |
| Import mapped correctly with help   | Satisfied          | Imports & exports   |
| Request: Slack integration          | Neutral            | Integrations        |
| New page                           |                   |                     |

## Build any tool for your agents.

Write custom tools for Notion Agents that generate assets, query live data, and hit any API.

presentationTool.ts [See example](https://github.com/makenotion/notion-cookbook/tree/main/workers/powerpoint-creator)

```typescript
worker.tool("createPresentation", {
	title: "Create Presentation",
	description:
		"Reads a Notion page and creates a PowerPoint presentation from its content. Each heading becomes a new slide. The generated .pptx file is uploaded to the bottom of the page.",
	schema: j.object({
		pageId: j.string()
	}),
	execute: async ({ pageId }, { notion }) => {
		// Fetch page content as markdown and parse into slides
		const pageTitle = await getPageTitle(notion, pageId);
		const markdown = await getPageMarkdown(pageId);
		const slides = groupMarkdownIntoSlides(markdown, pageTitle);

// Build the .pptx file
		const filename = `${pageTitle}.pptx`;
		const buffer = await buildPresentation(pageTitle, slides);

// Upload to Notion and append to the page
		await uploadToNotion(notion, pageId, filename, buffer);

return `Created presentation \"${pageTitle}\" with ${slides.length + 1} slides (1 title + ${slides.length} content) and added it to the page.`;
	},
});
```

```
Workers > tool:createPresentation
Running tool "createPresentation"...
```

Query any data warehouse

queryRevenueTool.ts [See example](https://github.com/makenotion/notion-cookbook/tree/main/workers/snowflake-query)

```typescript
worker.tool("queryRevenue", {
	title: "Query Revenue",
	description: "Run a SQL query against the deals warehouse table.",
	schema: j.object({
		query: j
			.string()
			.describe("e.g. SELECT SUM(amount) AS revenue WHERE region = 'North America'"),
	}),
	execute: async ({ query }) =>
		snowflake.query(query.replace(/(\s+WHERE|$)/i, " FROM deals$1")),
	});
```

```
Workers > tool:queryRevenue
```

## Trigger Notion workflows from anywhere.

Listen for incoming webhooks from any app, then run workflows with Notion Agents, pages, databases, and external APIs.

PR merged

Customer canceled

Candidate signed offer

Contract signed

Issue escalated

## All of this, on a hosted runtime.

Workers are isolated sandboxes managed by Notion, so the code behind your syncs, tools, and workflows runs on our infra instead of your servers.

```
$ ntn deploy worker
[build] Deploying...
[build] Uploading to Notion...
[build] Worker updated...

Capabilities:
  tool  queryCustomers
  tool  moreOfficeSnacks
  sync  linearTickets
```

Alpha

## Bring your favorite agents into Notion.

Use external agents like Claude, Cursor, Decagon, or one you’ve built, in a shared interface for your team and agents.

### Mention

Collaborate with agents like teammates. @mention them in any page, comment, or chat with them directly.

### Assign

Hand off work to your agents from any task, or trigger them in parallel.

### Orchestrate

Watch agents think, call tools, and act across Notion and other apps with your review and approval when it matters.

### BYO Agent

Bring your in‑house agents into Notion with the External Agents API. Notion gives them triggers, tools, and permissions so they show up as first‑class collaborators on all the same surfaces.

```
POST /sessions/{id}
POST /sessions/{id}/messages
GET  /sessions/{id}/events
```

## CLI, API, MCP, SDK — LFG.

### Notion CLIBeta

Let coding agents use token‑efficient commands to build and deploy syncs and tools to our Workers runtime.

### Notion API

Turn docs into Markdown and build internal tools with PATs or shared connections.

### Notion MCP

Search, read, and edit pages and databases with up to 91% fewer tokens.

### Notion Agent SDKAlpha

Bring your Agents into any app. Trigger runs via API, keep multi-turn threads, and stream responses in real time.

```typescript
import { NotionAgentsClient } from "@notionhq/agents-client";

const client = new NotionAgentsClient();
const agent = await client.agents.agent(id);

await agent.chat({
  message: "Hello, World!"
});
```

## Any data. Any tool. Any agent. All in Notion.
