見出し画像

Notion 3.5 Developer Platform リリースから5日で「Slackに議事録を投げるだけで全社のタスクが自動で立ち上がる」を実装してみた

Worker × Custom Agent × Slack 直結連携の壁と、その超え方 ── 実装中に踏み抜いた13個の落とし穴を完全公開

はじめに:何を作ったか

2026年5月18日、私は次のシステムを動かす実装を完成させました:

  • Slack の #meeting -notes チャンネルに議事録を投稿する

  • 30秒待つと、Notion の L3 Knowledge Base に議事録ページが自動作成される

  • さらに1分待つと、議事録から ToDo が抽出され、L1 My Tasks に複数件のタスクが Source=会議 で起票される

  • L1 タスクの担当者・期限・優先度・関連プロジェクトは、すべて Claude が文章から推定して埋める

これは 2026年5月13日にリリースされた Notion 3.5 Developer Platform(Notion CLI / Workers / Custom Agents 統合)の機能をフル活用した実装で、リリースから5日で完成しました。

なぜこんなものを作ったのか?
AIコンサル業を営む立場として、**「実装まで知っている人間が提案している」**という事実を商談の場で証明する必要があったからです。AIを語るのに自分の業務管理がExcelとSlackで散らかっていたら、誰も発注しません。

この記事では、その実装の全工程と踏み抜いた13個の落とし穴を公開します。Notion 3.5 で Worker + Custom Agent を組み合わせて何か作ろうとしている方への、5日分の時間短縮材料になればと思います。

完成形:3層のAIが連鎖して動く Agent Orchestra

最終的なアーキテクチャは以下のようになりました:

[1] Slack #meeting-notes チャンネル
       ↓ メッセージ投稿
[2] Notion Custom Agent「Meeting Splitter」
    (Slack直結トリガー)
       ↓ 自動発火
[3] L3 Knowledge Base にページ作成
    (Type=議事録、本文=Slackメッセージ全文)
       ↓
[4] 同じ Custom Agent が本文から ToDo を抽出
       ↓
[5] L1 My Tasks に複数タスク起票
    (Source=会議、Assignee/Due/Priority/Project はClaudeが推定)

これと並行して、外部メール(Gmail)からタスクが起票される別ルートも Worker で実装しています:

Gmail @task ラベル付与
   ↓
gmail-task-router Worker(webhook)
   ↓
L1 My Tasks に Source=メール で起票
   ↓
Custom Agent「Ticket Router」が発火
   ↓
Project と Phase を自動推定して書き戻し

つまり、入口は Slack でも Gmail でも、出口(L1 My Tasks)は常に同じ。これが商談で見せると圧倒的に効きます。

全体アーキテクチャ:4DB + 2Worker + 2Agent

Notion 側のDB構造(4層モデル)

L1〜L4 が双方向リレーションでつながっているのが肝で、「タスクを開けば、所属プロジェクトと顧客と議事録に芋づる式に辿れる」 状態を作ります。

Worker(TypeScript / Notion CLI でデプロイ)

Custom Agent(Notion UI でノーコード設定)

合計4DB + 2Worker + 2Agent
1日でここまで動かせます。

Phase 1:Notion Business 契約と Workers 有効化

まず Notion Business プランの契約から。Workers の利用には Business または Enterprise が必須です(Plus 以下では Workers の設定画面自体が出てこない)。

私は 月額¥3,800の月払い で契約しました。年払いだと月額¥3,150になりますが、いきなり年契約縛りはリスキーなので、1ヶ月でROIを確認してから判断する方針です。

契約直後のチェックリスト

  • Settings → Plans → Upgrade → Business

  • Settings → ConnectionsDeveloper Platform → 「Enable Workers」を ON

  • Settings → Billing → 領収書設定(会社名・住所・インボイス登録番号)

Pitfall #1: ベータ期間の終了日

スクリーンショットで見て初めて知ったのですが、Workersが無料で使えるベータ期間は 2026年8月11日まででした。9月以降は「Notion クレジット」(金額未公表のアドオン)が必要になります。

💡 ベータ期間中に最大限実装と検証を済ませる戦略 ── 今日が5月18日なので残り85日しかないと知った時の焦りで、私は実装を一気に進めました。

Phase 2:4DB自動構築(Node.jsスクリプトで一発)

