The 21 Latest AI Agent Skills, Part 6: Handing Notion, Obsidian, and PDF to the Agent

The document-work part of the 21 agent skills. It covers the Notion API and CLI, the Obsidian vault, and natural-language PDF editing.
Markdown sourceยทAnything to add or correct?

Part 5 polished words. Part 6 touches documents. Notion through its API, Obsidian through files, and PDF through natural-language instructions. All three are handed to the agent, but the method splits into three.

The reason, up front, is this. Notion's documents live in the cloud, so it has to go through the API; the Obsidian vault is just a local folder, so file tools are enough. PDF is both, so it uses a wrapped tool. The tool splits according to where the target lives.

1. notion (v2.0.0)

The productivity category. Built by the community. It is not a single skill but carries two paths.


Notion API + ntn CLI: pages, databases, markdown, Workers.

Integration token


1. Create an integration at https://notion.so/my-integrations
2. Copy the API key (starts with ntn_ or secret_)
3. Save to ${HERMES_HOME:-~/.hermes}/.env:
   NOTION_API_KEY=ntn_your_key_here
4. Share the target page/database with the integration
   In Notion, page menu ... โ†’ Connect to โ†’ the integration name you created

Number 4 is the most practical pitfall in this skill. The skill writes it this way.


Without this, the API returns 404 even though the page exists.

The page exists but a 404 appears. Usually you interpret it as a permission problem and reissue the token or tear down and recreate the integration. In reality, the cause is not sharing it. The Notion API does not tell you through a 404 whether the agent can see the page. It is designed to hide existence.

Installing ntn


curl -fsSL https://ntn.dev | bash
# Or (requires Node 22+, npm 10+)
npm install --global ntn

ntn --version    # verify

And there is an instruction here too.


Skip ntn login. Use the integration token instead.
It works headless, without a browser.

export NOTION_API_TOKEN=$NOTION_API_KEY      # ntn reads NOTION_API_TOKEN
export NOTION_KEYRING=0                       # do not use the OS keychain

Not needing a browser login is the reason this CLI exists. Browser login is impossible in a server environment or a container. The keychain is the same. There is no concept of a keychain on a server. So NOTION_KEYRING=0 drops it to file-based auth (~/.config/notion/auth.json).

Choosing a path at runtime


if command -v ntn >/dev/null 2>&1; then
  # use ntn
else
  # fall back to curl
fi

This is why the skill carries both paths together. Native ntn is not out for Windows yet, so you install it under WSL2 or just use the HTTP path.

File upload is the CLI's biggest win


ntn files create < photo.png
ntn files create --external-url https://example.com/photo.png
ntn files list

Over HTTP it takes three steps. Create upload, PUT the bytes, reference. The CLI reduces this to one line. This difference shows when you upload an image to Notion.

Useful environment variables are also laid out.

VariableEffect
NOTION_API_TOKENAuth token (takes priority over the keychain)
NOTION_KEYRING=0File-based credentials at ~/.config/notion/auth.json
NOTION_WORKSPACE_IDSkips the workspace selection prompt

Path B: HTTP + curl

It is the Windows default and the general-purpose path. Every request uses the same pattern.


curl -s -X GET "https://api.notion.com/v1/..." \
  -H "Authorization: Bearer $NOTION_API_KEY" \
  ...

Page creation and update accept markdown. That is why it fits agents especially well. If you handle Notion's block API directly, you have to wander through the nested block structure, but putting markdown in makes that disappear.

There is also a path that reads a page as markdown. This means it is client-friendly. You read it directly without parsing block JSON.

2. obsidian (v1.0.0)

The note-taking category. Built jointly by Teknium and Hermes Agent.


Read, search, create, and edit notes in the Obsidian vault.

The description is short. A vault is ultimately a folder. The design philosophy of this skill comes from there too.

From the vault path

The environment variable convention is documented.


OBSIDIAN_VAULT_PATH, e.g. ${HERMES_HOME:-~/.hermes}/.env
If not set, ~/Documents/Obsidian Vault

And the pitfall appears right away.


File tools do not expand shell variables.
Do not put a path containing $OBSIDIAN_VAULT_PATH into read_file, write_file, patch,
search_files. Resolve the vault path first and pass a concrete absolute path.
The vault path can contain spaces, which is also why you end up using file tools rather than shell commands.

