7.7 KiB
7.7 KiB
Architecture
Overview
Hermes Mobile is split into two deployable parts:
-
Mobile app
- Native Android app built with Capacitor around a shared React UI.
- PWA/web build remains available as fallback and dev target.
- Talks only to the companion server.
- Does not need direct access to Hermes files or credentials.
-
Companion server
- Runs on the same Linux machine as Hermes Agent.
- Bridges mobile UI actions to Hermes Agent.
- Owns upload storage, push notifications, pairing/auth, app metadata, and realtime event fanout.
+---------------------------+
| Android App |
| - Chat |
| - Tool timeline |
| - Cron UI |
| - Files |
| - Approvals |
+-------------+-------------+
|
| HTTPS REST + WebSocket/SSE + native push/Web Push fallback
v
+---------------------------+
| Hermes Companion Server |
| - Auth/pairing |
| - Task orchestrator |
| - Hermes adapters |
| - Event bus |
| - Upload store |
| - Cron wrapper |
| - Notification providers |
+------+------+-------------+
| |
| +--------------------+
| |
v v
+-------------+ +--------------+
| Hermes CLI | | Hermes files |
| Hermes API | | sessions/db |
| AIAgent | | cron jobs |
+-------------+ +--------------+
Key Architectural Rule
The companion server should depend on stable Hermes surfaces first, but isolate every integration behind interfaces.
interface HermesAdapter {
health(): Promise<HermesHealth>
startTask(input: StartTaskInput): AsyncIterable<HermesEvent>
continueSession(sessionId: string, input: StartTaskInput): AsyncIterable<HermesEvent>
stopTask(taskId: string): Promise<void>
}
Possible implementations:
CliHermesAdapter: spawnshermes chat -qor interactive process. Easiest baseline, weakest event detail.ApiHermesAdapter: calls Hermes API server. Good for compatibility, but generic OpenAI API hides some tool events.PythonHermesAdapter: imports Hermes Agent modules and uses callbacks for stream/tool progress. Best long-term event fidelity.GatewayHermesAdapter: uses existing gateway/session machinery if exposed.
Companion Server Modules
companion/
src/
app.ts # server bootstrap
config/ # env/yaml config loading
auth/ # pairing, sessions, tokens, passkeys later
db/ # SQLite schema/migrations/repositories
events/ # event bus + SSE/WebSocket fanout
hermes/ # adapter interface + implementations
tasks/ # task lifecycle/orchestration
uploads/ # multipart upload handling + retention
notifications/ # webpush/ntfy/gotify providers
cron/ # Hermes cron wrapper
approvals/ # approval queue + Hermes callbacks later
routes/ # REST API routes
ws/ # realtime endpoints
system/ # service health, logs, install info
Event Bus
Everything that happens in the companion becomes an event.
Core event shape:
type CompanionEvent = {
id: string
type: string
taskId?: string
sessionId?: string
ts: string
level?: 'debug' | 'info' | 'warn' | 'error'
payload: unknown
}
Important event types:
task.created
task.started
task.status
task.finished
task.failed
task.cancelled
assistant.delta
assistant.message
assistant.final
tool_call.started
tool_call.output
tool_call.finished
tool_call.failed
file.uploaded
file.generated
approval.required
approval.resolved
cron.job.listed
cron.job.updated
cron.job.finished
notification.sent
notification.failed
The mobile app subscribes by:
- WebSocket for active app foreground.
- SSE fallback.
- Push notifications when app is background/closed.
Data Storage
SQLite
Companion-owned metadata:
- paired devices
- auth sessions
- tasks
- task events
- uploaded files metadata
- notification subscriptions
- user settings/cache
Do not duplicate full Hermes session content unless needed for mobile indexing. Hermes session DB remains source of truth.
Filesystem
Default paths:
/var/lib/hermes-mobile/
hermes-mobile.db
uploads/
<task-id>/
generated/
cache/
logs/
User-mode install paths:
~/.local/share/hermes-mobile/
~/.config/hermes-mobile/config.yaml
API Surface
Auth / Pairing
POST /api/pair/start
POST /api/pair/confirm
POST /api/auth/login
POST /api/auth/logout
GET /api/me
Pairing flow:
- Installer prints
https://host/pair?code=123-456. - User opens on phone.
- Server binds device and issues token.
- Future sessions use secure cookie or bearer token.
Tasks
POST /api/tasks
GET /api/tasks
GET /api/tasks/:id
POST /api/tasks/:id/stop
GET /api/tasks/:id/events
WS /api/tasks/:id/stream
Uploads
POST /api/uploads
GET /api/files
GET /api/files/:id/download
DELETE /api/files/:id
Sessions
GET /api/sessions
GET /api/sessions/:id
POST /api/sessions/:id/continue
PATCH /api/sessions/:id
Cron
GET /api/cron/jobs
POST /api/cron/jobs/:id/run
POST /api/cron/jobs/:id/pause
POST /api/cron/jobs/:id/resume
DELETE /api/cron/jobs/:id
System
GET /api/health
GET /api/hermes/health
POST /api/hermes/test
GET /api/logs
Hermes Integration Notes
Existing useful surfaces observed:
- Hermes API server exposes
/v1/chat/completions,/v1/responses,/v1/models,/health. AIAgentsupportsstream_delta_callbackandtool_progress_callbackconstructor params.- Cron jobs are manageable through Hermes CLI/tooling and stored under Hermes home.
- Gateway platforms already handle STT/media patterns, but mobile should not depend on Telegram.
Long-term ideal:
- Add/consume a Hermes-native event stream from AIAgent that emits structured tool events.
- Companion server can either import Hermes modules or call a local IPC endpoint.
Security Model
Default deployments:
- LAN/Tailscale only, simple pairing token.
- Public HTTPS, pairing token + device token + optional passkey.
Security requirements:
- No unauthenticated access to prompt endpoints.
- Upload size limits.
- File paths normalized; no arbitrary file read from upload endpoints.
- CSRF protection if cookie auth used.
- Audit log for approvals.
- Secrets remain in Hermes config/vault, not in mobile app.
Notification Architecture
Provider interface:
interface NotificationProvider {
send(device: Device, message: NotificationMessage): Promise<void>
test(device: Device): Promise<void>
}
Providers:
WebPushProviderNtfyProviderGotifyProviderNoopProvider
Deployment Modes
User mode
- Runs as current user.
- Uses
~/.config/hermes-mobileand~/.local/share/hermes-mobile. - Good for dev/single-user boxes.
System mode
- Creates
hermes-mobilesystem user or runs under Hermes user. - Uses
/etc/hermes-mobileand/var/lib/hermes-mobile. - systemd service.
- Better production posture.
Native Android Shell
Capacitor Android is part of the primary architecture, not a future contingency.
- The shared React UI builds into
apps/mobile/dist. - Capacitor packages that build into an Android APK.
- PWA/web access remains useful for dev, desktop, and fallback.
- Native plugins provide share target, richer push, haptics, status bar, splash screen, microphone/file improvements, and Android lifecycle hooks.