Skip to main content

Borgee platform for Hermes Agent

borgee-hermes-plugin connects one Hermes Agent 0.18.2 gateway profile to one Borgee agent over BPP. It carries its own copy of the Borgee Python SDK, so it installs without borgee-plugin-sdk from PyPI.

Compatibility

Each row identifies one supported runtime boundary.

Component Supported version
Python 3.11, 3.12, or 3.13
Hermes distribution hermes-agent==0.18.2
Hermes release source 9de9c25f620ff7f1ce0fd5457d596052d5159596
Borgee Python SDK vendored from packages/sdk/plugin-py

This package and the SDK are licensed under the MIT License. The repository provides a manual workflow for publishing them to TestPyPI and PyPI; this documentation does not imply that a registry release has occurred.

Install

Vendor the SDK source into the package before building it from a checkout:

uv venv .venv
.venv/bin/python packages/plugins/hermes/scripts/vendor_plugin_sdk.py
uv pip install --python .venv/bin/python packages/plugins/hermes

Enable the entry-point plugin and configure the platform in the active Hermes profile's config.yaml:

plugins:
  enabled:
    - borgee

group_sessions_per_user: false

display:
  busy_input_mode: queue

streaming:
  enabled: true

borgee:
  enabled: true
  base_url: https://chat.example.com
  # Set true only for an explicit http://127.0.0.1 or http://localhost server.
  allow_insecure_loopback: false
  max_concurrent_dispatches: 4
  drain_timeout_seconds: 30

streaming.enabled is a global Hermes setting; it applies to every connected platform by default. To disable streaming for a specific platform, set platforms.<name>.display.streaming.enabled: false in that platform's config block.

Put the agent API key in the active profile's .env:

BORGEE_API_KEY=bgr_replace_with_the_agent_key

base_url is non-secret and belongs in config.yaml. The API key is accepted only through BORGEE_API_KEY; values in config.yaml are rejected. Hermes loads each profile's own .env, so the same variable name remains profile-isolated without profile-suffixed secret names.

Run one Hermes process and one Borgee socket per HERMES_HOME. Leave gateway.multiplex_profiles disabled. The adapter takes two Hermes-scoped interprocess locks in a fixed order: a canonical real-HERMES_HOME hash, then the Borgee origin plus credential fingerprint. It releases credential then profile. An owner-token registry applies the same exclusions within one process where Hermes locks are PID-reentrant.

Delivery and session behavior

Borgee authenticates the BPP socket as one agent and applies channel membership and require-mention policy before sending an event. The adapter therefore sets Hermes authorization_is_upstream=True; it does not maintain a second local allowlist.

Hermes DMs use agent:main:borgee:dm:<channel-id>. Channel conversations use agent:main:borgee:channel:<channel-id>. The required top-level group_sessions_per_user: false makes two authors in one channel share that channel session while preserving their names on each inbound event.

The plugin checkpoints BPP only after it commits the complete receipt to $HERMES_HOME/plugins/borgee/inbox.sqlite3. The SDK cursor advances after that commit, while pending work remains in the durable inbox. A scheduler claims a receipt in SQLite before calling Hermes, preserves FIFO within each ordinary session, and permits bounded concurrency across sessions.

Ingress stores an ordinary, control, or urgent_stop dispatch class using Hermes' real command, plugin-command, and clarify state before the receipt commit. If classification fails, the delivery fails without a checkpoint.

SQLite open, close, and every submitted actor operation settle before cancellation is rethrown. Cancelling open closes any connection created in the worker, shuts down that executor, and makes the actor non-reusable. Close is idempotent and always finishes connection and worker shutdown, including when concurrent lifecycle callers are cancelled.

Hermes slash commands and pending clarify answers bypass an active ordinary turn. For /queue <payload> and /q <payload>, the adapter removes the prefix in the receipt transaction and keeps the payload as a durable ordinary turn until the session becomes idle. A bare /queue follows Hermes' normal inline usage response.

The scheduler can find a persisted control past an arbitrarily deep ordinary backlog, then rechecks the live Hermes bypass state before dispatch. If the session became idle during that check, the receipt must wait for the ordinary FIFO head.

Ordinary and control work have independent bounded lanes, and /stop has a separately reserved urgent slot. A timed-out control or urgent execution releases its lane slot, suspends the matching Hermes session when it exists, and quarantines the claimed receipt for explicit remediation.

Crash recovery

A receipt moves through this state machine:

pending -> processing -> completed | failed
                    \-> in_doubt -> quarantined

The pending -> processing claim and its unique token commit before Hermes runs. A crash after the claim may have performed tools or sent side effects, so restart never replays that receipt automatically. Startup marks leftover processing rows in_doubt, suspends every matching Hermes session before the BPP SDK connects, and quarantines the rows.

A missing Hermes session needs no suspension because the next turn cannot continue its old tool tail, but its receipt is still quarantined.