4つのDBを手動で作るのは時間の無駄なので、Node.jsスクリプトでNotion APIを叩いて一発構築しました。CSV 4本を読み込んで、DB作成 → プロパティ設定 → Select選択肢登録 → 行挿入 → Relation解決まで自動化。

javascript

// 抜粋: L4 → L2 → L3 → L1 の順で作成
const l4Db = await createDB('L4 Clients & Deals', {
  'Client Name': { title: {} },
  Stage: { select: { options: [
    { name: 'リード', color: 'gray' },
    { name: '商談', color: 'yellow' },
    { name: '受注', color: 'green' },
  ]}},
  // ...
});

// L4 行挿入後、L2 を作成(L4 へのRelation付き)
const l2Db = await createDB('L2 Projects & Cases', {
  Client: { relation: { database_id: l4Db.id, single_property: {} } },
  // ...
});

Pitfall #2: single_property vs dual_property

Notion API で Relation を作るとき、single_property と dual_property の2種類があります:

  • single_property:片方向リレーション(L1から L2が見えるが、L2 から L1 は見えない)

  • dual_property:双方向リレーション(両方から相手が見える)

私は深く考えずに single_property で作ってしまいました。
結果、L2 プロジェクトのページを開いても、紐づくタスク25件が表示されない状態に。これが商談デモで致命的:「タスクからプロジェクトへ芋づる式に辿る」ストーリーが成立しないからです。

対処:Notion UI で各 Relation プロパティを開き、「他のDBに表示」トグルをONにする。

これはAPI側からdual_propertyとして作るのが正解で、次回からはスクリプトを書き直します。

Pitfall #3: CSV内のProject名がL2と完全一致せずRelation解決失敗

CSVデータの設計でも罠を踏みました。L1 タスクの CSV に Project = "Notion全社展開PJ" と書いていたのに、L2 のProject Name は "Notion全社展開PJ - サンプル製造" と suffix 付き。これが完全一致しないため、import スクリプトが25件分のRelation解決に失敗。

対処:別途 fix_relations.js という後付けスクリプトを書いて、CSVの Project 名 → L2 の正式名 への補正マップを適用。

javascript

const PROJECT_NAME_FIX = {
  'Notion全社展開PJ': 'Notion全社展開PJ - サンプル製造',
};

学び:CSVデータを作る時点で、L2 と完全一致する名前を使う。これだけです。

Phase 3:ビュー設計 ── 集約率ダッシュボード が商談の心臓

L1 My Tasks に「Source 別 Board ビュー」を作ります。プロパティは:

  • 会議(経営者・部門長との議論で出たタスク)

  • メール(外部からの受信由来)

  • Slack(チャット流れから拾われたタスク)

  • 顧客(直接の依頼・問い合わせ)

  • 自発(自分から動いたもの)

集約率ダッシュボードビュー

これが Board 形式で並ぶと、商談で次のセリフが完璧にハマります:

「導入前は 8割のタスクがメール埋もれ・Slack流れ・口約束で、誰が何を抱えているか経営者は把握できませんでした。今このボード上に 全件捕捉済みです。これが『集約率』というKPIです。」

数字で語れる集約率KPIが、感覚的な「Notionを入れたら便利になりました」より100倍説得力があります。

Phase 4:Worker #1(gmail-task-router)── pitfallの嵐

ここから本格的に Notion Workers 領域に入ります。5時間で7個のpitfallを踏み抜いた実録です。

Pitfall #4: Windows ネイティブ未対応

最初の壁。https://ntn.dev/install.ps1 という PowerShell インストール用URLは存在しない(公式ドキュメントにあると私は誤認していた)。実は ntn CLI は 2026年5月時点で macOS/Linux のみネイティブ対応で、Windowsは WSL2 必須 です。

対処:WSL2 (Ubuntu) を開いて、そこで作業する。すでに WSL2 が入っている人なら 5 分で済みますが、新規インストールは PC 再起動含めて30分はかかります。

Pitfall #5: npm install -g の権限エラー

WSL2 で curl -fsSL https://ntn.dev | bash を実行したら:

error: Could not install the Notion CLI to /usr/local/bin/ntn
The installer could not create or write to /usr/local/bin.

対処:エラーメッセージに書いてあった通り、ホームディレクトリにインストール:

bash

curl -fsSL "https://ntn.dev" | NTN_INSTALL_DIR="$HOME/.local/bin" bash

