add notion tools for create/update/delete pages

This commit is contained in:
CREDO23 2026-02-11 16:11:53 +02:00
parent c492505876
commit 8649ca7ac0
6 changed files with 368 additions and 42 deletions

View file

@ -1,38 +0,0 @@
import hashlib
from typing import Any
from langchain_core.tools import tool
def create_create_notion_page_tool():
@tool
async def create_notion_page(
title: str,
content: str,
) -> dict[str, Any]:
"""Create a new page in Notion with the given title and content.
Use this tool when the user asks you to create, save, or publish
something to Notion. The page will be created in the user's
configured Notion workspace.
Args:
title: The title of the Notion page.
content: The markdown content for the page body.
"""
# Generate a unique page ID based on title for testing
# This helps verify if edited args were used
page_hash = hashlib.md5(title.encode()).hexdigest()[:8]
# Return detailed response showing what was actually received
return {
"status": "success",
"page_id": f"stub-page-{page_hash}",
"title": title,
"content_preview": content[:100] + "..." if len(content) > 100 else content,
"content_length": len(content),
"url": f"https://www.notion.so/stub-page-{page_hash}",
"message": f"✅ Created Notion page '{title}' with {len(content)} characters",
}
return create_notion_page

View file

@ -0,0 +1,11 @@
"""Notion tools for creating, updating, and deleting pages."""
from .create_page import create_create_notion_page_tool
from .delete_page import create_delete_notion_page_tool
from .update_page import create_update_notion_page_tool
__all__ = [
"create_create_notion_page_tool",
"create_update_notion_page_tool",
"create_delete_notion_page_tool",
]

View file

@ -0,0 +1,110 @@
from typing import Any
from langchain_core.tools import tool
from sqlalchemy.ext.asyncio import AsyncSession
from app.connectors.notion_history import NotionHistoryConnector
def create_create_notion_page_tool(
db_session: AsyncSession | None = None,
search_space_id: int | None = None,
connector_id: int | None = None,
):
"""
Factory function to create the create_notion_page tool.
Args:
db_session: Database session for accessing Notion connector
search_space_id: Search space ID to find the Notion connector
connector_id: Optional specific connector ID (if known)
Returns:
Configured create_notion_page tool
"""
@tool
async def create_notion_page(
title: str,
content: str,
parent_page_id: str | None = None,
) -> dict[str, Any]:
"""Create a new page in Notion with the given title and content.
Use this tool when the user asks you to create, save, or publish
something to Notion. The page will be created in the user's
configured Notion workspace.
Args:
title: The title of the Notion page.
content: The markdown content for the page body (supports headings, lists, paragraphs).
parent_page_id: Optional parent page ID to create as a subpage.
If not provided, will ask for one.
Returns:
Dictionary with:
- status: "success" or "error"
- page_id: Created page ID
- url: URL to the created page
- title: Page title
- message: Success or error message
Examples:
- "Create a Notion page titled 'Meeting Notes' with content 'Discussed project timeline'"
- "Save this to Notion with title 'Research Summary'"
"""
if db_session is None or search_space_id is None:
return {
"status": "error",
"message": "Notion tool not properly configured. Please contact support.",
}
try:
# Get connector ID if not provided
if connector_id is None:
from sqlalchemy.future import select
from app.db import SearchSourceConnector, SearchSourceConnectorType
result = await db_session.execute(
select(SearchSourceConnector).filter(
SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.connector_type
== SearchSourceConnectorType.NOTION_CONNECTOR,
SearchSourceConnector.is_enabled == True,
)
)
connector = result.scalars().first()
if not connector:
return {
"status": "error",
"message": "No Notion connector found. Please connect Notion in your workspace settings.",
}
connector_id = connector.id
# Create connector instance
notion_connector = NotionHistoryConnector(
session=db_session,
connector_id=connector_id,
)
# Create the page
result = await notion_connector.create_page(
title=title, content=content, parent_page_id=parent_page_id
)
return result
except ValueError as e:
return {
"status": "error",
"message": str(e),
}
except Exception as e:
return {
"status": "error",
"message": f"Unexpected error creating Notion page: {str(e)}",
}
return create_notion_page

View file

@ -0,0 +1,102 @@
from typing import Any
from langchain_core.tools import tool
from sqlalchemy.ext.asyncio import AsyncSession
from app.connectors.notion_history import NotionHistoryConnector
def create_delete_notion_page_tool(
db_session: AsyncSession | None = None,
search_space_id: int | None = None,
connector_id: int | None = None,
):
"""
Factory function to create the delete_notion_page tool.
Args:
db_session: Database session for accessing Notion connector
search_space_id: Search space ID to find the Notion connector
connector_id: Optional specific connector ID (if known)
Returns:
Configured delete_notion_page tool
"""
@tool
async def delete_notion_page(
page_id: str,
) -> dict[str, Any]:
"""Delete (archive) a Notion page.
Use this tool when the user asks you to delete, remove, or archive
a Notion page. Note that Notion doesn't permanently delete pages,
it archives them (they can be restored from trash).
Args:
page_id: The ID of the Notion page to delete (required).
Returns:
Dictionary with:
- status: "success" or "error"
- page_id: Deleted page ID
- message: Success or error message
Examples:
- "Delete the Notion page abc123"
- "Remove the page xyz789 from Notion"
- "Archive this Notion page: abc123"
"""
if db_session is None or search_space_id is None:
return {
"status": "error",
"message": "Notion tool not properly configured. Please contact support.",
}
try:
# Get connector ID if not provided
if connector_id is None:
from sqlalchemy.future import select
from app.db import SearchSourceConnector, SearchSourceConnectorType
result = await db_session.execute(
select(SearchSourceConnector).filter(
SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.connector_type
== SearchSourceConnectorType.NOTION_CONNECTOR,
SearchSourceConnector.is_enabled == True,
)
)
connector = result.scalars().first()
if not connector:
return {
"status": "error",
"message": "No Notion connector found. Please connect Notion in your workspace settings.",
}
connector_id = connector.id
# Create connector instance
notion_connector = NotionHistoryConnector(
session=db_session,
connector_id=connector_id,
)
# Delete the page
result = await notion_connector.delete_page(page_id=page_id)
return result
except ValueError as e:
return {
"status": "error",
"message": str(e),
}
except Exception as e:
return {
"status": "error",
"message": f"Unexpected error deleting Notion page: {str(e)}",
}
return delete_notion_page

