Skip to content

AI

How I Built My Own Self-Hosted AI Assistant with Hermes

I built a self-hosted AI assistant with Hermes that connects Telegram, Obsidian, GitHub, task management, research, monitoring, and automation into one persistent personal workflow.

11 min read

I’ve been using AI tools in my development workflow for a while, but at some point I realized I wanted something more than just another chat window.

I didn’t want an AI that only answered questions.

I wanted something that could stay online, remember context, manage small parts of my day, do research, keep notes, track tasks and expenses, work with GitHub repositories, and notify me when something actually needed my attention.

That’s what led me to Hermes Agent.

What started as a simple experiment with a VPS slowly turned into a small personal AI system that I can access from Telegram.

What Hermes Actually Is

The easiest way to think about Hermes is as an agent runtime that sits between an LLM and the tools around it.

Instead of this:

Me
 ↓
AI Model
 ↓
Answer

you get something closer to this:

Me
 ↓
Telegram
 ↓
Hermes Agent
 ↓
LLM
 ↓
Tools / Skills
 ↓
Linux / GitHub / Obsidian / SQLite / Web

The model still does the reasoning, but Hermes gives it a way to actually do things.

It can work with files, run terminal commands, use custom skills, search the web, manage scheduled jobs, delegate work to other models, and keep persistent state.

That was the part that interested me most.

Why I Run It on a VPS

I decided to run Hermes on a small VPS instead of my Mac.

The main reason is simple: I wanted it to be available all the time.

My laptop doesn’t need to be open for Hermes to:

  • respond on Telegram

  • run scheduled tasks

  • send reminders

  • generate daily reports

  • monitor the server

  • work on background tasks

The server itself is not publicly exposed more than necessary.

I use Tailscale for private access, and SSH is restricted to key-based authentication. The idea was to keep the management side private while still letting Hermes communicate with external services when needed.

Telegram Became the Main Interface

Telegram ended up being the best interface for the system.

I can just send something like:

Add a high-priority task to the Tymora project for preparing the tenant onboarding flow.

or:

Research current Laravel response caching options and save the results to my notes.

That works well for quick interactions, especially from a phone.

At first, though, everything happened in one Telegram conversation.

That became messy very quickly.

Research conversations, coding sessions, finance questions, reminders, and random daily questions all shared the same context.

The solution was Telegram forum topics.

My current setup looks roughly like this:

Hermes

🤖 System
💻 Coding
🧠 General
🔎 Research
💰 Finance
✅ Tasks
📅 Daily & Weekly

Each topic is treated as its own Hermes session.

That means a long research conversation does not pollute the context of a coding session.

The General topic is just for normal everyday questions.

And if I create a new topic later, Hermes can treat that as a completely new session without me manually configuring it.

That turned Telegram from a simple bot chat into something closer to a lightweight workspace.

Using Different Models for Different Jobs

I also didn’t want to use one model for everything.

The main model acts more like a technical lead.

It handles things like:

  • understanding the request

  • planning

  • architecture

  • breaking work into smaller tasks

  • reviewing results

Implementation-heavy work can then be delegated to another model.

The flow looks like this:

Main Model
   │
   ├── Analyze
   ├── Plan
   ├── Break down the work
   │
   ▼
Implementation Model
   │
   ├── Write code
   ├── Refactor
   └── Write tests
   │
   ▼
Main Model
   └── Review

I like this setup because it feels much closer to how a small engineering team works.

One model does not need to do everything.

Obsidian as the Knowledge Layer

I didn’t want useful information to disappear inside chat history.

So I connected Hermes to a dedicated Obsidian vault.

Research, notes, project information, daily summaries, and other useful information can be written there as plain Markdown.

The vault is organized roughly like this:

Obsidian Vault
│
├── Daily
├── Projects
├── Research
├── Tasks
└── Knowledge

The important part is that Obsidian is not the agent’s hidden memory.

It is my own readable knowledge base.

I can open the same files myself, edit them, version them, and keep them even if I stop using Hermes one day.

The vault is also stored in a private GitHub repository, so every change has version history.

That gives me both a knowledge base and a safety net.

A Real Task Manager with SQLite

For tasks, I didn’t want to rely only on Markdown checkboxes.