The host can expose the adapter's remediation library method to an operator:

await adapter.remediate_receipt(ingest_seq, "discard")

await adapter.remediate_receipt(
    ingest_seq,
    "requeue",
    confirm_duplicate_side_effect_risk=True,
)

Both actions reset an existing Hermes session first. discard records an operator decision and never runs the message. requeue requires explicit confirmation that tools, provider requests, or outbound effects might occur a second time. There is no automatic requeue path.

During shutdown, the adapter stops admission, drains Hermes processing for the configured bound, and then closes the BPP client, inbox, and both ownership locks. Work that does not finish by the bound becomes in_doubt for the same startup quarantine path.

A quarantined receipt blocks later ordinary turns only on its own Hermes session lane until the operator discards or explicitly requeues it. Other sessions remain schedulable; active session keys are excluded before the database query applies its global candidate limit.

Channel and Zone tools

The plugin registers Borgee domain tools with Hermes' borgee toolset. Each registered function has its own parameter schema, and synchronous host dispatch forwards work onto the running gateway loop and BPP client. Tool availability follows the active adapter and BORGEE_API_KEY.

borgee_channel_create requires the current guild_id, a name, and explicit nullable parent_id. The agent takes the Server ID from the canonical Borgee conversation context. Default (no Zone) is JSON null; a named Zone uses its ID. Placement cannot be edited after creation, and grouping grants no conversation access.

{"guild_id":"server-id","name":"lobby","parent_id":null}

borgee_list_zones discovers named Zone IDs for one Server. It returns {zones:[{id,name}],next_after} in ascending ID order; next_after: null marks the end. The default limit is 20, with explicit values from 1 through 50. Pass a returned non-null cursor as after only when more discovery is needed. The virtual Default group is not a returned Zone, and a named “Default” remains an ordinary named Zone.

{"guild_id":"server-id","limit":20}

The server authorizes the acting agent's current membership on every discovery page and validates its membership, channel.create capability, target Organization, and selected Zone when creating a channel. The plugin does not select a remembered Server or inherit the agent owner's membership.

Creation preserves JSON null; missing or malformed placement fails visibly. Update rejects any supplied parent_id or channel_type, including null and unchanged values. Malformed discovery responses fail through the SDK's checked decoder. There are no model-facing Zone create, rename, or delete tools, and Zone IDs are not conversation targets.

Outbound behavior

Hermes send, edit_message(finalize=...), and delete_message map to BPP semantic actions. Edit-based Hermes streaming creates a preview with send, updates it with edit_message, and accepts the final finalize=True call. Typing is a no-op because BPP task lifecycle frames already report real work; the adapter does not invent a typing signal.

Every outbound message ID is persisted for echo filtering. The resolved Borgee agent ID is also filtered, which closes the race where the server broadcasts an agent-authored message before the outbound ID transaction completes.

Agent config updates are acknowledged as rejected with a legal BPP reason; Borgee model, prompt, and tool changes are not applied to a running Hermes conversation. Disabling the Borgee agent stops new intake and the connection without claiming cancellation of a turn already executing inside Hermes. /stop remains Hermes' real current-turn cancellation command.

Limits

The inbound adapter handles only text messages and mentions. Attachments, inbound history retrieval, server read_file requests, REST side channels, multi-agent routing, and multi-profile multiplexing are outside its boundary. Model tools separately support conversation history reads. Edited, deleted, and reaction events receive durable terminal receipts but do not start inference.

Metadata

Release files for borgee-hermes-plugin 0.3.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for borgee-hermes-plugin 0.3.5
File Size Uploaded
borgee_hermes_plugin-0.3.5.tar.gz 113.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for borgee-hermes-plugin 0.3.5
File Interpreter ABI Platform
borgee_hermes_plugin-0.3.5-py3-none-any.whl Python 3 none any Details

Total release size: 213.0 kB

Release files / borgee_hermes_plugin-0.3.5.tar.gz

Download URL borgee_hermes_plugin-0.3.5.tar.gz
Size 113.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d0402e7a460362ff4e768075a07b118704cd5e9fdd976e8cdf7ee1df818b69fd
BLAKE2b-256 checksum
How to use checksums
7cdaf237144fed798a37a06c89a6f49e1b8bcb50c6ba6fe5a8e77b5460ad1d15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / borgee_hermes_plugin-0.3.5-py3-none-any.whl

Download URL borgee_hermes_plugin-0.3.5-py3-none-any.whl
Size 99.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d7599d7fcea8b3d620607cc7a5e60505cd9576889d40a9de4167f13bd76c028b
BLAKE2b-256 checksum
How to use checksums
288736779b0e08158aff8691608786541fea9b6d1304712292f9a926cc071162
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.3.5 This release

2 release files

0.3.1

2 release files

0.2.16

2 release files

0.2.12

2 release files

0.2.10

2 release files

0.2.0

2 release files

0.1.4

2 release files

0.1.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page