View file

@ -0,0 +1,116 @@
from typing import Any
from langchain_core.tools import tool
from sqlalchemy.ext.asyncio import AsyncSession
from app.connectors.notion_history import NotionHistoryConnector
def create_update_notion_page_tool(
db_session: AsyncSession | None = None,
search_space_id: int | None = None,
connector_id: int | None = None,
):
"""
Factory function to create the update_notion_page tool.
Args:
db_session: Database session for accessing Notion connector
search_space_id: Search space ID to find the Notion connector
connector_id: Optional specific connector ID (if known)
Returns:
Configured update_notion_page tool
"""
@tool
async def update_notion_page(
page_id: str,
title: str | None = None,
content: str | None = None,
) -> dict[str, Any]:
"""Update an existing Notion page's title and/or content.
Use this tool when the user asks you to modify, edit, or update
a Notion page. At least one of title or content must be provided.
Args:
page_id: The ID of the Notion page to update (required).
title: New title for the page (optional).
content: New markdown content for the page body (optional).
If provided, replaces all existing content.
Returns:
Dictionary with:
- status: "success" or "error"
- page_id: Updated page ID
- url: URL to the updated page
- title: Current page title
- message: Success or error message
Examples:
- "Update the Notion page abc123 with title 'Updated Meeting Notes'"
- "Change the content of page xyz789 to 'New content here'"
- "Update page abc123 with new title 'Final Report' and content '# Summary...'"
"""
if db_session is None or search_space_id is None:
return {
"status": "error",
"message": "Notion tool not properly configured. Please contact support.",
}
if not title and not content:
return {
"status": "error",
"message": "At least one of 'title' or 'content' must be provided to update the page.",
}
try:
# Get connector ID if not provided
if connector_id is None:
from sqlalchemy.future import select
from app.db import SearchSourceConnector, SearchSourceConnectorType
result = await db_session.execute(
select(SearchSourceConnector).filter(
SearchSourceConnector.search_space_id == search_space_id,
SearchSourceConnector.connector_type
== SearchSourceConnectorType.NOTION_CONNECTOR,
SearchSourceConnector.is_enabled == True,
)
)
connector = result.scalars().first()
if not connector:
return {
"status": "error",
"message": "No Notion connector found. Please connect Notion in your workspace settings.",
}
connector_id = connector.id
# Create connector instance
notion_connector = NotionHistoryConnector(
session=db_session,
connector_id=connector_id,
)
# Update the page
result = await notion_connector.update_page(
page_id=page_id, title=title, content=content
)
return result
except ValueError as e:
return {
"status": "error",
"message": str(e),
}
except Exception as e:
return {
"status": "error",
"message": f"Unexpected error updating Notion page: {str(e)}",
}
return update_notion_page

View file

@ -45,12 +45,16 @@ from langchain_core.tools import BaseTool
from app.db import ChatVisibility
from .create_notion_page import create_create_notion_page_tool
from .display_image import create_display_image_tool
from .generate_image import create_generate_image_tool
from .knowledge_base import create_search_knowledge_base_tool
from .link_preview import create_link_preview_tool
from .mcp_tool import load_mcp_tools
from .notion import (
create_create_notion_page_tool,
create_delete_notion_page_tool,
create_update_notion_page_tool,
)
from .podcast import create_generate_podcast_tool
from .scrape_webpage import create_scrape_webpage_tool
from .search_surfsense_docs import create_search_surfsense_docs_tool
@ -201,13 +205,34 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
requires=["user_id", "search_space_id", "db_session", "thread_visibility"],
),
# =========================================================================
# ADD YOUR CUSTOM TOOLS BELOW
# NOTION TOOLS - create, update, delete pages
# =========================================================================
ToolDefinition(
name="create_notion_page",
description="Create a new page in the user's Notion workspace",
factory=lambda deps: create_create_notion_page_tool(),
requires=[],
factory=lambda deps: create_create_notion_page_tool(
db_session=deps["db_session"],
search_space_id=deps["search_space_id"],
),
requires=["db_session", "search_space_id"],
),
ToolDefinition(
name="update_notion_page",
description="Update an existing Notion page's title or content",
factory=lambda deps: create_update_notion_page_tool(
db_session=deps["db_session"],
search_space_id=deps["search_space_id"],
),
requires=["db_session", "search_space_id"],
),
ToolDefinition(
name="delete_notion_page",
description="Delete (archive) a Notion page",
factory=lambda deps: create_delete_notion_page_tool(
db_session=deps["db_session"],
search_space_id=deps["search_space_id"],
),
requires=["db_session", "search_space_id"],
),
]