# 策展 · X (Twitter) 🔥🔥🔥

> 作者：Notion Developers (@NotionDevs) · 平台：X (Twitter) · 日期：2026-05-14

> 原始來源：https://x.com/NotionDevs/status/2054591579076403467

## 中文摘要

Notion 推出開發者平台，支援資料同步、工具建置與 Agent 協調。

Notion Developers 宣布推出「Notion Developer Platform」，這套工具組合專為開發者和程式撰寫 Agent 設計，實現同步任意資料來源、建置任意工具，以及協調任意 Agent。平台回應開發者一年來最迫切的呼聲，包括 Markdown API、資料庫檢視 API、個人存取權杖，以及 Notion MCP 提升 91% token 效率等功能，強調無需管理伺服器、無需黏合程式碼，讓團隊和 Agent 獲得完整脈絡以完成工作。

**平台三大核心能力**  
平台聚焦三項關鍵功能：  
- 同步任意資料來源至 Notion 資料庫，例如 Zendesk 工單、Salesforce 記錄或 Postgres 資料。  
- 建置任意工具，透過 Notion Workers 擴展功能。  
- 協調任意 Agent，讓自訂 Agent 發揮更大潛力。  

**資料庫同步功能**  
新推出的資料庫同步功能（由 Workers 驅動）在 Notion 基礎設施上運行，使用者可將任意資料來源同步至 Notion 資料庫。無需自行管理伺服器或撰寫黏合程式碼，為整個團隊及其 Agent 提供必要脈絡。舉例來說，可直接將 Zendesk 工單或 Salesforce 記錄匯入 Notion，讓工作流程更順暢。

**Notion Workers 介紹**  
Notion Workers 是託管的自訂程式碼執行環境，讓使用者無需運行自家伺服器即可擴展 Notion。Workers 可直接連線其他工具的 API，自動化原本的手動移轉，填補工具間的空白。例如，自動處理跨系統資料傳遞，避免手動複製貼上。

**ntn CLI 安裝與部署**  
安裝 ntn CLI，即 Notion CLI，將完整 Notion API 帶入終端機，並支援建置與部署 Workers，適用於人類開發者和程式撰寫 Agent。  

安裝指令：  
```
curl -fsSL https://ntn.dev | bash
```  
Workers 部署至 Notion 沙盒，由 Notion 處理基礎設施，從構想到運行程式碼僅需單一工作階段。平台內建觀測性、OAuth 與速率限制，包含驗證、權限、沙盒、速率限制及跨系統存取，使用者只需專注建置邏輯。

**建置 Agent 工具**  
若喜愛的應用程式缺乏 MCP 伺服器或適當 MCP 工具，使用者可透過 Workers 為自訂 Agent 建置功能，涵蓋 Notion 和 MCP 未提供的邏輯。以程式碼撰寫並部署為 Worker，提供可組合工作流程、類型化 I/O、可重複執行及記錄執行。相較 LLM 推理，這更確定性、更可靠，且 token 成本僅為其一小部分。適用於產生 asset、查詢內部資料，或在其他應用程式採取行動。  