そして PATH に追加:

bash

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

これは Linux慣れしてる人なら 1 分で気づきますが、Windows ユーザーには罠です。

Pitfall #6: @notionhq/workers のバージョン pin が罠

私は npm の癖で package.json に:

json

"@notionhq/workers": "^0.5.0"

と書きましたが、そんなバージョンは存在しない。実際の公式 scaffold は:

json

"@notionhq/workers": ">=0.0.0"

を使っています。

対処:ntn workers new ntn-scaffold で公式スキャフォルドを生成 → cat package.json で正解を確認 → 自分のプロジェクトにコピペ。

Pitfall #7: semver ^0.0.0 の特殊ルール

ここで semver の闇に遭遇しました。>=0.0.0(任意のバージョン)と書こうとして^0.0.0 と書き間違えると:

対処:キャレットを使うなと言いたいわけではなく、0.x.y で x=0 のときだけ特殊ルールがあることを覚えておく。

Pitfall #8: tsconfig.json は公式scaffold準拠が安全

私は最初、 target: ES2022, module: ESNext, moduleResolution: Bundler で書きましたが、公式scaffoldは:

json

{
  "target": "ES2020",
  "module": "nodenext",
  "moduleResolution": "nodenext",
  "outDir": "./dist",
  "rootDir": "./src"
}

対処:scaffold準拠に書き直し。これで build パイプラインが期待通り動きます。

Pitfall #9: build スクリプト未定義

ntn workers deploy を実行すると、内部で npm run build が走ります。が、私は package.json に build スクリプトを書いていなかったため:

[build:err] npm error Missing script: "build"

対処:"build": "tsc" を scripts に追加。これも scaffold 準拠の話です。

Pitfall #10: @types/node が無いと型エラーの嵐

process.env.X を使うと TS2580: Cannot find name 'process' が出ます。Buffer、console、fetch も同様。

対処

bash

npm install --save-dev @types/node

これで Node 22 ランタイムの型情報が入り、すべて解決。

Pitfall #11: WebhookConfiguration の title と description が必須

webhook を以下のように書いてエラー:

typescript

worker.webhook("onGmailTaskLabel", {
  execute: async (events, context) => { /* ... */ }
});
error TS2345: Argument of type ... is missing the following properties: title, description

対処:title と description を追加。tool 系のCapability例(公式scaffold)にも書いてあった必須項目を webhook にも適用する必要があるとは思っていませんでした。

typescript

worker.webhook("onGmailTaskLabel", {
  title: "Gmail Task Router",
  description: "Gmail @task ラベルが付与されたメールを L1 My Tasks に自動起票する Worker",
  execute: async (events, context) => { /* ... */ }
});

Pitfall #12: Webhook callback の引数シグネチャを間違える

最大の罠でした。私が書いたコード:

typescript

execute: async ({ payload, notion }) => { /* ... */ }

これは 完全に間違い。型エラー:

'(events: WebhookEvent[]) => ...' は '(events: WebhookEvent[], context: CapabilityContext)' に代入不可

正しいシグネチャ

typescript

execute: async (events, context) => {
  for (const event of events) {
    const payload = (event as any).payload || (event as any).body;
    // 処理
    await context.notion.pages.create({ /* ... */ });
  }
}

ポイント:

  • 引数は2つ(events, context)、destructuringではない

  • events は配列(バッチ処理が前提)

  • Notion クライアントは context.notion から取得

  • 戻り値は void または Promise<void>

これは型定義ファイル node_modules/@notionhq/workers/dist/capabilities/webhook.d.ts を直接見て理解しました。ドキュメントよりコード読んだ方が早い、はあるあるです。

Pitfall #13: NOTION_ プレフィックスは予約済(ただし1個だけ例外)

ntn workers env push 時のエラー:

error: Failed to set environment variables (400 Bad Request InvalidSecretError):
Environment variable name must not start with "NOTION_" (reserved prefix)

私は NOTION_L1_DB_ID という名前を使っていたのが拒否。

でも矛盾:実行時のエラーには「NOTION_API_TOKEN を .env に追加してください」と書いてある。実際 context.notion は内部で NOTION_API_TOKEN を要求する。

真実:NOTION_* プレフィックスは予約だが、NOTION_API_TOKEN 1個だけは公式の例外。それ以外のカスタム変数は別の名前にする必要があります。

