Welcome to FlowZap, the App to diagram with Speed, Clarity and Control.

Hermes Agent Multi-Tenant Setup: Profiles, Sandboxing, and Kanban for Multiple Clients

5/14/2026

Tags: Hermes Agent, multi-tenant, profiles, sandboxing, Kanban, Docker, Telegram

Jules Kovac

Jules Kovac

Business Analyst, Founder

Hermes Agent Multi-Tenant Setup: Profiles, Sandboxing, and Kanban for Multiple Clients

You built a Hermes Agent. It works. Then a client says: "Can I get one of those?"

The solopreneur's edge is build once, sell to many. Hermes ships with profile-based isolation that is the right foundation for multi-client deployments — but profiles alone are not a complete security boundary. This article shows what profiles actually isolate, where you need to add sandboxing, and how Kanban boards keep multi-team work organized.

 

 

What Are Hermes Profiles?

A profile is a fully independent agent instance with its own config.yaml, .env, SOUL.md, memory store, session history, skills, cron jobs, and gateway state.

 

hermes profile create acme
# Now: acme chat, acme gateway start, acme cron list

 

What profiles isolate: Hermes state. Profile A cannot read Profile B's memory, sessions, or cron jobs.

What profiles do NOT isolate: The filesystem. On the default local terminal backend, every profile runs as your OS user with the same file access as any other process you own.

 

 

Can Hermes Agent Support Multiple Clients on One Server?

Yes — with the right guardrails.

 

 

The Isolation Reality

Layer Isolated by Profiles? What You Must Add
Memory (SQLite DB) Fully Nothing
Sessions Fully Nothing
API keys (`.env`) Fully Nothing
Telegram bot Token lock enforced One token per running gateway
Filesystem Not on local backend terminal.cwd, Docker, SSH, or Modal backends
Execution Not on local backend Docker sandbox, Modal, or Singularity
Dashboard visibility Shared dashboard can expose profiles and Kanban work across the same host Keep the shared dashboard private; a client-facing dashboard needs a separate isolated Hermes runtime, not just a profile-scoped process

Without filesystem restrictions or a sandbox, one client-facing session may access files available to the host user account. Always pair profiles with a sandboxed terminal backend for client-facing work.

 

 

Architecture Overview

external_users { # External Clients
  n1: circle label="Client A User"
  n2: circle label="Client B User"
}

shared_host { # Shared Host Environment
  n3: rectangle label="Reverse Proxy"
  n4: rectangle label="Shared Gateway"
  n5: rectangle label="Admin Dashboard"
  n6: rectangle label="Profile: acme"
  n7: rectangle label="Profile: beta"
  n8: rectangle label="kanban.db"
  n9: rectangle label="Host Filesystem"
}

client_a_tools { # Client A Internal
  n10: rectangle label="Engineering tools"
  n11: rectangle label="Support tools"
  n12: rectangle label="Research tools"
}

external_users.n1.handle(right) -> shared_host.n3.handle(left) [label="webhook"]
external_users.n2.handle(right) -> shared_host.n3.handle(left) [label="webhook"]
shared_host.n3.handle(right) -> shared_host.n4.handle(left)
shared_host.n4.handle(right) -> shared_host.n6.handle(left) [label="Token A"]
shared_host.n4.handle(bottom) -> shared_host.n7.handle(top) [label="Token B"]
shared_host.n4.handle(top) -> shared_host.n5.handle(bottom) [label="ops only"]
shared_host.n6.handle(right) -> client_a_tools.n10.handle(left) [label="/engineering"]
shared_host.n6.handle(right) -> client_a_tools.n11.handle(left) [label="/support"]
shared_host.n6.handle(bottom) -> client_a_tools.n12.handle(top) [label="/research"]
shared_host.n6.handle(bottom) -> shared_host.n8.handle(top) [label="shared board"]
shared_host.n7.handle(bottom) -> shared_host.n8.handle(top) [label="shared board"]
shared_host.n6.handle(bottom) -> shared_host.n9.handle(top) [label="local backend risk"]
shared_host.n7.handle(bottom) -> shared_host.n9.handle(top) [label="local backend risk"]

 

 

Critical: The Dashboard Problem

A single Hermes dashboard instance pointed at the shared Hermes runtime shows more than one profile's work on the same host.

