ChatGPT × Cloudflare Workers × Notion で「話しかけるだけのタスク管理」を作りました
TL;DR
- Custom GPT の Actions 機能で Notion をバックエンドにしたタスク・スケジュール管理システムを構築
- Cloudflare Workers(Hono) を Notion API への薄い Proxy として配置し、ChatGPT から直接 Notion を操作
- 「問い合わせ来たから今日中に回答入れといて」と話すだけでタスクが登録される体験を実現
- 76 テスト / 11 エンドポイント / TypeScript で全体を構成。開発は GitHub Copilot(Agent Mode) で加速
なぜ作ったのか
タスク管理ツールは山ほどあります。Notion、Todoist、Asana、Jira……。
しかし、どれも 「ツールを開いて、入力して、保存する」 という操作が必要です。移動中にスマホでポチポチ入力するのは面倒ですし、会議中にさっと入れるのも難しい。
一方で、ChatGPT とは日常的に会話しています。なら 「ChatGPT に話しかけるだけでタスクが Notion に入る」 状態を作れば、入力のハードルが限りなくゼロになるのでは?
そう思って作ったのがこのシステムです。
アーキテクチャ
iPhone/Web ChatGPT App → Cloudflare Workers (Hono) → Notion API
Custom GPT Bridge API Tasks / Schedules DB
対話・補完 薄い Proxy データストア + 人間UI
3つの設計原則
| 原則 | 意味 |
|---|---|
| 知性は GPT 側に集約 | タスク名の整形、期限の推測、優先度の判断はすべて GPT のプロンプトで実現。API 側にロジックを持たない |
| Bridge API は薄い Proxy | Notion API へのリクエスト変換と認証管理のみ。ビジネスロジックを置かない |
| Notion はデータストア兼 UI | 人間も Notion から直接閲覧・編集できる。ChatGPT 専用のデータベースにしない |
ここが重要なポイントです。サーバーサイドに知性を入れない。GPT が賢くなれば、API を変えずにシステム全体が賢くなりえます。
技術スタック
| 項目 | 選定 | 選定理由 |
|---|---|---|
| 言語 | TypeScript | 型安全 + Cloudflare Workers ネイティブ対応 |
| ランタイム | Cloudflare Workers | コールドスタートなし、無料枠で十分、グローバルエッジ |
| フレームワーク | Hono | Workers 最適化済み、軽量、Express ライクな DX |
| データストア | Notion API | 人間も直接使える UI を兼ねる |
| テスト | Vitest + @cloudflare/vitest-pool-workers | Workers ランタイム上でテスト実行 |
| 開発支援 | GitHub Copilot(Agent Mode) | Issues → PR の自動化 |
なぜ Cloudflare Workers?
Custom GPT の Actions は HTTPS エンドポイントを叩きます。つまり、どこかにサーバーが要る。
選択肢はいくつかありました:
- AWS Lambda + API Gateway: セットアップが重い、コールドスタートあり
- Vercel / Next.js API Routes: SSR 不要なのにフレームワークが大きすぎる
- Cloudflare Workers: 設定ファイル1つ、デプロイ1コマンド、コールドスタートなし
薄い Proxy に大仰なインフラは不要です。Workers + Hono の組み合わせが最適でした。
実装の中身
ディレクトリ構成
src/
├── routes/
│ ├── tasks.ts # POST/GET/PATCH /tasks
│ ├── schedules.ts # POST/GET/PATCH/DELETE /schedules
│ └── schedule-templates.ts # POST/GET/PATCH/DELETE /schedule-templates
├── notion/
│ ├── client.ts # Notion API クライアント初期化
│ ├── tasks.ts # Tasks DB 操作
│ ├── schedules.ts # Schedules DB 操作
│ └── schedule-templates.ts # ScheduleTemplates DB 操作
├── index.ts # Hono エントリポイント + 認証ミドルウェア
└── types.ts # 型定義 + Enum マッピング
エンドポイント一覧(11本)
| メソッド | パス | 機能 |
|---|---|---|
| POST | /tasks |
タスク作成 |
| GET | /tasks |
タスク一覧(status, priority, due_date, assignee フィルタ) |
| PATCH | /tasks/:id |
タスク更新(部分更新) |
| POST | /schedules |
予定作成 |
| GET | /schedules |
予定一覧(date, from/to で範囲フィルタ) |
| PATCH | /schedules/:id |
予定更新 |
| DELETE | /schedules/:id |
予定削除 |
| POST | /schedule-templates |
テンプレート作成 |
| GET | /schedule-templates |
テンプレート一覧(day_of_week フィルタ) |
| PATCH | /schedule-templates/:id |
テンプレート更新 |
| DELETE | /schedule-templates/:id |
テンプレート削除 |
認証の仕組み
ChatGPT → [Bearer Token] → Cloudflare Workers → [Integration Token] → Notion API
-
GPT → Workers: Custom GPT の Actions に Bearer Token を設定。Workers 側で
bearerAuthミドルウェアで検証 - Workers → Notion: Notion Integration Token を Cloudflare Workers の Secret として登録
// Hono の bearerAuth ミドルウェアで全ルートを保護
app.use("/tasks/*", async (c, next) => {
const auth = bearerAuth({ token: c.env.API_TOKEN });
return auth(c, next);
});
Notion プロパティのマッピング
API と Notion のプロパティ名・値を双方向にマッピングする仕組みを作りました。
// API 値 → Notion Select 名
export const PRIORITY_MAP = {
high: "🔴高",
medium: "🟡中",
low: "🔵低",
} as const satisfies Record<ApiPriority, string>;
// Notion Select 名 → API 値(逆引き自動生成)
export const PRIORITY_REVERSE_MAP = Object.fromEntries(
Object.entries(PRIORITY_MAP).map(([k, v]) => [v, k]),
) as Record<string, ApiPriority>;
これにより:
- API からは
"high"で指定 - Notion 上では
🔴高と表示 - Notion から読み出すときは自動的に
"high"に戻る
Notion のプロパティ名を日本語にしたのは、人間が Notion を直接見たときの可読性を優先したためです。
GPT プロンプトの設計
Custom GPT の Instructions(プロンプト)が、このシステムの「知性」の全てです。
## タスク登録
- タスク名はユーザーの発言をそのまま使わず、簡潔なアクションに整える
- 例: 「問い合わせ来たから今日中に回答入れといて」→ 「問い合わせ回答を入力する」
- 「今日」「急ぎ」「至急」が含まれる場合は priority=high にする
- 期限が会話から読み取れたらセットする(「今日中に」→ 今日の日付)
GPT がタスク名を整形し、期限を推測し、優先度を判断します。API 側は受け取ったデータをそのまま Notion に渡すだけです。
「いつもの入れて」のユースケース
スケジュールテンプレート機能の真骨頂は「いつもの入れて」です。
- GPT が
GET /schedule-templatesでテンプレート一覧を取得 - 対象週の各曜日の日付を計算(例:
mon→2026-03-23) - テンプレートごとに曜日 + 時刻 → ISO 8601 日時に変換
-
POST /schedulesで実際の予定として一括登録
このロジックは全て GPT のプロンプトに書いてあります。API 側に「テンプレートから予定を生成する」エンドポイントは存在しません。GPT が既存 API を組み合わせて実現します。
テスト戦略
76 tests / 14 files / all passing
テスト構成
| 種類 | 対象 | テスト数 |
|---|---|---|
| Unit | 値マッピング(STATUS_MAP 等の双方向変換) | 16 |
| Unit | バリデーション(pageToTask 変換) | 4 |
| Integration | POST /tasks(正常系・バリデーション) | 8 |
| Integration | GET /tasks(フィルタ組み合わせ) | 8 |
| Integration | PATCH /tasks(部分更新・404) | 8 |
| Integration | POST/GET/PATCH/DELETE /schedules | 12 |
| Integration | POST/GET/PATCH/DELETE /schedule-templates | 20 |
Cloudflare Workers のテスト環境
@cloudflare/vitest-pool-workers を使い、Workers ランタイム上で直接テスト実行しています。
// vitest.config.ts
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
test: {
poolOptions: {
workers: {
wrangler: { configPath: "./wrangler.toml" },
},
},
},
});
Notion API のモックは vi.mock() で実現しています。実際の API は叩きません。
vi.mock("../../notion/client", () => ({
createNotionClient: vi.fn(() => ({})),
}));
開発プロセス:GitHub Copilot Agent Mode の活用
このプロジェクトの特徴は、GitHub Copilot(Agent Mode)を全面的に活用した開発プロセスにあります。
Copilot への指示を多層構成で管理するアプローチを取りました。指示の構造・品質チェック・ドリフト防止を分けて設計することで、Agent が設計意図を理解した上でコードを生成できる仕組みになっています。
詳細については、別途記事でご紹介する予定です。
セットアップ手順
1. Notion 側の準備
# Integration を作成して Token を取得
# 親ページを作成して Integration を接続
# DB を自動作成
NOTION_TOKEN=ntn_xxx PARENT_PAGE_ID=xxx npx tsx scripts/create-tasks-db.ts
NOTION_TOKEN=ntn_xxx PARENT_PAGE_ID=xxx npx tsx scripts/create-schedules-db.ts
NOTION_TOKEN=ntn_xxx PARENT_PAGE_ID=xxx npx tsx scripts/create-schedule-templates-db.ts
2. Cloudflare Workers デプロイ
npm install
npx wrangler login
npx wrangler secret put API_TOKEN
npx wrangler secret put NOTION_TOKEN
npx wrangler secret put NOTION_DATABASE_ID
npx wrangler secret put NOTION_SCHEDULES_DATABASE_ID
npx wrangler secret put NOTION_SCHEDULE_TEMPLATES_DATABASE_ID
npx wrangler deploy
3. Custom GPT 設定
- ChatGPT で「Create GPT」
- Instructions にプロンプトを設定
- Actions に OpenAPI spec をコピペ
- Authentication に Bearer Token を設定
- 完了
使ってみた感想
良かった点
- 入力のハードルが消えた: 移動中でも音声入力で「あれやっといて」と言うだけ
- Notion で一覧性が保てる: ChatGPT はインプット専用、Notion はダッシュボード。役割分担がきれい
- 拡張が容易: 新しい DB を追加して OpenAPI spec にエンドポイントを足すだけ
- GPT が勝手に賢くなる: プロンプトを改善すれば API 変更なしで体験が向上
改善したい点
- プロジェクト単位のグルーピング機能(次フェーズ)
- おすすめプラン生成(空き時間にタスクをはめ込む)
- 複数ユーザー対応(現在は個人用)
まとめ
Custom GPT + Cloudflare Workers + Notion という構成で、「話しかけるだけのタスク管理」 を実現しました。
個人的に重要だと感じたのは「API を薄く保つ」設計です。知性を GPT に集約することで、GPT の進化がそのままシステムの進化につながりやすくなります。サーバーサイドにロジックを入れすぎると、GPT が賢くなっても API がボトルネックになりかねません。
私の用途(個人のタスク管理)では、この構成で十分実用になりました。興味のある方はぜひ試してみてください。
技術スタック: TypeScript / Cloudflare Workers / Hono / Notion API / Custom GPT Actions / Vitest