One router, three agents: how our support, admin and marketing bots live on the same cheap inference
Spoiler: we built this in 2-3 days. Not because we're geniuses, but because once inference stops costing like a cast-iron bridge, you can stop rationing agents and just… breed them.
Hi, this is the dev team. The last couple of evenings went the way anyone who's ever shipped an AI agent knows by heart: "let's add another one." First there was a single support bot. Then it needed a "boss." Then we realized the same infrastructure happily carries marketing userbots too. Three different agents, three roles — but one shared brain, one shared tool layer, one wallet.
The architecture came out in three layers, each swappable independently: inference → agents → tools. Let's walk all three.

Layer 1 — Inference: our router instead of OpenAI/Anthropic
The whole zoo of agents reasons not through OpenAI and not through Anthropic, but through our own OpenAI-compatible router router.mingles.ai, which sits on top of a decentralized inference network.
For the agent it's not magic at all — it's three parameters:
- URL —
router.mingles.ai - key — your API key
- model — whatever you want to run (ours: a Kimi-class primary + two open-weight models as fallbacks)
Swap your base URL to the router and that's it — existing code just starts going somewhere else and costing a fraction. No new SDKs.
And those "three parameters" aren't a feature for show. They're exactly what turns "one expensive agent" into "a farm of agents that doesn't kill your margin." At the scale of live conversations the main cost line is tokens, and that's precisely what the router cuts. Every agent below routes through this same endpoint.
Bonus — a fallback chain: if a model drops on the network side (503), the runtime transparently switches to the next one in the list. The agent never even notices.
Layer 2 — Agents: what they run on (Hermes)
The agents themselves run on Hermes (nousresearch/hermes-agent) — a runtime we took as a base so we wouldn't have to write conversation orchestration from scratch.
The scheme is simple and, as it turned out, very convenient: one container → several "profiles" → one gateway per profile, all under an s6 supervision tree. Each profile is fully isolated — its own config, its own memory, its own sessions, and its own Telegram bot (Hermes requires the token to belong to a single profile). One gateway per profile = a small blast radius: the support brain and the admin brain, with their own permissions, never mix.
How we configured it, briefly:
- A profile = a YAML file with the desired state (model + fallback chain, which Telegram bot, which MCP server and where its token lives). Secrets aren't in git — they're injected from the environment at sync time.
- Channels. Each agent has its own Telegram bot; private agents are locked to an allow-list of user ids, the public one (support) is open to all. Support additionally exposes an internal OpenAI-compatible HTTP endpoint — the website chat widget rides on it.
- The rakes that cost us time: the model provider must be
custom, notopenai(otherwise the agent sends an empty model and every call 422s); and the Telegram allow-list is read from the per-profile.env, not from the config (otherwise "all users denied"). Both are now baked into our sync script so we don't step on them twice.
So "add an agent" = drop in a new YAML profile and sync. Not rewrite the system.
Layer 3 — Tools: this is where all the security lives (MCP)
The most important architectural decision: all tools live behind a single MCP server, and what an agent is allowed to do is decided not by the LLM — but by the server.
How it works:
- each agent authenticates to the MCP server with a bearer token;
- each token is bound to a role;
- each role has a static allow-list of tool names;
- the gate is enforced server-side, at call time — not in the prompt, not in the model. A jailbroken or confused model literally cannot invoke a tool its role doesn't grant;
- every call is rate-limited and audited.
The same tool server — completely different capabilities per agent:
| Agent | Role | Can do |
|---|---|---|
| Support | support_escalation | read account/usage/errors, open tickets, escalate to a human |
| Marketing | marketing_partner | read-only — growth analytics + partner/referral data |
| Admin/Ops | admin_executor | the privileged operational surface — gated and audited |
Add a capability = add a tool name to a role's list and rebuild the server. Remove one = delete a line. The registry refuses to register a tool no role claims — so the catalog and code can't silently drift.
And per-agent "superpowers" are just another MCP server wired into the profile: a shared knowledge base (vector-backed, retain/recall), web search (a DuckDuckGo sidecar), a browser, product analytics. The marketing agent collected all four plus a read-only internal-analytics role — it can pull real numbers, search the web and check a landing page, but is structurally incapable of touching billing.

Agent #3 up close — the Marketing/Userbot farm
Once you have cheap inference, profile isolation and role-gated tools, it turns out the marketing agent is the same construction kit, turned outward.
Right now we're running 3-5 userbots (deliberately few — the stage where we watch what works and what gets banned). Each userbot is:
- a separate account with its own proxy profile — one account = one IP = one identity on the network;
- its own persona — character, tone, style; the agent holds a native conversation instead of fan-blasting one canned text;
- built-in limits and warm-up — the folk wisdom "5 a day and you won't get banned," but enforced by system rules: randomized timing, capped volume, gradual warm-up;
- two strategies — DMs and group chats, which are different funnels.
Everything flows into a mini-CRM: who replied, who's warmed up, who to hand off to a human. And the bots think, naturally, through router.mingles.ai — which is why even live daily conversations across several accounts aren't a cost line, and scaling is a "when," not a "can we afford it."

Network hygiene (since we're on security)
The agent container has no database access and publishes no host ports — it can't reach the DB even if it wanted to. Outbound paths are only three: the inference router, the Telegram API, and an isolated bridge to the MCP server. No docker.sock, no shell tools — all side effects go through audited MCP calls. The through-line of the whole design is fail closed: when in doubt, the system refuses rather than risks.
The bottom line
In 2-3 days we built not "a bot" but a small ecosystem of three agent types across three swappable layers: cheap inference through our own router, isolated agents on Hermes, and one role-gated tool layer on MCP. Support answers customers, admin watches over things and loops in humans, marketing bots run native conversations and fill the CRM.
If you're an agency building AI agents, or a vibe-coder with an idea that "tokens will eat" — the takeaway is one line: point the URL at router.mingles.ai, bring your key and a model — and count what the agents bring in, not the inference bill.
We're still early, running on 3-5 accounts and collecting numbers. Once we nail a working setup, we'll share the figures. Until then — go vibe-code your own farm. The brain for it is already here.