詳細文件：[工具指南](https://developers.notion.com/workers/guides/tools)。  

Workers 工具讓 Agent 避免浪費時間思考工作流程，使用者可自行定義 x → y → z 邏輯，並暴露為單一工具。  

**撰寫 Agent 工具步驟**  
在 `src/index.ts` 中匯入 Worker 與 schema 建構器：  
```typescript
import { Worker } from "@notionhq/workers";
import { j } from "@notionhq/workers/schema-builder";

const worker = new Worker();
export default worker;
```  

使用 `worker.tool` 註冊工具，例如 `lookupCustomer`：  
```typescript
worker.tool("lookupCustomer", {
	title: "Lookup Customer",
	description: "Find a customer by email address.",
	schema: j.object({
		email: j.email().describe("The customer's email address."),
	}),
	hints: { readOnlyHint: true },
	execute: async ({ email }) => {
		const customer = await findCustomerByEmail(email);

		if (!customer) {
			return {
				found: false,
				message: `No customer found for ${email}.`,
			};
		}

		return {
			found: true,
			name: customer.name,
			plan: customer.plan,
			accountUrl: customer.accountUrl,
		};
	},
});
```  
工具金鑰如 `"lookupCustomer"` 需穩定且具體，重命名將影響既有 Agent 配置。  

**工具描述與輸入 schema**  
`title` 保持簡短，`description` 如指令般明確說明工具作用與使用時機，避免過廣描述如「Run support operations」。  

定義輸入 schema 使用 `j` 建構器，產生 JSON Schema 並提供 TypeScript 類型：  
```typescript
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."),
}),
```  
每個欄位使用 `.describe()`，選用欄位加 `.nullable()`，在 `execute` 中明確處理如 `limit ?? 10`。  

**輸出結構與唯讀標記**  
優先回傳結構化物件：  
```typescript
execute: async ({ email }) => {
	const customer = await findCustomerByEmail(email);
	if (!customer) {
		return { found: false };
	}
	return {
		found: true,
		customer: {
			name: customer.name,
			plan: customer.plan,
			accountUrl: customer.accountUrl,
		},
	};
},
```  
預測形狀時加 `outputSchema` 驗證：  
```typescript
outputSchema: j.object({
	results: j.array(
		j.object({
			id: j.string().describe("The ticket ID."),
			title: j.string().describe("The ticket title."),
			url: j.string().describe("A URL for the ticket."),
		}),
	),
}),
```  

唯讀工具設 `readOnlyHint: true`，無副作用、可重複呼叫，且預設政策下可自動執行；無此標記視為寫入工具，需使用者許可。

**呼叫 Notion 與外部 API**  
`execute` 第二參數為 context，使用 `context.notion` 呼叫 Notion API，權限與執行 Agent 相同：  
```typescript
execute: async ({ pageId }, { notion }) => {
	const page = await notion.pages.retrieve({ page_id: pageId });
	return page;
},
```  
外部 API 存憑證於 secrets（`process.env`），使用者授權 API 如 GitHub 用 OAuth。

**本地測試與部署工具**  
本地執行：  
```
ntn workers exec lookupCustomer --local -d '{"email":"ada@example.com"}'
```  
載入 `.env` 預設，可指定 `--dotenv .env.local` 或 `--no-dotenv`。本地無預驗證 Notion SDK，建議設 `NOTION_API_TOKEN` 於 `.env`。  

部署後：  
```
ntn workers deploy
ntn workers exec lookupCustomer -d '{"email":"ada@example.com"}'
```  
成功後於 Agent 工具配置中新增。

**雙向 Webhooks**  
過去 Webhooks 單向：Notion 觸發外部應用程式，現外部應用程式可直接觸發 Notion。詳細文件：[Webhooks 指南](https://developers.notion.com/workers/guides/webhooks)。  

**Webhook 定義與事件物件**  
在 Worker 中定義：  
```typescript
worker.webhook("onExternalEvent", {
  title: "External Event Handler",
  description: "Processes incoming webhook requests",
  execute: async (events) => {
    for (const event of events) {
      console.log("Delivery:", event.deliveryId);
      console.log("Method:", event.method);
      console.log("Body:", event.body);
    }
  },
});
```  
部署後列出 URL：  
```
ntn workers deploy
ntn workers webhooks list
```  
或 `--json` / `--plain`。URL 含唯一 ID 作為共享密鑰，如 `https://www.notion.so/webhooks/worker/{spaceId}/{workerId}/{uniqueWebhookId}/{webhookName}`，視為 secrets，建議內部驗證簽名。  

事件物件包含 `deliveryId`（唯一交付 ID）、`body`（解析 JSON）、`rawBody`（原始字串，用於驗證）、`headers`（小寫）、`method`（POST）。  

**Webhook 請求驗證**  
使用外部提供者簽名秘密驗證，擲 `WebhookVerificationError` 失敗：  
```typescript
import * as crypto from "node:crypto";
import { WebhookVerificationError, Worker } from "@notionhq/workers";

function verifyGitHubSignature(rawBody: string, headers: Record<string, string>): void {
  const secret = process.env.GITHUB_WEBHOOK_SECRET;
  if (!secret) {
    throw new WebhookVerificationError("GITHUB_WEBHOOK_SECRET not configured");
  }
  const signature = headers["x-hub-signature-256"];
  if (!signature?.startsWith("sha256=")) {
    throw new WebhookVerificationError("Invalid GitHub signature");
  }
  const expected = `sha256=${crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex")}`;
  if (signature.length !== expected.length) {
    throw new WebhookVerificationError("Invalid GitHub signature");
  }
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    throw new WebhookVerificationError("Invalid GitHub signature");
  }
}

worker.webhook("onGithubPush", {
  title: "GitHub Push Webhook",
  description: "Handles push events from GitHub repositories",
  execute: async (events) => {
    for (const event of events) {
      verifyGitHubSignature(event.rawBody, event.headers);
      console.log("Verified GitHub event:", event.body);
    }
  },
});
```  
設定秘密：  
```
ntn workers env set GITHUB_WEBHOOK_SECRET=your-secret
```  
5 次連續 `WebhookVerificationError` 後封鎖，重新部署重置。其他錯誤重試至 3 次，成功重置計數器。

**從 Webhook 使用 Notion**  
接收相同 context，`context.notion` 需手動驗證：設 `NOTION_API_TOKEN`（內部整合 token）：  
```
ntn workers env set NOTION_API_TOKEN=secret_xxx
```  
範例建立頁面：  
```typescript
worker.webhook("createPageFromWebhook", {
  title: "Create Page From Webhook",
  description: "Creates a page when an external event is received",
  execute: async (events, { notion }) => {
    const databaseId = process.env.MY_WEBHOOK_DATABASE_ID;
    if (!databaseId) {
      throw new Error("MY_WEBHOOK_DATABASE_ID is not configured");
    }
    for (const event of events) {
      const externalId = typeof event.body.id === "string" ? event.body.id : event.deliveryId;
      await notion.pages.create({
        parent: { database_id: databaseId },
        properties: {
          Name: {
            title: [{ text: { content: `Webhook event ${externalId}` } }],
          },
        },
      });
    }
  },
});
```  

**檢查執行記錄**  
```
ntn workers runs list
ntn workers runs logs <run-id>
ntn workers runs list --plain | grep webhook
```

**外部 Agent API**  
引入「External Agents API」，將任意 Agent（含自建）帶入 Notion。已與 @claudeai、@OpenAI Codex、@DecagonAI、@cursor_ai、@warpdotdev、@cognition、@floraai、@Amplitude_HQ、@console__、@getserval 合作，即開即用。所有 Agent 工作在 Notion 中可見、可審核、可行動，無需跨工具複製脈絡。加入等候名單：[External Agents](https://ntn.so/ext-agents)。

**Agent Activity 功能**  
新「Agent Activity」顯示 Agent 在任務資料庫中的確切活動，一鍵跳至完整聊天線程。解決 Agent 是否卡住的疑慮。

**Notion 作為協調層**  
以 Notion 為協調層，例如 Decagon 工單路由至程式撰寫 Agent，提出修復並迴圈團隊審核，全在 Notion 內。非僅工程師，所有人皆可與 Agent 共事。

**Notion Agent SDK（即將推出）**  
將 Notion Agent 帶入任意應用程式，透過 API 觸發執行（串流回應或非同步輪詢），支援多輪對話線程。可嵌入產品、驅動 Slack/Discord bot，或從其他應用程式啟動非同步工作流程。加入等候名單：[Agent SDK](https://ntn.so/agent-sdk)。  

**直播與文件資源**  
追蹤介紹直播：[直播連結](https://x.com/i/broadcasts/1AJEmOArraYJL)。完整文件索引：[llms.txt](https://developers.notion.com/llms.txt)。後續資源包括 Schema 參考、SDK 文件、Secrets 管理及 Notion API 整合等。此平台強調開發者友好，特別強化 Agent 效率與整合深度，預期大幅提升 Notion 在 Agentic 程式開發生態的地位。

## 標籤

MCP, 新產品, 功能更新, Agent, Notion