This is not a customer-facing multi-tenant portal. It is an internal operator console. The Kanban docs are explicit that Kanban is shared across all Hermes profiles, stored in ~/.hermes/kanban.db, and that tasks are profile-agnostic by design.

The fix is straightforward:

 

  1. Keep the shared dashboard as your private ops console. Never give clients access to it.
  2. For client-facing dashboards, run a separate isolated Hermes runtime per client, not just a profile-scoped dashboard process. In practice that means a separate install, container, VM, or at minimum a separate OS-user/runtime boundary.
  3. Put each behind its own subdomain with authentication (nginx reverse proxy + basic auth or OAuth). Never let a client hit the shared instance.
  4. Or skip the dashboard entirely — many solopreneurs operate purely through Telegram channels and never expose a web UI to clients.

The rule is simple: one client-visible dashboard = one isolated Hermes runtime. If a client needs stronger separation than that, move them to a separate host or container with its own Hermes installation.

 

 

Are Hermes Profiles Secure Enough for Multi-Tenant Use?

Profiles are a foundation, not a complete solution. Security depends on what you add around them.

 

 

Minimum Security Checklist

 

# 1. Fresh profile (never --clone from personal)
hermes profile create client-x

# 2. Restrict workspace
client-x config set terminal.cwd /var/hermes-clients/client-x

# 3. Use a sandboxed backend
client-x config set terminal.backend docker

# 4. Set a separate bot token
nano ~/.hermes/profiles/client-x/.env
# TELEGRAM_BOT_TOKEN=789012:ABC-DEF-...

# 5. Disable irrelevant toolsets
client-x config set agent.disabled_toolsets '["flowzap","creative","media"]'

# 6. Start its gateway
client-x gateway start

 

Why --clone is risky: It copies your personal config, API keys, and memory into the new profile. Always create fresh profiles for clients.

 

 

Telegram Bot Tokens

Each running gateway should use its own bot token. If two profiles share the same token, the second gateway is blocked with a clear error.

 

ERROR: [Telegram] Bot token already in use by profile acme (PID X).

 

For multi-department clients, either use one profile with internal routing (simpler) or create multiple Telegram bots with separate tokens.

 

 

Architecture Options: 4 Setup Patterns

 

Option 1: Single Client, Single Department

 

external_actor { # External Actor
  n1: circle label="Client User"
}

hermes_runtime { # Hermes Runtime
  n2: rectangle label="Telegram Bot"
  n3: rectangle label="Gateway"
  n4: rectangle label="Profile: client-x"
}

execution_sandbox { # Execution Boundary
  n5: rectangle label="Isolated Workspace"
}

external_actor.n1.handle(right) -> hermes_runtime.n2.handle(left) [label="message"]
hermes_runtime.n2.handle(right) -> hermes_runtime.n3.handle(left)
hermes_runtime.n3.handle(right) -> hermes_runtime.n4.handle(left) [label="routes"]
hermes_runtime.n4.handle(right) -> execution_sandbox.n5.handle(left) [label="executes code"]

 

Use for: First client, proof-of-concept, simple Q&A bots.

 

 

Option 2: Single Client, Multiple Departments (Internal Routing)

One profile, one bot. The SOUL.md routes by prefix (/engineering, /support).

 

team_users { # Client Entry Points
  n1: circle label="Team User"
}

entry_point { # Bot & Routing
  n2: rectangle label="Shared Bot"
  n3: rectangle label="Gateway"
  n4: diamond label="Prefix Router"
}

hermes_profile { # Unified Profile
  n5: rectangle label="Profile: acme"
}

department_modes { # Internal Logic
  n6: rectangle label="Engineering Mode"
  n7: rectangle label="Support Mode"
}

team_users.n1.handle(right) -> entry_point.n2.handle(left) [label="/eng or /support"]
entry_point.n2.handle(right) -> entry_point.n3.handle(left)
entry_point.n3.handle(right) -> entry_point.n4.handle(left)
entry_point.n4.handle(right) -> hermes_profile.n5.handle(left) [label="loads profile"]
hermes_profile.n5.handle(right) -> department_modes.n6.handle(left) [label="if /eng"]
hermes_profile.n5.handle(right) -> department_modes.n7.handle(left) [label="if /support"]

 