The task system uses SQLite as the source of truth.

It supports things like:

  • projects

  • tasks

  • subtasks

  • priorities

  • due dates

  • dependencies

  • recurring tasks

  • reminders

  • statuses

Obsidian only shows generated views such as:

Inbox.md
Today.md
This Week.md
Overdue.md

So SQLite holds the actual data, while Obsidian provides a readable interface.

From Telegram, I can say:

Remind me tomorrow at 2 PM to check the Filalabs release.

or:

Show me overdue tasks for this week.

or:

Split this task into three subtasks: migration, Filament resource, and tests.

Hermes converts the natural-language request into structured task data.

Expense Tracking

I built the finance system in a similar way.

It uses a separate SQLite database.

For example:

Add 850 TRY as a grocery expense.

Hermes can categorize and store it.

Later I can ask:

How much did I spend this month?

or:

Which category did I spend the most on?

The finance and task systems are separated:

hermes-data/

finance/
└── finance.db

tasks/
└── tasks.db

I prefer this kind of separation because each skill stays responsible for its own domain.

Research That Doesn’t Disappear

Research is another area where this setup became useful.

I can send something like:

Research the current multitenancy options for Laravel 13, compare the trade-offs, and save it to Obsidian.

Hermes can search, compare sources, summarize the results, and save the useful part to the Research section of the vault.

The important difference is that the result doesn’t stay trapped inside a chat session.

It becomes part of the knowledge base.

That makes follow-up research much more useful because Hermes can work from previous notes instead of starting from zero every time.

Daily and Weekly Briefs

Once Tasks, Finance, Research, and Obsidian were connected, I added scheduled summaries.

Every day Hermes creates a Daily Brief.

It can include things like:

Daily Brief

4 tasks completed
2 tasks moved to tomorrow
1 task overdue

Today's spending:
1,850 TRY

New research:
2

Tomorrow:
- Package release
- Server check
- Tenant onboarding

The detailed version is written to Obsidian.

A shorter version is sent to the Daily & Weekly topic on Telegram.

There is also a weekly review with project progress, spending, completed work, blocked tasks, and priorities for the next week.

This was one of the moments where Hermes started feeling less like a chatbot and more like an assistant.

GitHub Coding Workspace

The coding workflow is probably the most interesting part of the whole system.

I created a separate GitHub account specifically for Hermes.

That account is only added as a collaborator to repositories where I actually want the agent to work.

So the access model looks like this:

Main GitHub Account
        │
        │ collaborator access
        ▼
Hermes GitHub Account
        │
        ├── Repository A ✓
        ├── Repository B ✓
        └── Everything else ✗

I don’t give the agent unrestricted access to my main GitHub account.

The coding flow is controlled:

Telegram
    ↓
Hermes
    ↓
Requirement Analysis
    ↓
Plan
    ↓
Feature Branch
    ↓
Implementation
    ↓
Tests / Lint
    ↓
AI Review
    ↓
Commit
    ↓
GitHub Push
    ↓
Pull Request
    ↓
Human Review
    ↓
Merge

The agent is not allowed to push directly to the main branch.

Every meaningful change happens on a feature branch and ends in a pull request.

I still make the final merge decision.

The first time I started a real pull request from Telegram and later saw the branch and PR on GitHub, the whole setup started to feel surprisingly practical.

Monitoring the Agent Itself

Once you have an agent running 24/7, another question appears:

Who watches the agent?

So I added a health monitoring layer.

It checks things like:

  • Hermes gateway

  • scheduled jobs

  • task reminders

  • Git sync

  • backups

  • disk usage

  • memory

  • load

  • Tailscale

  • SQLite integrity

  • systemd services

  • coding workspace health

The important rule is that it stays quiet when everything is fine.

I don’t want a bot telling me every five minutes that the server is healthy.

If something goes wrong, it sends a short warning to the System topic.

For example:

Backup snapshot has not been updated for 41 hours.

When the issue is resolved, it sends a recovery message.

That makes the monitoring useful instead of noisy.

An iPhone Widget for Server Health

I also built a small Scriptable widget for iPhone.

It shows a lightweight summary such as:

Hermes       ● Healthy

Agent        ✓
Backup       ✓
Git Sync     ✓

