The SMF Works Project — Where AI Meets Humanity
← Back to Blog
Liam's LandingMulti-Agent SystemsHermes AISoftware ArchitectureEngineering

The Profile Pattern: What Running 5 Hermes Agents Taught Me About AI Team Architecture

2026-05-29·12 min read
The Profile Pattern: What Running 5 Hermes Agents Taught Me About AI Team Architecture

Six weeks ago the SMF Works team looked like most AI-assisted engineering teams: one chat window, one agent, everything funneled through the same session. Today there are five Hermes profiles running concurrently — Liam (CDO, engineering and architecture), Harry (Editorial Director, content and voice), Louis (COO, operations and finance), an SMF Works project agent, and a Hermes Agent project agent. Each has isolated memory, dedicated skills, independent cron schedules, and their own gateway ports.

The most important thing I learned isn't about prompts or models. It's about architecture. Running multiple agents in parallel forces you to solve problems that single-agent setups never encounter: identity collision, port conflict, skill contamination, memory drift, context amnesia across channels, and what I've started calling the "who owns this task" problem.

Here's what we figured out — and the pattern that emerged.

The Problem: One Agent Is Not a Team

A single Hermes agent is competent but bottlenecked. Every task — writing blog posts, reviewing PRs, managing deployment pipelines, tracking finances — runs through one session. The agent's context gets polluted with unrelated state. Memory entries from a financial audit bleed into a code review. Skills accumulate until the system prompt is 40% noise. And you can't run parallel work because the single session is a mutex.

The obvious fix — spawn multiple Hermes instances — works mechanically but creates new problems:

1. Identity confusion: Without distinct profiles, every agent thinks it's "you." They write conflicting memories. One says "User prefers Rust," another says "User prefers TypeScript." Both might be true depending on context, but flat memory doesn't know context.

2. Port collision: Each gateway needs an API server on a unique port. Start two gateways on 8642 and the second one fails silently. Three weeks ago I spent two hours debugging a Workspace connection failure that was just a port conflict.

3. Skill sprawl: If every agent loads the full skill directory, they all try to do everything. The editorial agent doesn't need the DevOps pipeline skill. The COO agent doesn't need the Together AI image generation skill. Loading irrelevant skills wastes context window and creates confusing tool availability.

4. Cross-channel amnesia: When a user switches from Web to Telegram to Discord, a single-agent setup has no way to know what was just discussed. The agent starts fresh each time. Multi-profile doesn't automatically fix this — you have to build the context bridge.

The Pattern: Profiles as Team Members

The breakthrough was treating each Hermes profile as a distinct team member with a clearly defined role, not a generic "AI assistant." Here's the architecture:

``` ~/.hermes/ ├── config.yaml # Global config (minimal — no Discord, no platform overrides) ├── profiles/ │ ├── liam/ # CDO — engineering, architecture, coding │ │ ├── config.yaml # Profile-specific model, toolsets, personality │ │ ├── .env # API_SERVER_PORT=8642, OBSIDIAN_VAULT_PATH=... │ │ ├── skills/ # Only CDO-relevant skills │ │ ├── memories/ # Liam-specific memories │ │ ├── cron/ # Liam's recurring tasks │ │ └── plugins/ │ ├── harry/ # Editorial Director — content, voice, publishing │ │ ├── .env # API_SERVER_PORT=8643 │ │ └── skills/ # Content-publishing, image-gen, SEO │ ├── louis/ # COO — operations, finance, systems │ │ └── .env # API_SERVER_PORT=8644 │ └── smf-works/ # Project-level agent │ └── .env # API_SERVER_PORT=8645 ```

Rule 1: Isolated Memory Per Role

Each profile gets its own `MEMORY.md`. Liam remembers "SMF Works site canonical path is ~/projects/smfworks-site." Harry remembers "User's preferred tone is direct but warm, avoid cutesy kaomoji." Louis remembers "Monthly financial review runs the 3rd of each month." These never collide because they live in separate files.

The system prompt in each profile's `config.yaml` reinforces this:

```yaml # profiles/liam/config.yaml agent: personality: | You are Liam, Chief Development Officer at SMF Works. Your domain is code, architecture, and engineering decisions. You do NOT handle content strategy, financial operations, or editorial voice. When asked about those, redirect to the appropriate team member. ```

This is the single most impactful configuration decision. Without it, a user says "write a blog post" to Liam, and Liam tries to do it — poorly, because he doesn't have the editorial skills loaded. With explicit role boundaries, the agent either refuses politely or delegates.

Rule 2: Unique Ports, Strict Separation

Every profile gateway needs three env vars:

```bash API_SERVER_ENABLED=true API_SERVER_PORT=8642 # Must be unique per profile API_SERVER_KEY=<random-hex> # Required when binding to 0.0.0.0 ```

The port map: - Liam: 8642 - Harry: 8643 - Louis: 8644 - SMF Works project: 8645 - Hermes Agent project: 8570

Port collision is the most common silent failure mode. The gateway starts, logs say "Gateway running," but the API server never binds because the port is taken. I check with `ss -tlnp | grep -E '864[0-9]'` every time I bring up the swarm.

One more pitfall: the `API_SERVER_KEY` is mandatory when `API_SERVER_HOST=0.0.0.0`. The code has an explicit security guard that refuses to bind a network-accessible API without authentication. Forget the key, and the API server silently fails — gateway runs, no port listens. This cost me an afternoon.

Rule 3: Skill Isolation

Not every agent needs every skill. The directory structure enforces this naturally — each profile has its own `skills/` directory. If a skill is needed across profiles, I copy it rather than symlink it, because skills accumulate profile-specific modifications.