This is the accident that most often happens to people migrating from the old pattern. If you put the variable in as-is, the file is not visible. If the path has a space, it breaks in the shell too. The two problems overlap and it can look like nothing works no matter how the agent fixes it. In reality it is variable non-expansion.

You can use terminal only when the path is not yet known. Once you know it, you go back to file tools.

Tool mapping

The reason the skill explicitly pushes file tools over shell commands is in the table.


- Read a note: read_file. Prefer over cat (it attaches line numbers and pagination)
- List notes: search_files (target: "files"). Prefer over find or ls
- Search: search_files. Prefer over grep, find, ls
  Filename search: target: "files" + pattern
  Content search: target: "content" + regex + file_glob: "*.md"
- Create a note: write_file. Prefer over a shell heredoc or echo (avoids quoting issues, returns a structured result)
- Append: read with read_file, and if there is a stable anchor, add content to the anchor with patch
  Only rewrite the whole thing with write_file when there is no anchor
- Partial edit: patch. Prefer over shell text substitution

Here you can see the real reason. cat has no line numbers, so re-reading later is hard. find and ls do not give structured results. A shell heredoc breaks because of quotes. write_file does not break and returns a result. Tool choice is not a performance issue but a safety issue.

Two branches of appending


When the anchor is stable: replace the anchor with (anchor + new content) via patch
When rewriting the whole thing is clearer: write_file
When you need a simple addition without an anchor: terminal may be the clearest and safest choice

The skill writing "may be the clearest and safest choice" is practical. It does not dictate the tool. A shell heredoc is not inherently bad, and forcing a patch when there is no anchor can be worse.

Wikilinks


Obsidian links notes with the [[Note Name]] syntax. When creating a note, connect related content with it.

If an agent does not know this when using Obsidian, it creates notes as isolated files. The knowledge graph a person builds does not get created. One line is everything.

3. nano-pdf (v1.0.0)

The productivity category. Community.


Edit text in existing PDFs via natural-language prompts.

It edits PDFs with natural language. No one questions who would even build this for a single entry.

Install


uv pip install nano-pdf     # recommended (already in Hermes)
pip install nano-pdf

Usage


nano-pdf edit <file.pdf> <page_number> "<instruction>"

Three examples.


# Change the title on page 1
nano-pdf edit deck.pdf 1 "Change the title to 'Q3 Results' and fix the typo in the subtitle"

# Update a date on a specific page
nano-pdf edit report.pdf 3 "Update the date from January to February 2026"

# Edit content
nano-pdf edit contract.pdf 2 "Change the client name from 'Acme Corp' to 'Acme Industries'"

You use the instruction as-is. Not "page 3, date January to February" but "Update the date from January to February 2026." English is more natural. The tool is made in English, so the examples are in English too.

Scope and cautions


- For structural tasks (merge, split, forms, watermarks, generation), refer to the pdf skill
- For extracting text from scans, refer to ocr-and-documents

The skill declares its scope precisely and hands off to others. nano-pdf does not claim structural work.

Four pitfalls


- Page numbers may be 0-based or 1-based depending on the version โ€” if the wrong page, retry with ยฑ1
- Always verify the resulting PDF after editing (check file size with read_file, or open it)
- The tool uses an LLM internally โ€” it needs an API key (check the setup with nano-pdf --help)
- It fits text changes well. Complex layout edits may need another method

The second is the part you really have to be careful about. The edit command may succeed while nothing changed. This is the case where the LLM misreads the instruction or cannot find the target text. The tool returns success, but the PDF is unchanged. So the skill forces "always verify."

Checking the file size with read_file does not actually verify the PDF content. If the size is the same, it could have changed without you knowing. To check the body you have to read it separately. This skill stops after requiring only minimal verification. So in practice, opening it yourself after conversion is the right move.

Part 6 Summary

SkillVersionWhat it does
notion2.0.0Integration token + ntn CLI or curl, pages/DB/markdown
obsidian1.0.0Read, search, create, edit the vault with file tools, wikilinks
nano-pdf1.0.0Edit PDF text via natural-language instructions

The three cover all document work. Cloud documents, local documents, and a format that rarely changes. The tool splitting according to the nature of the target is the point of this part.

Next, the final Part 7 moves on to running and deploying local models directly.