RAM          42%
Disk         31%

Updated 2m ago

The widget does not need Tailscale to be active.

The health monitor exposes a minimal read-only endpoint through Cloudflare Tunnel.

The architecture looks like this:

Health Monitor
      ↓
Read-only API
      ↓
Cloudflare Tunnel
      ↓
Scriptable
      ↓
iPhone Widget

The endpoint cannot restart anything, execute shell commands, or access admin functions.

It only returns limited health telemetry and is protected by a bearer token.

I wanted the convenience of a public widget without turning the VPS into a public admin panel.

Backups

Once the system started storing real state, backups became important.

The important data is encrypted locally using Restic and sent to Google Drive through rclone.

VPS
 ↓
Restic
 ↓
Encryption
 ↓
rclone
 ↓
Google Drive

I also tested restoring data from the backups.

That part matters.

A backup you have never restored is mostly a theory.

Security Was Part of the Design

I intentionally tried to avoid the “give the AI root access to everything” approach.

Some of the rules I use are:

  • SSH is not publicly exposed

  • Tailscale is used for private server access

  • GitHub uses a separate agent account

  • the agent only sees selected repositories

  • direct pushes to main are blocked

  • coding changes go through pull requests

  • health endpoints are read-only

  • different data domains use separate SQLite databases

  • secrets are kept out of notes and repositories

  • monitoring does not run as root just because one metric is unavailable

The principle is simple:

Give the agent enough capability to be useful, but not more authority than it actually needs.

I think this matters a lot once AI systems start doing real work instead of just generating text.

What I Ended Up Building

At this point, Hermes is no longer just an AI bot for me.

It is closer to a small personal AI layer that connects several tools together.

                         Telegram
                            │
                            ▼
                       Hermes Agent
                            │
              ┌─────────────┼─────────────┐
              │             │             │
              ▼             ▼             ▼
            LLMs          Skills        Scheduler
              │             │             │
              │      ┌──────┼──────┐      │
              │      ▼      ▼      ▼      │
              │    Tasks Finance Research │
              │                           │
              └──────────┬────────────────┘
                         │
              ┌──────────┼───────────┐
              ▼          ▼           ▼
           Obsidian    GitHub      SQLite

        Health Monitor
              │
       ┌──────┴──────┐
       ▼             ▼
   Telegram      iPhone Widget

        Backups
          │
       Restic
          │
     Google Drive

Most of it can be controlled through normal language from Telegram.

That is probably the part I enjoy most.

The Biggest Advantage Isn’t Better AI

The biggest benefit for me is not that the AI suddenly became smarter.

It is continuity.

A normal AI interaction usually looks like:

Question
 ↓
Answer
 ↓
Done

This system can look more like:

Request
 ↓
Action
 ↓
Persistent data
 ↓
Follow-up
 ↓
Reminder
 ↓
Report
 ↓
Another action

A research request can become an Obsidian note.

A request can become a task.

A coding request can become a pull request.

A deadline can turn into a reminder.

A server problem can generate an alert without me asking anything.

That is the difference that made the whole experiment worthwhile.

What’s Next?

I still have a few things I want to improve.

The GitHub pull request lifecycle can be connected more tightly to the Task Manager, so coding tasks automatically move from in_progress to waiting_review and eventually to done.

I also want to keep experimenting with different models for different types of work.

But at this point, I’m deliberately slowing down on adding features.

The system is already capable enough that the next useful improvements will probably come from actually using it every day.

This whole thing started with a very simple idea:

What if I put Hermes on a VPS and talked to it through Telegram?

It ended up becoming much more than that.

And that is probably the most interesting part of building agent systems.

You stop thinking about AI as an app you open, and start thinking about it as infrastructure you can shape around the way you already work.

Share this article

Vue6 min read

Authentication with Firebase and VueJS

Build Firebase authentication in Vue with Pinia, GitHub login, session-aware route middleware, and protected authenticated and guest pages.

  • Vue
  • Firebase
  • Authentication
Vue2 min read

Pinia vs Vuex

Compare Pinia and Vuex through simple state management examples, API differences, and practical guidance for choosing a store for your Vue application.

  • Vue
  • Pinia
  • Vuex