Examples¶
End-to-end LangChain agent flow examples that you can run locally.
The snippets below run as doctests. They use in-memory stand-ins for the Notion SDK so you can
experiment without calling the live API. Swap the stub classes for real notion-client instances
when integrating into your project.
>>> import asyncio
>>> from langchain_notion_tools.config import NotionClientSettings
>>> from langchain_notion_tools.tools import NotionSearchTool, NotionWriteTool
>>> from langchain_notion_tools.blocks import from_text
>>> class MemoryPages:
... def __init__(self):
... self.created = []
... self.updated = []
... self.retrieved = {}
... def create(self, **payload):
... self.created.append(payload)
... page_id = f"page-{len(self.created)}"
... url = f"https://notion.local/{page_id}"
... self.retrieved[page_id] = {"id": page_id, "url": url}
... return {"id": page_id, "url": url}
... def update(self, *, page_id, properties):
... self.updated.append((page_id, properties))
... return {"id": page_id, "url": f"https://notion.local/{page_id}"}
... def retrieve(self, *, page_id):
... return self.retrieved.get(page_id, {"id": page_id, "url": f"https://notion.local/{page_id}"})
>>> class MemoryBlocksChildren:
... def __init__(self):
... self.appended = []
... def append(self, **payload):
... self.appended.append(payload)
... return {"results": payload.get("children", [])}
>>> class MemoryBlocks:
... def __init__(self):
... self.children = MemoryBlocksChildren()
>>> class MemoryAsyncPages(MemoryPages):
... async def create(self, **payload):
... return super().create(**payload)
... async def update(self, *, page_id, properties):
... return super().update(page_id=page_id, properties=properties)
... async def retrieve(self, *, page_id):
... return super().retrieve(page_id=page_id)
>>> class MemoryAsyncBlocksChildren(MemoryBlocksChildren):
... async def append(self, **payload):
... return super().append(**payload)
>>> class MemoryAsyncBlocks:
... def __init__(self):
... self.children = MemoryAsyncBlocksChildren()
>>> class MemorySearch:
... def __init__(self, results):
... self.results = results
... self.calls = []
... def __call__(self, **kwargs):
... self.calls.append(kwargs)
... return {"results": self.results}
>>> class MemoryDatabases:
... def __init__(self, rows):
... self.rows = rows
... self.calls = []
... def query(self, *, database_id, **kwargs):
... self.calls.append((database_id, kwargs))
... return {"results": self.rows}
>>> class MemoryClient:
... def __init__(self, search_results=None, database_rows=None):
... self.pages = MemoryPages()
... self.blocks = MemoryBlocks()
... self.search = MemorySearch(search_results or [])
... self.databases = MemoryDatabases(database_rows or [])
>>> class MemoryAsyncClient:
... def __init__(self, search_results=None, database_rows=None):
... self.pages = MemoryAsyncPages()
... self.blocks = MemoryAsyncBlocks()
... self.search = MemorySearch(search_results or [])
... self.databases = MemoryDatabases(database_rows or [])
1. Create a page then append an action items section¶
>>> sync_client = MemoryClient()
>>> async_client = MemoryAsyncClient()
>>> settings = NotionClientSettings(api_token="test-token")
>>> write_tool = NotionWriteTool(settings=settings, client=sync_client, async_client=async_client)
>>> draft_blocks = from_text("""# Weekly Review\n\n- Align roadmap\n- Confirm launch dates""")
>>> write_tool.run(title="Weekly Review", parent={"page_id": "parent-1"}, blocks=draft_blocks)["summary"]
"Created page under page parent-1 with title 'Weekly Review' and 3 block(s)."
>>> action_items = from_text("""### Action Items\n- Draft release notes\n- Schedule beta kickoff""")
>>> write_tool.run(update={"page_id": "page-1", "mode": "append"}, blocks=action_items)["summary"]
"Appended 2 block(s) on page page-1."
2. Update an existing page with a summary¶
>>> write_tool.run(
... update={"page_id": "page-1", "mode": "append"},
... blocks=from_text("## Summary\n- Reached parity with v1"),
... )["summary"]
"Appended 1 block(s) on page page-1."
3. Find a spec then post a decision log¶
>>> spec_hit = [{
... "object": "page",
... "id": "spec-123",
... "url": "https://notion.local/spec-123",
... "parent": {"type": "database_id", "database_id": "db-specs"},
... "properties": {
... "Title": {"type": "title", "title": [{"plain_text": "API Spec"}]},
... "Summary": {"type": "rich_text", "rich_text": [{"plain_text": "Latest API changes"}]},
... },
... }]
>>> sync_client.search = MemorySearch(spec_hit)
>>> async_client.search = MemorySearch(spec_hit)
>>> search_tool = NotionSearchTool(client=sync_client, async_client=async_client)
>>> search_tool.run(query="API spec")
[{'title': 'API Spec', 'object_type': 'page', 'id': 'spec-123', 'url': 'https://notion.local/spec-123', 'parent_id': 'db-specs', 'preview': 'Latest API changes'}]
>>> decision_log = from_text("""### Decision\n- Adopt OAuth2\n- Sunset legacy keys""")
>>> write_tool.run(update={"page_id": "spec-123", "mode": "append"}, blocks=decision_log)["summary"]
"Appended 2 block(s) on page spec-123."
4. Agent-style confirmation before writing to Notion¶
>>> async def agent_flow(prompt: str) -> dict:
... proposal = from_text(f"# Draft\n{prompt}")
... preview = write_tool.run(
... update={"page_id": "spec-123", "mode": "append"},
... blocks=proposal,
... is_dry_run=True,
... )
... # pretend we confirmed with the human
... return await write_tool.arun(
... update={"page_id": "spec-123", "mode": "append"},
... blocks=proposal,
... )
>>> asyncio.run(agent_flow("Summaries must call out risk items"))["summary"]
'Appended 1 block(s) on page spec-123.'