Four systems and two cron jobs, or one install
A small team wants shared agents, shared memory, BYOK and an autonomy dial. Here is what assembling it costs, and what one install still lacks.
A self-hosted AI agent setup for a small engineering team needs five things: a runtime that runs the same agents for everyone, a shared knowledge base, a shared memory a human can vet before it becomes a rule, a dial for how autonomous each agent is allowed to be, and a place to talk to the agents where the team already works. The advice that circulates today assembles this from parts — an agent runtime, a chat app, a Markdown vault, a memory service, and the bespoke scripts a team writes to keep all four in sync. Vocion is one install that covers four of those five. It does not cover the fifth: Vocion has no Slack chat interface today. Slack is a read-only source connector — it ingests channel history so agents can search it. There is no bot, no mention handler, no slash command. If a Slack surface is the actual requirement, take Hermes.
This piece walks the honest trade row by row. The full matrix, with every source cited, is on the comparison page.
The setup everyone recommends
One route to shared agents for a small team assembles four systems. Hermes Agent (Nous
Research) is the runtime: each named profile gets its own config, memory, sessions, and gateway
PID, and a single gateway process routes messages to the right profile
(Architecture, accessed
2026-09-09); secrets, including provider API keys, are read from that profile's own .env
(Configuration, accessed
2026-09-09). That gateway reaches 20+ messaging platforms, Slack among them, from one background
process (Messaging, accessed
2026-09-09). Hermes documents seven terminal/sandbox backends — local, ssh, docker, singularity,
modal, daytona, and vercel_sandbox — in a security comparison table naming each backend's
isolation level and best-fit use case
(Security, accessed 2026-09-09).
The installation docs don't state a minimum server size, so we won't repeat the "runs on a small
VPS" line elsewhere without a source for it. Slack is the interface, wired
through that same messaging gateway. Obsidian stores notes as local, plain-text Markdown with
no proprietary lock-in (Obsidian, accessed 2026-09-09) — the property that
makes a shared vault plausible, though we found no Obsidian doc that specifically advertises agent
read/write access to it. A self-hosted alternative aimed at a different job is Open Notebook:
MIT-licensed, with a REST API served at /docs on its own local port
(Open Notebook README, accessed 2026-09-09) — it is a
notebook-and-podcast research tool, not a drop-in Obsidian replacement. Mem0/OpenMemory,
Zep, and Letta are the usual picks for shared memory across agents; the next section
sources each one. Of the three, Letta's own docs go furthest into the rest of this list too: they
describe Slack, Telegram, and Discord channels
(Channels, accessed 2026-09-09), scheduled
recurring prompts (Schedules, accessed
2026-09-09), and memory shared across agents
(Shared memory, accessed 2026-09-09). By that set
of criteria — chat channels, schedules, and shared memory documented under one product — Letta
reads, in our judgment, as the closest single-vendor answer to this comparison, not just a memory
layer; that ranking is our opinion, not a claim Letta's docs make about themselves.
None of this is a bad stack. It is a plausible stack, assembled from real, documented products. The cost shows up in the next section.
What the assembled stack costs to keep running
Four systems means four places state can drift, and nothing in that stack owns cleanup or
accountability by default. Each piece also wants its own provider key: Hermes reads secrets from
each profile's own .env
(Configuration, accessed
2026-09-09), and Mem0's default setup needs its own OPENAI_API_KEY
(Open source overview, accessed 2026-09-09) — separate
from whatever key drives Obsidian's LLM plugins or Open Notebook's model providers. None of the four
systems' own docs describe a shared place where "who approved this" gets recorded across all of
them. That absence — not a specific script count — is the argument for keeping cleanup and spend
reporting in the same install as the agents.
Vocion's answer to "a scheduled job" is an automation: a five-field UTC cron schedule or an
event match — exactly one, not both — dispatched through dispatchDo to run one of workflow,
checkMission, or job (docs/entities/automation.md). The cleanup half of the problem is also
smaller than it looks, because the learning-candidate queue already proposes rules for a human
instead of needing a script to go mine them for you — more on that below.
Shared context is a versioning problem, not a file-sync problem
An Obsidian vault answers "where do the notes live," not "which version of a note produced this
output." Vocion's workspace is Git-backed YAML and Markdown, and every workspace:apply inserts a
workspace_version row (packages/core/src/libs/workspace/applier.ts, the db.insert(workspaceVersionSchema)
call around line 250). Every tool_call is stamped with that same workspace_sha
(packages/core/src/models/Schema.ts, the tool_call table's workspace_sha column). Two agents
reading "the same" file today is a file-sync guarantee. An output tracing back to the exact prompt
version that produced it is a different guarantee, and it is the one a team debugging a bad agent
reply actually needs.
Shared memory that a person signs off on
The assembled stack reaches for Mem0, Zep, or Letta here. Mem0's open-source path documents a memory layer — it needs pgvector (server mode) or a local Qdrant instance (library mode), a history database, an LLM key, and an embeddings provider, and that page does not describe agents, approvals, or scheduling (Open source overview, accessed 2026-09-09). Zep's concepts page describes a temporal Context Graph and an "agent tool" for retrieving from it, with no approval workflow on that page (Concepts, accessed 2026-09-09). Letta's shared-memory docs describe agents committing and pulling changes to a shared memory repository, also with no approval step described (Shared memory, accessed 2026-09-09). None of those three pages describes a step where a human decides whether a proposed memory becomes a standing rule — that is what those specific pages say, not a claim about every page either product publishes.
Vocion's learning steps do. New rules are deduplicated by trigram Jaccard similarity at a 0.72
threshold (packages/core/src/services/LearningsService.ts, DEDUP_THRESHOLD = 0.72), and
classified feedback lands in a learning_candidate queue and becomes a real rule only when a person
approves it, with the rejection reason kept
(packages/core/src/services/LearningCandidateService.ts, packages/core/src/models/Schema.ts's
learning_candidate table). That is the difference between a memory store and a queue of rules a
human adopts: a memory store remembers what it was told; this is a review step that decides what
gets remembered at all. See Teams: the org chart is the interface
for how those same agents are organized into a one-level parent: hierarchy
(docs/entities/team.md, docs/entities/agent.md). Hermes' own architecture docs describe each
profile as a standalone instance with its own config, memory, and sessions
(Architecture, accessed
2026-09-09); we found no parent/child relationship documented between profiles there, which is why
we call that model flat by comparison.
The autonomy dial
Hermes has a documented command-approval and authorization model: it gates shell/terminal commands against a curated list of dangerous patterns and, depending on the configured mode, either escalates to a human or fails closed on timeout (Security, accessed 2026-09-09). The choice a reader is actually making is not "no HITL versus HITL" — it is a shell-command gate versus a review queue over authored actions.
Vocion's version is mission autonomy levels 1 through 5 (packages/core/src/services/missions/autonomy.ts,
AutonomyLevel, AUTONOMY_LABELS), a review queue with list, assign, snooze, and decide
(packages/core/src/services/ReviewService.ts), and trust rules that let a proposal auto-execute
only when its confidence clears an explicit per-action threshold, refusing with
no-rule, disabled, below-threshold, or no-confidence when it doesn't
(packages/core/src/services/TrustService.ts). Per-agent harness.interrupts names the skills or
tools that pause for approval regardless of level (docs/entities/agent.md). One agent can be set
to draft-only; another can act inside its rules; the difference is a level, not a rewrite. The
review queue itself is documented in
The review queue, over HTTP.
BYOK and where the key actually lives
Hermes reads each profile's secrets, including provider API keys, from that profile's own .env
(Configuration, accessed
2026-09-09). Vocion resolves per-organization vendor keys for
openai, anthropic, vertex, azure-openai, aws, and a custom endpoint
(packages/core/src/libs/platforms/registry.ts). The org's stored key is tried first, and a null
falls through to the server's own environment key
(packages/core/src/libs/llm/orgKey.ts, resolveOrgProviderKey). Stored credentials are encrypted
with AES-256-GCM under a per-tenant data encryption key, wrapped by AWS KMS in production or a local
master key in dev (packages/core/src/libs/crypto/credentialVault.ts). One distinction worth
stating plainly, because two harness fields sound alike and are not: runsOn —
in-process, agentcore-container, or aws-managed-harness — is which machinery runs the
turn, while harness.modelProvider — anthropic, openai, or bedrock — is whose model
answers (packages/core/src/libs/workspace/schemas.ts, the modelProvider field and the comment
above it; docs/entities/agent.md). They are separate axes, and one default links them: an agent
that sets modelProvider: bedrock and leaves runsOn unset gets agentcore-container, since
choosing AWS as the model vendor is almost always choosing AWS as the place to run it; writing
runsOn: in-process next to it opts back out (docs/entities/agent.md).
Spend limits that refuse the run
The assembled stack's answer to credit accountability, if it has one, is typically a bespoke report
written after the fact — none of the four systems above document a built-in spend cap. Vocion's
agent_budget rows carry soft caps that warn and hard caps that
refuse, in both tokens and cents, per agent per daily or monthly period
(packages/core/src/models/Schema.ts, the agent_budget table). preflightCheck refuses a run on
hard_tokens_exceeded or hard_cents_exceeded before it starts; chargeUsage accrues; setLimits
configures the caps (packages/core/src/services/BudgetService.ts).
Say the difference precisely, because it cuts both ways: the reader asked "who on the team is
burning credits" — a per-person question. Vocion's budget is keyed on agent_slug, not on a person.
That is a stronger control in one sense — it refuses the run instead of reporting on it afterward —
but it is aimed at a different unit than the one the reader asked about. The agent_budget table has
no user_id or equivalent column (packages/core/src/models/Schema.ts), so there is no per-user
credit report today.
The part we do not have: Slack
Can you talk to a Vocion agent in Slack. No. The Slack connector
(packages/core/src/libs/sources/slack.ts, 72 lines) calls Slack's conversations.history endpoint
on a schedule and yields the messages as ingestible documents. That is the entire file. There is no
bot user, no app_mention handler, no slash command, and no call to chat.postMessage — a repo-wide
search for either turns up nothing but that one history call. @slack/* is not a dependency in
packages/core/package.json. The connector reads channel history into an agent's context; it does
not let an agent post back.
Hermes' messaging gateway, by contrast, reaches Slack, Telegram, Discord, and 20+ other platforms from one gateway process (Messaging, accessed 2026-09-09). If that is the requirement, the honest recommendation is Hermes.
What running it actually takes
Hermes' installation docs don't state a minimum server size, so we won't claim a specific hosting
footprint for it here. Vocion wants Postgres and a compose stack — the repo's docker-compose.yml
brings up a postgres service (pgvector-enabled) plus the Langfuse and Temporal platform services
it includes, and the Next.js app itself runs alongside that with npm run dev:next
(docker-compose.yml). Clone the repo (https://github.com/vocion/vocion-core); it is not
published to npm — npm view @vocion/core against the public registry returns a 404 as of
2026-09-09, and the package's own package.json marks it "private": true
(packages/core/package.json) — so there is no npm install @vocion/core. Bring up the compose
stack, run the migrations, and apply a workspace. That is a heavier first hour than a single small
server. What it buys, in the same install, is the versioning, the review queue, the per-agent
budgets, and the learning-candidate queue described above.
The approval gate itself is a workflow step, not a special case: an approve step "pauses in the
review queue for a human decision," with an optional reviews field naming the earlier step whose
output is being judged (docs/entities/workflow.md). The support-reply demo
(vocion-demos/demos/support-reply/) shows the shape — its
context/support-demo/workflows/support-triage/workflow.yaml has a review step of type: approve
sitting between draft and send. One caveat: the demo still ships its two skills under an
operations/ directory, a layer the workspace loader has rejected since v2.20.0
(packages/core/src/libs/workspace/loader.ts), so this demo does not currently load on v2.47.9 —
read the workflow file for the gate's shape rather than trying to run the demo as-is.
Which one to pick
If the team's non-negotiable is a chat surface in Slack today, pick Hermes — its docs don't advertise the versioning, budget enforcement, or learning-candidate queue described above, so budget time to build equivalents if you need them. If the non-negotiable is a single system that already tracks which workspace version produced an output, routes low-confidence actions to a human, and refuses a run before it overspends — and the team can live without a Slack surface for now — one install covers four of the five things being assembled. Either way, know the row you are trading away before you commit to a stack.
Where to find it
The full trade matrix, every claim sourced, is on the comparison page. Clone
vocion-core, bring up the compose stack, and apply a workspace to see the review queue and
the approval gate for yourself.