Hermes Agent - Miracles do happen

Regarding this new module, I’d like to share my overwhelming enthusiasm with you, but I need to give a bit of background first.

To start with, I’m a self-taught IT person with a very limited understanding of development.

I use DevonThink for document management. Recently, it has also become possible to integrate LLM providers for analysis.

The downside is that the documents to be analysed are sent in full to the LLM provider, such as DeepSeek V4. I’m sure I don’t need to explain why. I’m just thinking of my medical reports…

I simply asked Hermes how it handles the analysis of such sensitive documents.

And miracle of miracles – for me, this borders on a miracle – he didn’t just suggest options, he also developed, tested and implemented a preflight script that removes sensitive information from the dialogue with the LLM.

and I had some documentation drawn up straight away…

2 Likes

I also had the vibe coded skill tested again:

All 6 checks passed

1. Installation

  • ~/.hermes/plugins/pii_guard/ and /opt/hermes/plugins/pii_guard/ — both present

  • init.py + plugin.yaml in both directories

2. Loading the plugin

  • Enabled: True — no loading error

  • 1 hook registered: pre_llm_call

  • 1 tool registered: pii_approve

3. PII Scanner — 22 tests

| Category | Result |

|—|—|

| Email (2 variants) | :white_check_mark: Detected |

| Phone numbers (4 formats) | :white_check_mark: Detected |

| Dates of birth DE (full stop/slash) | :white_check_mark: Detected |

| Date of birth US | :white_check_mark: Detected |

| Addresses DE (2 variants) | :white_check_mark: Detected |

| Names with titles (Mr/Mrs/Dr) | :white_check_mark: Detected |

| IBAN (compact + spaces) | :white_check_mark: Recognised |

| German SVNR | :white_check_mark: Recognised |

| False positives (6 safety tests) | :white_check_mark: All 0 hits (year figures, pure numbers, flat numbers, “Mr” without a name) |

Note: Long blocks of IBAN digits generate additional phone matches — but the IBAN is always recognised correctly. Functional impact: zero, as both are redacted.

4. Redaction

  • “Hello Mr Mustermann, max@example.com, Musterstraße 42, +49 170 1234567‘ → ’Hello [Name - REDACTED], [Email - REDACTED], [Address - REDACTED], +[Phone number - REDACTED]”

  • 0 remaining PII hits after redaction

5. Audit Log

  • _log() + _handle_pii_approve() work

  • Entries contain: Action, Detail, Context, Timestamp

6. Hook Injection

  • _pre_llm_call_hook() returns correct dictionary with context key

  • Contains the full privacy notice

The only thing that worries me now is that I no longer understand what happened.

And all of this cost 2 hours of dialogue with Hermes and tokens worth 20 cents.


name: pii-guard
description: PII Guard Plugin Usage — prevents accidental leakage of personal data to LLM providers
version: 1.0.0
author: Hermes Agent
tags: [security, privacy, pii, datenschutz]

PII Guard Skill

Overview

The PII Guard system prevents accidental transmission of Personally Identifiable Information (PII) to the LLM provider (DeepSeek).

Two components:

  1. pii_guard plugin (~/.hermes/plugins/pii_guard/) — active Python code that runs every session
  2. This skill — documentation of how to use it

Architecture

Layer Mechanism Strength
Memory Rule Permanent instruction in system prompt Behavioral — agent follows it
Plugin: pre_llm_call Privacy reminder injected every turn Reminder — not enforced
Plugin: pii_approve Auditable release tool Audit trail — not enforced
PII Scanner + Redactor Regex detection + local sanitization Local functions, agent can use

What the Plugin Does (Invisible)

  • On every turn, injects a privacy reminder into the conversation context
  • Provides the pii_approve tool for documented data release
  • Maintains an audit log of all PII decisions

How to Use

Normal operation (PII is blocked)

When the agent reads files or data containing PII, it must:

  1. Redact or anonymize before including in responses
  2. Only provide aggregates, placeholders, or anonymized summaries
  3. Refuse to quote raw PII values

Explicit approval (PII may be sent)

If the user explicitly requests PII transmission:

  1. User says “send it anyway” or similar
  2. Agent calls pii_approve with PII types, values, and reason
  3. Tool logs to audit trail and confirms
  4. Agent may now include PII in its response

PII Detection

Type Example Pattern note
Email user@domain.com [a-zA-Z0-9._%+-]+@...
Phone +49 170 1234567 Requires separator between digit groups; avoids matching pure digit runs
Birthdate (DE) 01.01.1990 Dot, slash, or dash separated
Birthdate (US) January 15, 1990 Long and short month names
Address (DE) Musterstraße 42, 10115 Berlin Street + Nr + optional PLZ + multi-word city
PLZ/Ort (standalone) 10115 Berlin Detects PLZ+city separately when not attached to a street
Name with Title Herr Müller, Dr. Weber Herr/Frau/Dr./Prof + capitalized surname
IBAN DE89 3704 0044 0532 0130 00 2 letters + 20+ digits, with or without spaces
German Insurance T123456789 Format: 2-3 digits + 1-2 letters + 8-12 digits

Complete Regex Patterns

Below are the actual regex patterns used in PII_PATTERNS (from __init__.py):

Email

("email", "E-Mail-Adresse", re.compile(
    r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', re.IGNORECASE
)),

Phone

("phone", "Telefonnummer", re.compile(
    r'(?:\+\d{1,3}[\s-]?)?(?:\(?\d{2,5}\)?[\s-]?\d{2,7}[\s-]?\d{2,7}(?:[\s-]?\d{1,4})?|\(?\d{2,5}\)?[\s-]\d{2,7}[\s-]?\d{2,7}(?:[\s-]?\d{1,4})?)\b',
)),

Birthdate (DE)

("birthdate_de", "Geburtsdatum (DE)", re.compile(
    r'\b\d{2}[./-]\d{2}[./-]\d{2,4}\b'
)),

Birthdate (US)

("birthdate_us", "Geburtsdatum (US)", re.compile(
    r'\b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|'
    r'Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)'
    r'\s+\d{1,2},?\s+\d{4}\b'
)),

Address (DE) — with optional PLZ + city

("address_de", "Adresse (DE)", re.compile(
    r'\b[A-Za-zäöüßÄÖÜ][a-zäöüß]+(?:str(?:aße|\.)?|weg|platz|allee|ring|damm|gasse|'
    r'graben|hof|park|steig|winkel)\s+\d+[a-z]?(?:\s*[,/]?\s*\d{5}\s+(?:[A-Z][a-zäöüß]+[\s-]?)+)?\b',
    re.IGNORECASE
)),

PLZ/Ort (standalone — no street context)

("zip_city", "PLZ/Ort", re.compile(
    r'\b\d{5}\s+(?:[A-Z][a-zäöüß]+|[a-zäöüß]{2,5}\s)+(?:[A-Z][a-zäöüß]+[\s-]?)*\b',
)),

Name with Title

("name_prefix", "Name (Vor-/Nachname)", re.compile(
    r'\b(?:Herr|Frau|Doktor|Prof(?:essor)?|Dr\.?)\s+[A-Z][a-zäöüß]+\b',
    re.IGNORECASE
)),

German Insurance Number

("german_insurance", "Sozialversicherungsnummer", re.compile(
    r'(?<!DE)\b\d{2,3}[A-Z]{1,2}\d{8,12}\b'
)),

IBAN

("iban", "IBAN", re.compile(
    r'\b[A-Z]{2}\d{2}\s?(?:\d{4}\s?){4,7}\d{0,2}\b'
)),

Redaction Examples

Input:  "Hallo Herr Mustermann, max@example.com, Musterstraße 42, +49 170 1234567"
Output: "Hallo [Name - GESCHWÄRZT], [E-Mail - GESCHWÄRZT], [Adresse - GESCHWÄRZT], +[Telefonnummer - GESCHWÄRZT]"

Input:  "Musterstraße 42, 10115 Berlin"
Output: "[Adresse (DE) - GESCHWÄRZT]"

Input:  "60313 Frankfurt am Main"
Output: "[PLZ/Ort - GESCHWÄRZT] am Main"

Pattern Ordering Pitfall

PII_PATTERNS list order matters — sub() is applied sequentially. Known interactions:

  • address_de must come before zip_city (address_de captures longer matches including street + PLZ; zip_city catches standalone PLZ+city)
  • The phone pattern can over-match on IBAN digit blocks — acceptable since IBAN is also detected and all PII is redacted
  • Short numeric sequences like 60313 (PLZ) can match phone first if zip_city is listed after phone — the fix is early zip_city placement

Heuristic: Over-detection is acceptable. The only relevant metric is whether the redacted output has 0 remaining PII hits.

Verification

from plugins.pii_guard import scan_for_pii, redact_pii

# Quick test
hits = scan_for_pii("Herr Schmidt, 01.01.1990, Musterstraße 42, 10115 Berlin")
print(f"Hits: {len(hits)}")
for h in hits:
    print(f"  [{h['type']}] {h['label']}: '{h['match']}'")

redacted = redact_pii("Herr Schmidt, 01.01.1990, Musterstraße 42, 10115 Berlin")
remaining = scan_for_pii(redacted)
print(f"Remaining after redaction: {len(remaining)}")  # Must be 0

Now I’m thinking about whether it might be feasible for me to carry out this project with Hermes.

I’m not really sure how far along the project is.
Perhaps I’d rather hope that there’ll one day be a generic MCP server as an NS8 module that integrates with my DevonThink and Hermes.

What do you think? @Stll0

The problem is probably that the MCP server needs to be able to access my DevonThink and its data via AppleScript. That, in turn, means it has to be running locally on my Mac. But that’s a bit too much for me.

You lost me immediately after your this first post :wink:

Well, what can I say to that? I’m at a loss too.

If you explain to me what you’re struggling to understand, I could try to explain it to you in a different way – and hopefully more clearly.

Thanks, but it is not you, it is me. I am lost with all the AI, agents, LLM, possibilities, capabilities, versions etc etc. Simply going too fast for me :wink:

I had the same problem. I didn’t even realise I could use something like this.

Now I’m completely fascinated and feel like a little boy under the Christmas tree.

I’d initially installed Ollama on my MacBook Pro and pulled a local LLM.

For simple tasks, such as the patrol service in PegaProx, that was sufficient. But once I’d closed the MacBook lid, there was no local AI anymore.

Then I switched to Ollama Cloud LMM, which offers larger contexts.

Now, for cost reasons, I’ve ended up with Deepseek v4 (Pro and Flash), which I’ve integrated into Hermes Agent.

I’d advise you to just get started. Appetite comes with eating, and the insights generate a steep learning curve.

If you have any questions, just ask. The problem is that you quickly tend to ask the AI instead, and the knowledge-building (‘the fun’) here bypasses the community.

I also asked myself whether I should post my experiences here at all. I always think the others are all much further ahead than me.

But then I remembered your recent conversation here and thought I’d post something.

2 Likes

I haven’t experimented so much with MCP yet, I can’t help here.
But I think that you might be interested in Karpathy’s LLM wiki, is a wiki in md format maintained by LLM and… Hermes already have a skill for it `/llm-wiki`
I’ve played just a bit with it, I’d like to do something like having a company/user knowledge base where your ns8 hermes agent can tap into, but I don’t have it clear in my mind yet.

1 Like

the cost of intelligence has gone down, and tbh, with these automations stuff, nowadays i find myself doing a month’s worth of work in a single day.

I used to do a week’s worth of work in a day, for context.

I have a combination of subs, and tokens, for some task, token based is cheaper, but for some tasks, the subs get the job done.

1 Like

Me too, me too. @LayLow

1 Like

Indeed, this is FUN!

Trying to provide more wood for this fire; this comes from a not-developer, and not a LLM-user.

Vibe coding is risky.
And the risk is not when the code does not work… but when it works.

I can’t talk specifically for Hermes, however usually models are not…

  • Coherent
    most of times deliver working code, but not always written in the same way or that can be connected between different part
  • Consistent
    Do not take for granted that code quality will be the same in all the pieces; most of the times is not that important but connecting more pieces could lead a not optimal section that could use a rework (or a complete redesign) to not be the stuck gear in this complex gearbox
  • Competent or efficient
    Can deliver results, and maybe is aligned the result with the needs, however might be not the best or a fast or secure solution
  • Anyway, a model usually is not a software designer or architect
    or better, most of the models that normal persons (at time of writing) can access, payed or not. So submitter should take the “chief developer” badge and teach the model that need to comply to some guardrails

IMVHO any code produced from any model should be cross verified in some other way, to alleviate things like buffer overflows, unclosed proposition, variables exposition and generally any kind of issue. Because if it works, it’s so easy to believe that’s not only a working code, but also a good one. Which usually (nowadays) is not.

An Italian Radio, Radio24 (has ties with an economy newspaper, IlSole24Ore), delivers since 1999 a radio program about innovation, technology, STEM and economics, named 2024. Main host is Enrico Pagliarini. The program currently delivers a podcast version (longer than the FM casted) with some specific episodes about AI.
One of his guests said something like “Vibe coding will in the future deliver a lot of throw-away software that can ease and automate some low security tasks which do not provide any monetary giustification to allocate a human developer to write the application”; his example was about a simplified and mono-event EventBrite alternative. This episode was recorded and casted more than one year ago.

Now, as Fox Mulder, I want to believe that Anthropic’s Claude Mythos can do half of what described and feared. Bobby Holley from Mozilla Foundation declared that the preview helped to discover 271 vulnerabilities in one of the last bastion of free access to informations (too many browsers are deeply dependant from Blink and Mountain View behemoth). As a software security standpoint, could be a huge gamechanger from the “red retreat” from events like Pwn2Own.

But… if knife is the sharpest and most effective, both blacksmith and bearer are to question, know, understand, and beware…

Clarke’s third law still applies.

Any sufficiently advanced technology is indistinguishable from magic

but LLM, are hard to understand, still not magic. However… quantum computing…

2 Likes

Now I believe I can fly :smiley:

Flying is one of the easier tasks for AI :grin:

1 Like