対処

diff

- NOTION_L1_DB_ID=xxx
+ L1_DB_ID=xxx
+ NOTION_API_TOKEN=secret_xxx

そしてコード側も process.env.L1_DB_ID に変更してデプロイし直す。

Phase 5:Custom Agent #1(Ticket Router)── ノーコードの威力

Worker と打って変わって、Custom Agent はNotion UI でノーコード設定できます。最大の発見はここでした。

Agents メニューから新規エージェント作成 → 名前・Instructions・トリガー・ツールアクセス を入力するだけ。コードを1行も書かずに「L1 にメール由来タスクが追加されたら、Projectを自動推定して埋める」AIが動きます。

Pitfall #14: Filter条件と Worker出力の不整合

私は最初、Ticket Routerのフィルタを「Source is メール AND Priority is empty」にしました。意図:「まだ未処理のメールタスクだけ拾う」

ところが、Worker (gmail-task-router) が Priority=Mid を初期セットしてしまうため、このフィルタには 永遠にマッチしない

対処:フィルタを「Source is メール AND Project is empty」に変更。WorkerはPriorityを埋め、Custom AgentはProject分類を担当する 役割分担にする。

これは仕様変更というより設計の役割分担を明確化した感じです。Worker は捕獲、Agent は分類、で住み分け。

Phase 6:Worker #2(slack-meeting-ingest)── Slack統合の壁

Slack を Notion に繋ぐ場面で、3つの選択肢のうち1つが死んでいることを学びました。

当初プラン:Slack App + Event Subscriptions

通常のWebhook設計なら:

  1. Slack App を作成

  2. Event Subscriptions で message.channels イベントを購読

  3. Worker の Webhook URL を登録

  4. Slack が URL Verification Challenge を送る → Worker が challenge 値を返す

ところがNotion Workers の webhook callback は void を返す設計で、HTTP レスポンスボディを返せない。Slack が期待する challenge 応答ができず、URL Verification が永遠に通らない。

Pitfall #15: 公式Worker webhook は HTTP レスポンスを返せない

これは設計上の制約で、回避策はありません。Slack の Event Subscriptions は Notion Worker と直結できないのが現実。

解決策3つ

最大の発見:Custom Agent の Slack ネイティブトリガー

ここで Notion UI を触っていて気づきました。Custom Agent のトリガー設定画面に Slack が標準で含まれている

  • メッセージが投稿されました

  • 絵文字リアクションが追加されました

  • エージェントがメンションされました

つまり Worker を経由せず、Custom Agent が直接 Slack を監視できる

Slack 統合に半日溶かしかけたところでこれを発見し、slack-meeting-ingest Worker は実装したが本番運用ではバックアップ用、本番は Custom Agent 直結で行く方針に変更しました。

💡 この経験からの学び:Notion の Custom Agent と Worker は補完関係。Worker は外部APIへのactiveアクセス(Gmail API、freee API など)に強い。Custom Agent は Notion 内のpassive監視と自然言語ロジックに強い。SlackやNotion内イベントは Custom Agent 直結が筋

Phase 7:Custom Agent #2(Meeting Splitter)── Agent Orchestra の心臓

Meeting Splitter は 2つのトリガーで起動する設計にしました:



  1. L3 Knowledge Base にページが追加されたとき(Worker経由 or 手動で議事録追加)

  2. Slack #meeting -notes にメッセージが投稿されたとき(Slack直結トリガー)

Pitfall #16: 重複発火の防止

両方のトリガーが有効だと、同じSlackメッセージで2回発火して L1 タスクが重複作成される懸念があります。

対処:Instructionsの中で重複判定ロジックを書く。

ケース B: Slack のメッセージが投稿された場合
  → まず L3 を検索し、過去5分以内に同じ内容のページが既にあれば
    (Worker が先に作っている可能性)スキップする
  → 重複なし → L3ページ作成 → ToDo抽出 → L1起票

これで両ルートが共存できます。

Instructions の全文(参考)

あなたは議事録から ToDo を抽出する専門アシスタントです。

このエージェントは2つのトリガーで起動します:

ケースA: L3 ページ追加
  → 本文から ToDo を抽出、L1 にタスク起票

ケースB: Slack メッセージ投稿
  → 重複チェック → L3 にページ作成 → ToDo抽出 → L1 にタスク起票

