Bring Your Own Hermes — the reusable bridge runtime for BYOH (agent-as-backend) Hermes plugins.
Project description
byoh-bridge — Bring Your Own Hermes
The reusable runtime for BYOH apps — software whose backend is the user's own local AI agent (Hermes) and whose data never leaves the user's machine.
byoh-bridgeis the plumbing; you write the domain.
A traditional app is Browser → REST API → Postgres. A BYOH app is
Browser → dumb relay → your local Hermes agent → local SQLite. The "API surface"
isn't endpoints — it's typed tools the agent calls inside scoped workflows.
byoh-bridge provides all the generic machinery to make that work:
- Outbound relay bridge — dials a relay/gateway, speaks the
byo.*JSON-RPC protocol, streams agent events back to the browser. - Workflow autodiscovery — drop a folder of typed tools + read RPCs + a
SKILL.md; it's wired up. Tool/RPC contracts (Tool,Rpc,Workflow) + a metric factory. - Local SQLite storage — one
Base, WAL mode, programmatic Alembic migrations, and automatic change-events (any committed write notifies the subscribed browser — zero per-feature code). - Per-session tool sandbox — a
pre_tool_callhook blocks any tool outside the active workflow's allowlist. - Chunked upload pipeline into a local inbox (bytes never touch the cloud).
- Dependency safety net + a
/byoh-doctorcommand.
Install
# into your Hermes venv (editable, for development):
~/.hermes/hermes-agent/venv/bin/pip install -e path/to/byoh-bridge
# or, once published:
pip install byoh-bridge
It declares sqlalchemy, alembic, websockets — so installing it (or a plugin
that depends on it) pulls those in. No more hand-installing them into the venv.
Build a plugin on it
Your whole plugin entrypoint:
# my_app/__init__.py
from byoh_bridge import register as byoh_register, AppConfig
APP_CONFIG = AppConfig(
name="my-app", # data-dir + default agent-id slug
workflows_package="my_app.workflows", # autodiscovered
models_package="my_app.storage.models", # imported → Base.metadata
migrations_path=__path__[0] + "/alembic", # you own your versions/
# optional, env-overridable: data_dir, relay_url, agent_id,
# extra_requirements=[...], document_store=MyDocumentStore(),
)
def register(ctx): # Hermes calls this at startup
byoh_register(ctx, APP_CONFIG)
A feature is a workflow directory:
# my_app/workflows/weight/__init__.py
from pathlib import Path
from byoh_bridge.workflows import Workflow, register_tools, collect_rpcs
_SKILL = (Path(__file__).parent / "SKILL.md").read_text()
def build_workflow(ctx) -> Workflow:
tools = register_tools(ctx, f"{__name__}.tools") # tools/<x>.py → TOOL = Tool(...)
return Workflow(name="weight", skill=_SKILL,
allowed_tools=[t.name for t in tools],
rpcs=collect_rpcs(f"{__name__}.rpcs")) # rpcs/<x>.py → RPC = Rpc(...)
Models subclass the shared base; your alembic/env.py is three lines:
# my_app/storage/models/weight.py
from byoh_bridge.storage import Base
from sqlalchemy.orm import Mapped, mapped_column
class WeightLog(Base):
__tablename__ = "weight_logs"
...
# my_app/alembic/env.py
from my_app import APP_CONFIG
from byoh_bridge.alembic_support import run_env
run_env(APP_CONFIG)
Loading a plugin into Hermes (today's gotcha)
Hermes (≤ 0.15.x) discovers plugins as flat directories and loads each
plugin's root __init__.py by path, calling register(ctx). It does not
pip install the plugin or its dependencies. That clashes with the clean,
distributable shape this framework encourages — a src-layout pip package
using absolute imports (from byoh_bridge import …, an AppConfig.models_package
like "my_app.storage.models"). A bare clone therefore won't run: Hermes finds
no register() at the directory root, and neither your package nor byoh-bridge
is importable in Hermes's venv.
Until Hermes supports installed-package / entry-point plugin discovery (tracked
in docs/byoh/03-HERMES-GAPS.md), reconcile it two ways:
- A root
__init__.pyshim committed at your plugin repo root — Hermes loads this by path and it delegates to your real package:# <plugin-repo>/__init__.py from my_app import APP_CONFIG, register # noqa: F401
With asrc/layout, setuptools ignores this root file, so it never lands in your wheel. pip installthe plugin into Hermes's venv (so the package +byoh-bridge- SQLAlchemy/Alembic resolve).
hermes plugins install owner/repoonly clones — follow it withpip install <cloned-dir>.
- SQLAlchemy/Alembic resolve).
The reference plugin
tinybeat-pregnancy does
exactly this — its README has the copy-paste commands.
Configuration (env overrides)
| Env var | Default | Purpose |
|---|---|---|
BYOH_RELAY_URL |
ws://127.0.0.1:3000/ws/agent |
Where the bridge dials |
BYOH_AGENT_ID |
<app-name>-local |
Relay pairing id (must match the browser) |
BYOH_DATA_DIR |
<hermes_home>/<app-name> |
Where app.db + inbox/ live |
BYOH_BRIDGE_ENABLED |
1 |
Set 0 to load tools without dialing |
Verify (no live Hermes needed)
# migrations against a scratch DB:
export BYOH_DATA_DIR=$(mktemp -d)
cd path/to/your-plugin && alembic upgrade head
Reference app
tinybeat-pregnancy — the
plugin behind a private pregnancy companion — is the reference app built on
byoh-bridge: 11 workflows, domain models + migrations + safety, wired by one
AppConfig. It's the worked example of everything above.
MIT licensed. Status: 0.1.0, pre-release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file byoh_bridge-0.1.0.tar.gz.
File metadata
- Download URL: byoh_bridge-0.1.0.tar.gz
- Upload date:
- Size: 33.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
285de87c590e295036bccf89ec5f9154a20545f039f1aea0f30f51557d677dd4
|
|
| MD5 |
e2b47faa44cda2a2a7459475613b70f7
|
|
| BLAKE2b-256 |
762e49cab54a264b0abf3833b5abac4ca15ac65f3fae58850ffc7dc6477ad83f
|
Provenance
The following attestation bundles were made for byoh_bridge-0.1.0.tar.gz:
Publisher:
publish.yml on sumanthakkala/byoh-bridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
byoh_bridge-0.1.0.tar.gz -
Subject digest:
285de87c590e295036bccf89ec5f9154a20545f039f1aea0f30f51557d677dd4 - Sigstore transparency entry: 1740642322
- Sigstore integration time:
-
Permalink:
sumanthakkala/byoh-bridge@9292e1ef99ab5f910fe3060be6ababe2cb6f92f2 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/sumanthakkala
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9292e1ef99ab5f910fe3060be6ababe2cb6f92f2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file byoh_bridge-0.1.0-py3-none-any.whl.
File metadata
- Download URL: byoh_bridge-0.1.0-py3-none-any.whl
- Upload date:
- Size: 42.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0e8407ad2eeee4d3d549ed403b13252e193f3e70bfa14bbb307de88ca384017
|
|
| MD5 |
75a03116673262de407685bc3b511877
|
|
| BLAKE2b-256 |
f0b9176aff13907e907c3d412d23309f2a383fc3017dbed98f582a14ec0538cf
|
Provenance
The following attestation bundles were made for byoh_bridge-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on sumanthakkala/byoh-bridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
byoh_bridge-0.1.0-py3-none-any.whl -
Subject digest:
d0e8407ad2eeee4d3d549ed403b13252e193f3e70bfa14bbb307de88ca384017 - Sigstore transparency entry: 1740642327
- Sigstore integration time:
-
Permalink:
sumanthakkala/byoh-bridge@9292e1ef99ab5f910fe3060be6ababe2cb6f92f2 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/sumanthakkala
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9292e1ef99ab5f910fe3060be6ababe2cb6f92f2 -
Trigger Event:
push
-
Statement type: