Natural language task management via WhatsApp and Slack, backed by Notion, with automatic weekly knowledge enrichment into GBrain.
Send a message on WhatsApp or Slack like:
"Follow up with the vendor sales rep on Thursday"
And the agent will:
- Infer that this is a task creation request
- Detect the project (Sales-project, in this case)
- Convert the relative date to
YYYY-MM-DD - Create the task in your Notion database under the correct project
- Confirm with a ✅
Every Sunday, a cron job pulls all tasks updated that week, distils them into project-level summaries using OpenAI, and writes the results to GBrain as knowledge pages — so your AI agent accumulates context about what you are working on without you doing anything manually.
WhatsApp / Slack
↓
Hermes agent (AWS VPS)
↓ intent inference via system_prompt
notion_tasks.py ────────────────────→ Notion database
gbrain_enrichment.py (weekly cron)
↓ fetches last 7 days of tasks
OpenAI gpt-4o-mini (distil)
↓
GBrain (knowledge pages per project)
Components:
- Hermes — open-source AI agent with WhatsApp and Slack interfaces
- Notion — task database
- GBrain — personal knowledge graph with vector search
notion_tasks.py— thin Python wrapper around the Notion REST APIgbrain_enrichment.py— weekly cron that distils Notion tasks into GBrain knowledge pages
- Hermes installed and running on a VPS (Ubuntu recommended)
- GBrain installed and initialised (
gbrain init) - A Notion account with a task database
- OpenAI API key configured in GBrain (
gbrain config set openai_api_key sk-...) - Python 3.11+ with
requestsavailable
- Go to https://www.notion.so/my-integrations
- Click New integration, name it (e.g. "Hermes Agent"), select your workspace
- Copy the Internal Integration Token — this is your
NOTION_TOKEN - Open your tasks database in Notion → click
...(top right) → Connections → add your integration - Also add the integration to every parent page that contains the database
Open your Notion database in a browser. The URL looks like:
https://www.notion.so/yourworkspace/90a025v1...?v=...
The 32-character string before the ?v= is your NOTION_DATABASE_ID.
For each project page inside your database, open it in the browser and copy the ID from the URL in the same way. You will need one ID per project.
mkdir -p ~/.hermes/skills/productivity/notion-tasks/scripts
cp notion-tasks/notion_tasks.py ~/.hermes/skills/productivity/notion-tasks/scripts/
cp notion-tasks/gbrain_enrichment.py ~/.hermes/skills/productivity/notion-tasks/scripts/Edit both scripts and fill in:
NOTION_TOKEN = "secret_xxxxxxxxxxxxxxxxxxxx"
DATABASE_ID = "your_database_id_here"In notion_tasks.py, update the PROJECTS dict with your project page IDs:
PROJECTS = {
"Sales-project": "your_sales-project_page_id",
"hermes": "your_hermes_page_id",
# add more as needed
}In gbrain_enrichment.py, update PROJECT_IDS (reverse map — page ID → name):
PROJECT_IDS = {
"your_Sales-project_page_id": "Sales-project",
"your_hermes_page_id": "Hermes",
# add more as needed
}Also set the correct path to your GBrain binary:
GBRAIN = "/home/ubuntu/.bun/bin/gbrain" # find yours with: which gbrainRun a quick search to confirm which column names your database uses:
python3 - <<'EOF'
import requests, json
NOTION_TOKEN = "your_token"
r = requests.post("https://api.notion.com/v1/search",
headers={"Authorization": f"Bearer {NOTION_TOKEN}",
"Content-Type": "application/json",
"Notion-Version": "2022-06-28"},
json={})
print(json.dumps(r.json(), indent=2)[:3000])
EOFThe script defaults to Task name, Status, Due, and Project. If your
database uses different names, update the corresponding props.get(...) calls
in both scripts.
# List all tasks
python3 ~/.hermes/skills/productivity/notion-tasks/scripts/notion_tasks.py list
# Create a task
python3 ~/.hermes/skills/productivity/notion-tasks/scripts/notion_tasks.py \
create "Test task" "In progress" 2026-05-10 farm
# Mark done
python3 ~/.hermes/skills/productivity/notion-tasks/scripts/notion_tasks.py \
done "Test task"
# Run enrichment manually
python3 ~/.hermes/skills/productivity/notion-tasks/scripts/gbrain_enrichment.pyAdd the contents of notion-tasks/hermes_system_prompt.md to your Hermes
~/.hermes/config.yaml — both the system_prompt block and the
channel_prompts.default block.
Update the project keyword mapping in the system_prompt to match your projects.
Restart Hermes after editing:
pkill -f hermes && hermes &crontab -eAdd (runs every Sunday at 8pm):
0 20 * * 0 /home/ubuntu/.hermes/hermes-agent/venv/bin/python3 \
/home/ubuntu/.hermes/skills/productivity/notion-tasks/scripts/gbrain_enrichment.py \
>> /home/ubuntu/logs/gbrain_enrichment.log 2>&1
Use the Python binary from Hermes's venv — it has the openai package already
installed. Find your venv path with:
find /home/ubuntu/.hermes -name "python3" -type fOnce set up, send natural language messages from WhatsApp or Slack:
| Message | What happens |
|---|---|
Follow up with vendor sales rep on Thursday |
Creates task under inferred project, converts date |
Sign the legal contracts before Saturday |
Marks matching task as Done |
What's still pending? |
Lists all open tasks |
Push the supplier call to next Friday |
Updates due date |
Drop the old budget task |
Archives the task |
Schedule sales demo for Monday |
Creates task under Sales-project project |
No explicit commands needed — Hermes infers intent from natural language.
Every Sunday, gbrain_enrichment.py:
- Queries Notion for all tasks edited in the last 7 days
- Groups them by project
- Sends each group to OpenAI
gpt-4o-minifor distillation - Writes a summary page to GBrain per project (slug:
Sales-project-active-context, etc.)
The OpenAI API key is read directly from GBrain's config — no separate key needed.
After the first run, GBrain will contain pages like:
# Sales-project — Active Context
Week of 07 May 2026
• Sign the legal contracts — due 09 May
• Follow-up with legal team — key external dependency
• AWS installation completed this week
• 3 of 5 tasks marked Done this week
These pages compound over time as GBrain's weekly put overwrites with the
latest summary, keeping each project page current.
400 error from Notion API
Your integration does not have access to the database. Open the database in
Notion → ... → Connections → add your integration. Also add it to the parent
page if the database is nested.
Hermes responds without running the script
The LLM is hallucinating. Ensure both system_prompt and
channel_prompts.default contain the Notion Tasks block. The key phrase is:
"Hermes has NO internal task list. The ONLY way to create tasks is by running
notion_tasks.py via execute_code."
GBrain Unknown command: page
Your GBrain version uses put <slug> not page create. Run gbrain --help
to confirm available commands.
ModuleNotFoundError: openai
Use the Python binary from Hermes's venv, which already has openai installed:
/home/ubuntu/.hermes/hermes-agent/venv/bin/python3
Tasks created without a project
The project keyword was not matched. Check the PROJECTS dict in
notion_tasks.py and the project mapping in the Hermes system_prompt.
hermes-notion-gbrain/
├── README.md
├── .env.example
├── .gitignore
└── notion-tasks/
├── notion_tasks.py # Notion task CRUD via REST API
├── gbrain_enrichment.py # Weekly cron: Notion → OpenAI → GBrain
└── hermes_system_prompt.md # Hermes config blocks to copy-paste
PRs welcome. Useful additions:
- Support for additional Notion property types (priority, assignee)
- Daily digest skill — summarise today's tasks via WhatsApp
- Multi-database support
- Tests
- Hermes — the agent framework this runs on
- GBrain — the knowledge graph this enriches
- Notion API docs
MIT