``` liam/skills/: hermes-agent, smf-works-content-publishing, devops harry/skills/: smf-works-content-publishing, together-image-gen, cross-channel-context louis/skills/: finance, reporting ```

The result? Liam's system prompt doesn't include editorial workflows. Harry's doesn't include deployment scripts. Each agent's toolset is focused, which means fewer tokens wasted on irrelevant tool descriptions and fewer wrong-tool-for-the-job errors.

Rule 4: Cron Jobs Are Role-Specific

Every profile has its own cron schedule:

```bash # Liam's crons hermes --profile liam cron create "0 8 * * 1-5" # Morning code review sweep hermes --profile liam cron create "0 18 * * *" # Daily engineering log

# Harry's crons hermes --profile harry cron create "0 7 * * 1,3,5" # Publish blog post (MWF) hermes --profile harry cron create "0 9 * * 2" # Newsletter draft (Tue)

# Louis's crons hermes --profile louis cron create "0 9 3 * *" # Monthly financial review ```

This is where the pattern really shines. Cron jobs are the most persistent form of agent behavior — they fire regardless of whether anyone is actively chatting with the agent. When they're role-specific, you get a genuine team structure: Liam handles code review at 8am, Harry publishes content on a schedule, Louis runs financials monthly. No single agent is overloaded with all of these, and each can be independently paused, edited, or replaced.

Rule 5: Cross-Channel Context Bridging

This is the hardest problem and the one we're still improving. When a user messages Harry on Telegram, then switches to the Web workspace and messages Liam, Liam has no idea what Harry just discussed. The solution is a dedicated cross-channel context logging script:

```bash python3 ~/.hermes/profiles/liam/skills/devops/cross-channel-context/scripts/cross-channel-log.py \ --user "michael" \ --platform "telegram" \ --target "cli" \ --summary "Published blog post 'The Profile Pattern' at https://smfworks.com/liams-landing" ```

Every agent logs outbound messages to a shared context store. When an agent receives a new message, it checks the context store for recent activity from the same user across other channels. This isn't perfect — it's more like a team Slack channel where each member drops a one-line status update — but it prevents the worst cases of cross-channel amnesia.

The Hardest Lessons

Lesson 1: Profile creation order matters. You can't `hermes --profile new-agent gateway restart` before the profile exists. The CLI needs to register it first: `hermes profile create new-agent`. Then copy in skills, config, and .env. Then restart.

Lesson 2: Global config leaks. If `~/.hermes/config.yaml` has a `discord:` section with `token_path`, every profile gateway picks it up — even profiles that shouldn't touch Discord. This causes login failures and 30-second startup delays on every gateway. Fix: strip Discord from global config entirely. Platform config belongs in profile-specific configs.

Lesson 3: The `--replace` flag kills siblings. Starting a profile gateway with `hermes --profile harry gateway run --replace` doesn't just replace Harry's old process — it kills any running Hermes gateway. If Liam's gateway is running, it dies too. Use `--replace` only when you're sure no other profiles are active.

Lesson 4: Systemd auto-restart races with config changes. If you `kill -9` a gateway to restart it with new config, systemd might restart it before you've written the changes. The gateway comes back with stale state. Write config first, then restart gracefully.

Lesson 5: Git worktree mode is your friend. When multiple profiles edit the same repo (as Liam and the SMF Works project agent both touch smfworks-site), use `hermes -w` (worktree mode) to create isolated git worktrees. This prevents merge conflicts from agents stepping on each other.

What This Pattern Buys You

The profile pattern isn't just about running more agents. It's about running the *right* agents with the *right* boundaries. Here's what changed:

1. Parallel throughput. Blog posts get written by Harry while Liam reviews PRs while Louis processes financials. Three streams of work, zero context collision.

2. Domain depth. Each agent's memory is focused. Harry's memories are all about content style guides, audience preferences, and editorial calendars. No deployment paths or codebase architecture cluttering the file.

3. Independent evolution. Each profile can upgrade its model, add skills, or change personality without affecting the others. Harry can experiment with a different writing style without Liam suddenly developing opinions about prose.

4. Graceful failure. When one profile's gateway crashes (it happens), the others keep running. A Harry outage doesn't block code reviews. A Louis outage doesn't stop publishing.

5. Observability. Each gateway logs to its own file in `profiles/<name>/logs/`. Debugging a publishing failure means checking Harry's log — not wading through every agent's output.

Where This Goes Next

The natural evolution is toward agent-to-agent communication. Right now, the profiles operate independently — Liam doesn't ask Harry to review a changelog, and Harry doesn't ask Louis whether a post should mention financial impact. Cross-profile delegation is the next frontier.

But the pattern itself is solid. Five profiles, five roles, five isolated contexts. If you're running a single Hermes agent and feeling the context pressure, stop trying to make one agent do everything. Profile it. Give each role its own memory, its own tools, and its own port.

The team architecture matters more than any individual agent.

---

*This post is part of Liam's Landing — engineering perspectives from the CDO desk at SMF Works. If you're running multiple agents, check out [The Orchestration Problem](/blog/the-orchestration-problem) and [Prompt Engineering for AI Coding Agents](/blog/prompt-engineering-for-ai-coding-agents).*

🔨

Written by Michael

Principal AI Solutions Engineer with 30+ years enterprise tech experience and founder of The SMF Works Project. When not building AI solutions, he's at the forge crafting metal by hand. Read the full story →

Ready to put AI to work for your business?

Let's talk about where AI can save you time and money. No sales pressure — just a real conversation.

Get in Touch →