93 lines
3.7 KiB
Markdown
93 lines
3.7 KiB
Markdown
# Delegating tasks to Notion AI Custom Agents via MCP
|
|
|
|
Tested 2026-09-23. Method for having Claude hand off tasks to Notion's
|
|
published Custom Agents (not generic "Notion AI" — specific published
|
|
agents in a workspace) through the Notion MCP connector.
|
|
|
|
## Prerequisites
|
|
|
|
- Notion MCP connected with session tools available:
|
|
`notion-search-agents`, `notion-spawn-session`, `notion-wait-session`,
|
|
`notion-send-message-to-session`, `notion-list-session-events`,
|
|
`notion-search-sessions` / `notion-query-sessions`, `notion-stop-session`.
|
|
- At least one **published** Custom Agent in the target Notion workspace.
|
|
Unpublished/misconfigured agents exist in the list but fail at spawn time.
|
|
- If the agent needs to create/edit pages, it needs edit access granted to
|
|
that specific agent on the target page/teamspace **inside Notion's UI**.
|
|
This permission cannot be granted via MCP — it's Notion-side.
|
|
|
|
## Workflow
|
|
|
|
1. **Discover available agents**
|
|
|
|
```
|
|
notion-search-agents(scope: "workspace", limit: 20)
|
|
```
|
|
|
|
Returns `{url, name, description, icon}` per agent. `url` is in the form
|
|
`agent://<spaceId>/<agentId>` — required for spawning.
|
|
|
|
2. **Spawn a session**
|
|
|
|
```
|
|
notion-spawn-session(agent_url: "agent://...", initial_message: "<task>")
|
|
```
|
|
|
|
Returns `{session_url, status: "running"}` immediately (does not block).
|
|
`session_url` format: `session://<spaceId>/<sessionId>`.
|
|
|
|
Failure mode observed: an unpublished agent throws a clean 400
|
|
`"Agent is not published or configured."` — fails fast, no wasted session.
|
|
|
|
3. **Wait for completion**
|
|
|
|
```
|
|
notion-wait-session(session_url: "...", seconds: 45)
|
|
```
|
|
|
|
Polls up to `seconds` (max 60/call — call again if still running).
|
|
Returns `{status: "completed", message: "<agent's final output>"}`.
|
|
|
|
4. **Follow up in the same session (multi-turn)**
|
|
|
|
```
|
|
notion-send-message-to-session(session_url: "...", message: "<follow-up>")
|
|
```
|
|
|
|
Session retains context — e.g. asking to shorten/revise a draft works
|
|
correctly and keeps prior structure/formatting.
|
|
|
|
5. **Inspect what the agent actually did**
|
|
|
|
```
|
|
notion-list-session-events(session_url: "...", count: 50)
|
|
```
|
|
|
|
Returns a numbered event log: `user.message`, `agent.tool_result`
|
|
(each internal tool call the agent made, with output), `agent.message`
|
|
(final reply). Useful for verifying an agent's self-reported limitation
|
|
is real rather than a hallucinated excuse — e.g. we saw an orchestrator
|
|
agent actually check its own permission/module config before reporting
|
|
it couldn't create a page.
|
|
|
|
## Observed results (3 test agents)
|
|
|
|
| Agent | Outcome |
|
|
|---|---|
|
|
| Single-purpose content agent (e.g. "LinkedIn Post Writer") | Completed cleanly in ~15-20s, good structured output, follow-up edits honored. |
|
|
| Unpublished/misconfigured agent | Spawn rejected immediately with clear error, no session created. |
|
|
| Orchestrator-type agent with only web-search permission | Ran, reasoned, self-reported blocked status with a specific ask (grant edit access to a named parent page) instead of failing silently or hallucinating success. |
|
|
|
|
## Takeaways
|
|
|
|
- Round-trip (spawn → wait → completed) is reliable and fast for
|
|
self-contained generation/drafting tasks.
|
|
- Sessions are stateful — safe to iterate multi-turn rather than re-spawning.
|
|
- Agents accurately self-report permission scope; verify via
|
|
`notion-list-session-events` if you want to confirm rather than trust.
|
|
- For anything requiring page writes, grant edit access to that specific
|
|
Custom Agent on the target page/teamspace in Notion's UI first — this
|
|
step lives outside MCP and cannot be done from here.
|
|
- Always run `notion-search-agents` before spawning; not every listed
|
|
agent is actually usable.
|