抽出ルール:
- 本文の「ToDo」「次回までに」「対応する」を含む箇条書きを抽出
- 担当者は文中の名前から推定("田中部長が..." → Assignee: 田中部長)
- 期限は文中の日付表現から推定(「至急」→ High、「来週」→ Mid)
- Project は L2 を検索して最も近いものをリンク

L1 への書き込み:
- Name: 簡潔に(最大40文字)
- Status: Backlog
- Priority: High/Mid/Low
- Source: 会議
- Due: 文中の期限 or 会議日+7日

自然言語で判定ルールを書く のが最大の魅力。Zapier的なif-then 構築と比べて、SMB の経営者や部門長が自分で調整できるのが Notion Custom Agent の強さです。

Phase 8:エンドツーエンドテスト ── 2種類のサンプル議事録で検証

完成後、2つの異なる議事録サンプルで動作確認しました:

v1 で 6件、v2 で 7件のタスクが L1 に正しく起票されました。曖昧な期限表現も Claude が日付化できることを確認。

商談デモの実演用には v1(プロジェクト進捗)、汎用性アピール用には v2(営業フェーズ)を見せる、と使い分けると効果的です。

Pitfall完全リスト:13個の落とし穴と対処


ざっくり15個のpitfall + 2つの設計判断で完成しました。

5日間で学んだ本質的なこと

Notion 3.5 は「データ層とAI層のオーケストレーション基盤」

これまで Notion は「ドキュメント + データベース」でしたが、Workers と Custom Agent が加わって "AIを束ねるハブ" に変わりました。SMB にとっての意味は:

「Notion に情報を集約しさえすれば、AI に任せる準備が完了する」

これ以外のSaaSにこの戦略を取れているものは少なく、3年後の業務基盤として Notion 3.5 がSMBにとって筋が良い理由です。

Worker と Custom Agent は補完関係

外部から取り込みは Worker、内部処理は Custom Agent という棲み分けが綺麗に機能します。

商談で効くのは「人間が何もしていない」演出

5日かけて分かったのは、商談で1番効くのは技術の詳細ではなく "私の指は今、何も動いていません" という瞬間 ということ。

MTG面談後の議事録をSlackに共有

Slackにペーストして30秒待つだけで Notion に議事録ページが現れ、さらに L1 に複数タスクが上がる ── これを見せた瞬間、SMB の経営者は「自分の会社でもこれが動く絵」を頭の中で描けます。

Meeting Splitterが議事録からタスクを自動生成
Ticket Routerがチケットを作成中


実装の苦労(このリストの16個)は商談で語らず、結果だけを見せるのが効果的。

余談:この5日間の費用と回収

これに対するリターン候補:

  • Spot deployment 1件 = ¥30,000(7.9倍

  • Half-day WS 1件 = ¥300,000(78.9倍

  • 商工会議所登壇 1件 = ¥300,000(78.9倍

加えて:

  • このNote記事 → リード獲得チャネル(永続資産)

  • X / LinkedIn での実装スクショ投稿

  • 商談デモの読み取り専用URL(売れない期間も使い続けられる)

¥3,800を「広告費」と見なせば、1ヶ月以内にROIプラスは確実だと判断しています。

おわりに:御社でも90日でこれが動きます

私が AI コンサルとして提供している半日ワークショップ+全社展開プログラムでは、90日後に御社で同じ仕組みが立ち上がる状態を約束しています。

  • Phase 0 (1週間): 現状診断・タスク棚卸し

  • Phase 1 (2週間): 4層DB構築・テンプレ整備

  • Phase 2 (4週間): チーム展開・運用定着(集約率60%目標)

  • Phase 3 (4週間): Claude × MCP × Worker 連携(工数削減30%目標)

  • Phase 4: 自走化・改善ループ

投資額は ¥850,000(税抜)
人材開発支援助成金(事業展開等リスキリング支援コース) を併用すると、実質負担 約¥412,000 まで圧縮できます。

自社でNotionを動かしているコンサルから、自社でNotionを動かす方法を学ぶ」という一貫性が、私の提供する価値です。

商談デモの読み取り専用URL(今回作った Notion ワークスペース)は、ご興味あれば DM ください。実物を見ながら 30 分でメリットを判断していただけます。

関連リンク

いいなと思ったら応援しよう!