Agent stack build plans · № 3 · part 6

The traps

Every one of these is a mechanism, not a mood. Most of them only bite after the cron takes over — which is exactly when you’ve stopped watching.

1 · Cost runaway: daily cron × metered search

Hermes’s web_search and web_extract go through the paid Nous Portal tool gateway, and every call is metered. A thorough agent left uncapped will happily make thirty, forty, fifty calls per morning “to be safe” — and a cron job repeats that every single day, including the days nothing happened on your beat. Whatever one run costs you, the schedule multiplies it by thirty before the next bill. That’s why the briefing hard-caps tool calls per run and prints the count in every report’s Housekeeping line: the report itself is the meter. If the number creeps up week over week, your beat didn’t get busier — your intern got sloppier. Tighten the query list.

2 · execute_code on the local backend

The comforting phrase “sandboxed Python” is doing no work on a default install. execute_code runs Python that can call Hermes’s tools over RPC, and on the local terminal backend it executes as your user, on your machine. This plan has the agent writing its own parsing code against arbitrary web content and running it unattended at 7 a.m. — the one configuration that makes that honest is the docker backend (all capabilities dropped, no-new-privileges, 256-process cap), where the container is the security boundary. If you skipped stage 3 of setup because Docker felt like ceremony, you don’t have a sandboxed intern; you have a cron job with shell access.

3 · The 2,200-character “archive”

The most common misreading of Hermes memory: assuming MEMORY.md is where the past reports live. It’s capped at 2,200 characters — an index card. An intern told to “remember what you’ve covered” via the memory tool will fill the card in under a week, then every new fact evicts an old one, and the dedupe quietly dies while the file still looks full. The archive lives in the layers built for volume: session_search (full-text over ~/.hermes/state.db) and the reports/ directory you grep. Related trap: there is no built-in vector store (as of July 2026), and FTS is keyword matching — a story reworded beyond keyword overlap can slip past the dedupe. Accept the occasional near-duplicate, or graduate to an external memory provider (Mem0, Honcho et al.) once it actually hurts.

4 · Scraper skills rot silently

The failure mode of a self-written scraper is not an error — it’s an empty result. The ministry redesigns its stats page, the selector matches nothing, the script returns zero rows, and the report doesn’t get worse — it gets thinner, which reads as “quiet week.” You can lose a source for a month without noticing. Hence the two mechanical rules in prompt 3: every scraper prints a source-check line (“rows: N”), and the report’s Housekeeping section must flag any scraper that returned empty. Rot you can see costs a morning; rot you can’t costs a month of coverage.

5 · Approval fatigue → write_approval off

Around week two, the approval prompts for skill edits start to feel like bureaucracy, and the tempting fix is switching skills.write_approval off. Now the agent that runs unattended every morning can also rewrite its own tooling unattended — including the briefing skill that contains its rules about caps, paywalls, and politeness. Keep the gate. The volume argument is backwards anyway: a mature intern should be proposing skill changes a couple of times a month, not daily — if approvals are frequent enough to annoy you, the briefing is unstable and that’s the thing to fix.

6 · Assuming RSS, assuming access

Two “surely it does that” failures. First: Hermes has no built-in RSS monitoring — a plan that says “just watch these feeds” is describing a fetch-script skill or an external service wired to the webhook gateway, i.e. work, not a checkbox. Second: no scraper makes closed content open. The intern’s job is awkward-but-open formats; the briefing bans working around paywalls, robots.txt, rate limits, and ToS — and that ban is also self-interest, because a polite scraper is a scraper that still works next quarter. When coverage genuinely requires a paywalled source, the answer is boring: pay for it, and give the intern the legitimate API if one exists.

Disagree? Pin a note on it →