Use for: A client with 2-3 teams sharing one chat channel.

 

 

Option 3: Multiple Clients, Separate Bots (Core Multi-Tenant)

Each client gets their own bot token, gateway, and isolated profile.

 

external_tenants { # External Tenants
  n1: circle label="Client A User"
  n2: circle label="Client B User"
}

client_gateways { # Per-Token Entry Points
  n3: rectangle label="Gateway A"
  n4: rectangle label="Gateway B"
}

hermes_profiles { # Isolated Profiles
  n5: rectangle label="Profile: acme"
  n6: rectangle label="Profile: beta"
}

execution_sandboxes { # Execution Boundaries
  n7: rectangle label="Sandbox A"
  n8: rectangle label="Sandbox B"
}

external_tenants.n1.handle(right) -> client_gateways.n3.handle(left) [label="Token A"]
external_tenants.n2.handle(right) -> client_gateways.n4.handle(left) [label="Token B"]
client_gateways.n3.handle(right) -> hermes_profiles.n5.handle(left)
client_gateways.n4.handle(right) -> hermes_profiles.n6.handle(left)
hermes_profiles.n5.handle(right) -> execution_sandboxes.n7.handle(left) [label="Docker / Modal"]
hermes_profiles.n6.handle(right) -> execution_sandboxes.n8.handle(left) [label="Docker / Modal"]

 

Use for: 2+ paying clients. Each gets "their own bot" from one server.

Tip: Create fresh profiles (hermes profile create client-x), never --clone. No inherited API keys, no cross-client memory leaks.

 

 

Option 4: Full Multi-Tenant with Departments

 

client_users { # External Participants
  n1: circle label="Acme Users"
  n2: circle label="Beta Users"
}

entry_gateways { # Client Gateways
  n3: rectangle label="Acme Gateway"
  n4: rectangle label="Beta Gateway"
}

hermes_profiles { # Routed Profiles
  n5: diamond label="Acme Router"
  n6: rectangle label="acme-eng"
  n7: rectangle label="acme-support"
  n8: rectangle label="beta"
}

execution_sandboxes { # Secure Runtimes
  n9: rectangle label="Acme Sandbox"
  n10: rectangle label="Beta Sandbox"
}

client_users.n1.handle(right) -> entry_gateways.n3.handle(left) [label="/eng or /support"]
client_users.n2.handle(right) -> entry_gateways.n4.handle(left) [label="general"]
entry_gateways.n3.handle(right) -> hermes_profiles.n5.handle(left)
hermes_profiles.n5.handle(right) -> hermes_profiles.n6.handle(left) [label="if /eng"]
hermes_profiles.n5.handle(bottom) -> hermes_profiles.n7.handle(top) [label="if /support"]
entry_gateways.n4.handle(right) -> hermes_profiles.n8.handle(left)
hermes_profiles.n6.handle(right) -> execution_sandboxes.n9.handle(left) [label="executes"]
hermes_profiles.n7.handle(right) -> execution_sandboxes.n9.handle(left) [label="executes"]
hermes_profiles.n8.handle(right) -> execution_sandboxes.n10.handle(left) [label="executes"]

 

 

Where to Start

Your Situation Start With Upgrade
First client, testing Option 1 → Option 2 for departments
One client, 2+ teams Option 2 → Option 4 for client 2
3+ paying clients Option 3 → Option 4 as clients grow

 

 

How Do Kanban Boards Help Multi-Client Teams?

Hermes Kanban is a durable task board — every task is a row in SQLite, every handoff is a row any profile can see and edit. Since v0.13.0, the dispatcher runs embedded in the gateway by default.

Use separate boards per client to reduce coordination errors and keep work segmented. In Hermes Kanban, boards are the hard isolation boundary inside Kanban, while tenants are only a soft filter.

 

task_planner { # Planner
  n1: rectangle label="Orchestrator"
}

shared_board { # Coordination
  n2: rectangle label="Shared kanban.db"
}

specialized_workers { # Workers
  n3: rectangle label="Researcher A"
  n4: rectangle label="Researcher B"
  n5: rectangle label="Writer"
}

final_result { # Output
  n6: circle label="Deliverable"
}

task_planner.n1.handle(right) -> shared_board.n2.handle(left) [label="create tasks"]
shared_board.n2.handle(right) -> specialized_workers.n3.handle(left) [label="claim task 1"]
shared_board.n2.handle(right) -> specialized_workers.n4.handle(left) [label="claim task 2"]
specialized_workers.n3.handle(right) -> shared_board.n2.handle(right) [label="complete"]
specialized_workers.n4.handle(right) -> shared_board.n2.handle(right) [label="complete"]
shared_board.n2.handle(bottom) -> specialized_workers.n5.handle(top) [label="unblock writer"]
specialized_workers.n5.handle(right) -> final_result.n6.handle(left) [label="publish"]

 

The /kanban slash command works across all gateway platforms — Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Mattermost, email, and SMS.

 

 

What Changed in Hermes Agent v0.13.0?

As of May 7, 2026, the latest public Hermes Agent release is v0.13.0. The items below are the features most relevant to this setup in the current docs and release notes.

  • Kanban dispatcher is gateway-embedded by default — no separate daemon process for the normal setup.
  • Multiple Kanban boards — clean project separation per client or project.
  • Profile auto-aliases — every profile becomes its own CLI command.
  • Token lock safety — duplicate bot tokens trigger a clear error.
  • Bundled skills sync to all profiles on hermes update.

 

 

Step-by-Step: Onboarding a New Client

 

# 1. Fresh profile — no --clone
hermes profile create client-x

# 2. Restrict workspace and sandbox
client-x config set terminal.cwd /var/hermes-clients/client-x
client-x config set terminal.backend docker

# 3. Configure bot token
nano ~/.hermes/profiles/client-x/.env
# TELEGRAM_BOT_TOKEN=789012:ABC-DEF-...

# 4. Disable bundled toolsets the client does not need
client-x config set agent.disabled_toolsets '["flowzap","creative","media"]'
# Note: bundled skills auto-sync on hermes update.
# Custom skills go in ~/.hermes/profiles/client-x/skills/ only if you build them for this profile.

# 5. Start gateway
client-x gateway start

 

For multi-department clients, use one profile + SOUL.md routing instead of fighting the token lock.

 

~/.hermes/profiles/beta/SOUL.md
→ "Beta Corp agent. Prefix /engineering for tool access.
  Prefix /support for read-only ticket resolution."

 

 

What Works vs. What Breaks

Scenario Verdict
3 clients, 1 department each, Docker backend Works. Profiles + sandboxed backends cover Hermes state + execution isolation.
1 client, 5 departments, shared bot token Token lock blocks. Use internal routing or separate bots.
Two profiles, same token Second gateway refuses to start.
Different backends per client (Docker vs local) Works. Set terminal.backend per profile.
Cross-client filesystem via local backend Profiles don't isolate filesystem. Use Docker.
Kanban task in wrong client's board Separate boards per client reduces this risk because boards are the hard isolation boundary inside Kanban.
Client accesses shared dashboard Shared dashboard is admin-only. Kanban is shared across profiles on the same host, so a client-facing dashboard should run on a separate isolated Hermes runtime, not just an isolated HERMES_HOME.
--clone from personal to client profile Risk of API key leakage. Create fresh profiles.

 

 

The Bottom Line

Hermes Agent can support multiple clients on one server, but safe multi-tenant deployment depends on how you configure execution. Profiles isolate Hermes state well; Docker, SSH, Modal, Daytona, Vercel Sandbox, or Singularity provide the stronger execution boundaries you need for client-facing work. If you want client-facing dashboards, use a separate isolated Hermes runtime per company; if you stay on a shared host, keep the dashboard private and use messaging channels for client access.

 

 

Inspirations

 

Official Documentation

  1. Hermes Agent Profiles
  2. Kanban boards
  3. Security model
  4. Terminal backend config
  5. Telegram gateway setup
  6. Profile distributions
  7. v0.13.0 release notes
  8. Full documentation

 

Community & Commentary

  1. Profiles as governance primitive
  2. Defense-in-depth analysis
  3. Production deployment patterns
  4. Community builds

 

Security & Multi-Tenant Context

  1. LLM tenant isolation models
  2. Multi-tenant LLM threat taxonomy
  3. Real-world multi-tenant agent on one machine
Back to all Blog articles