Skip to main content

Call Notion's reverse-engineered ✦ AI / Custom Agent endpoint from the command line

Project description

notion-agent-cli

把你的 Notion ✦ AI / Custom Agent 变成一条 shell 命令。

A small Python CLI + library that talks directly to Notion's internal POST /api/v3/runInferenceTranscript endpoint using a token_v2 cookie copied from a logged-in browser session. No notion_manager Go proxy, no account pool — just your own session.

The conversations show up in Notion's ✦ AI chat panel under whichever Custom Agent persona you bind (e.g. Jarvis), so you can switch between talking to your agent from Notion's UI and from the shell.

Status

v0.1.0 — first tagged release. The library is live-validated against Notion's real endpoint and adopted by at least one downstream project (NotionAgents uses NotionAgentClient as its inference backend). See docs/STATUS.md for the full live-test ledger and docs/ROADMAP.md for what's still planned.

Install

pipx install notion-agent-cli      # recommended — isolated venv, one-line upgrade
# or
pip install notion-agent-cli       # if you don't use pipx

For the optional FastAPI HTTP wrapper (notion-agent serve):

pipx install 'notion-agent-cli[serve]'

For local development from a clone, pip install -e ".[dev]". The release flow is in docs/RELEASING.md.

Quickstart

# One-shot setup: paste the full `document.cookie` string copied from
# a logged-in Notion tab (DevTools → Application → Cookies → notion.so,
# right-click any row → "Copy all as ..."). The CLI extracts token_v2 /
# notion_user_id / notion_browser_id, calls /api/v3/loadUserContent to
# fetch workspace metadata, and picks the (only) workspace for you.
notion-agent init --cookie "notion_browser_id=...; notion_user_id=...; token_v2=v03%3A..."

# Want to keep the cookie out of shell history? Read it from stdin:
pbpaste | notion-agent init --cookie -

# Chat (returns the full reply after streaming completes).
notion-agent chat "用一句话确认你在线。"

For Jarvis-style custom agent binding (so threads surface in the ✦ AI chat panel under your agent name), grab the agent's instructions page id from its URL and pass it to init:

notion-agent init --cookie "..." \
                  --agent-name Jarvis \
                  --agent-page-id 2e115375-830d-8184-bf4d-f427d847c6bc

CLI surface

notion-agent init     Bootstrap notion_account.json from a token_v2 cookie.
notion-agent chat     Send one prompt, print the reply (text / --json / --stream / --ndjson).
notion-agent doctor   Validate the account file and ping /loadUserContent.
notion-agent models   refresh — pull the current alias→Notion-id map.
notion-agent agents   list    — custom agents in the bound workspace.
notion-agent threads  list    — recent chat threads (filter by --agent).
notion-agent profile  list / current / use <name> / migrate <name>
notion-agent serve    Local FastAPI server (optional [serve] extra).

Run notion-agent <sub> --help for flag details. Every subcommand accepts --account PATH to point at a non-default credential file.

Continuation (multi-turn chats)

chat saves per-thread continuation state under ~/.notionagents/threads/<thread-id>.json after every successful turn, so the next turn can be a follow-up in the same chat-panel thread:

# Turn 1 — capture the thread id.
THREAD=$(notion-agent chat --json "summarize my day so far" | jq -r .thread_id)

# Turn 2 — reuse it.
notion-agent chat --thread-id "$THREAD" "now translate it to chinese"

The thread's model is locked to whatever turn 1 chose — passing --model on a --thread-id continuation is silently ignored, since mid-thread model switches occasionally make Notion reject the partial transcript.

Multi-workspace profiles

Run notion-agent init once per workspace into a named profile file, then swap between them with profile use:

notion-agent init --cookie "..." --account ~/.notionagents/tplink.json
notion-agent init --cookie "..." --account ~/.notionagents/personal.json
notion-agent profile use tplink   # symlinks notion_account.json → tplink.json
notion-agent profile current      # prints "tplink"
notion-agent profile list         # both, * marks active

If you started before profiles existed, profile migrate <name> renames your existing notion_account.json into a named profile and replaces the original with a symlink — non-destructive, no re-init required.

Local HTTP server

notion-agent serve wraps the CLI in a small FastAPI app for orchestrators (n8n, Make, internal Go services) that prefer HTTP over shell-out. Install with the [serve] extra:

pip install -e ".[serve]"
notion-agent serve --host 127.0.0.1 --port 8000

# In another shell:
curl -sN -X POST localhost:8000/chat \
     -H 'content-type: application/json' \
     -d '{"prompt":"hi","stream":true}'   # SSE; data: {"text":"..."} per chunk
curl -s localhost:8000/healthz
curl -s localhost:8000/agents

Endpoints: POST /chat (blocking JSON or SSE), GET /healthz (doctor's checks, 200 / 503), GET /agents, GET /threads. Error codes match the library's ErrorCode taxonomy so callers branch on code without parsing messages.

Calling this from an AI agent

Two paths, pick the one that matches your runtime:

  • Claude Code — the repo ships a skill at .claude/skills/notion-agent/. Open this repo (or a downstream project that depends on the CLI) and the skill auto-loads via its frontmatter trigger phrases ("ask Jarvis", "Notion AI", "via the chat panel").
  • Anything else (Codex, Gemini, openclaw, your own orchestrator) — read docs/AGENTS.md. It has a paste-ready system-prompt snippet at the bottom covering the CLI contract, preflight, error codes, and safety rules in ~40 lines.

Both paths shell out to the same notion-agent binary — make sure it is on $PATH for whatever runtime you use.

Why this exists

Notion's Custom Agents went paid in May 2026 ($10 / 1k credits, 30–60 credits per run, Business+ only). Their built-in ✦ AI chat is free for any Plus seat but only addressable from the UI — not from a cron job, a webhook, or a shell pipe. This CLI bridges that gap by mirroring exactly what the SPA sends, so you get the same free-quota model from bash / python / wherever.

Reverse-engineering notes + the captured chat-panel traffic that this implementation is built against live in docs/01-notion-chat-protocol.md.

Library use

import asyncio
from notion_agent_cli import NotionAgentClient

async def main():
    client = NotionAgentClient("~/.notionagents/notion_account.json")
    try:
        resp = await client.complete(prompt="今天周几?")
        print(resp.text)
        print(f"usage: in={resp.usage.input_tokens} out={resp.usage.output_tokens}")

        # Reuse the thread for a follow-up:
        followup = await client.complete(
            prompt="and yesterday?", thread_id=resp.thread_id,
        )
        print(followup.text)
    finally:
        await client.aclose()

asyncio.run(main())

Async streaming consumers can pass on_text_delta= (sync) or on_text_delta_async= (coroutine, awaited per chunk — used by the FastAPI SSE branch). For raw NDJSON passthrough use client.stream_lines(...).

The public surface kept stable across v0.1: NotionAgentClient, NotionAgentError, ChatResponse, TokenUsage, ErrorCode. Sub-modules (transcript, ndjson, account, models, profile, serve) are importable but their internals can shift between minor releases.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

notion_agent_cli-0.1.1.tar.gz (92.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

notion_agent_cli-0.1.1-py3-none-any.whl (47.0 kB view details)

Uploaded Python 3

File details

Details for the file notion_agent_cli-0.1.1.tar.gz.

File metadata

  • Download URL: notion_agent_cli-0.1.1.tar.gz
  • Upload date:
  • Size: 92.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for notion_agent_cli-0.1.1.tar.gz
Algorithm Hash digest
SHA256 e3db27aef84895453a588145af695856d66db9262701983694e824a9035d6245
MD5 83051d13eaf9bdb92118233fd7a91969
BLAKE2b-256 69c297f0cd0d92ec75328c34e348dd4e76d0e1dc79bda1eba6833263b9f08336

See more details on using hashes here.

Provenance

The following attestation bundles were made for notion_agent_cli-0.1.1.tar.gz:

Publisher: release.yml on ChenyqThu/notion-agent-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file notion_agent_cli-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for notion_agent_cli-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 dccefa5fd8a713f8655a06aa4e36bcce9597fadb7e8435d197873d6a44ed107f
MD5 a66cc02ee7c01c7bf9cc28a45c36063e
BLAKE2b-256 889de90518d0163678475976c433fa1d5f0264275edf19119181c3117b1b971e

See more details on using hashes here.

Provenance

The following attestation bundles were made for notion_agent_cli-0.1.1-py3-none-any.whl:

Publisher: release.yml on ChenyqThu/notion-agent-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page