Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This page maps every published package in the repo to its primary use case and t
| Package | Use it for | Install | Docs |
| --- | --- | --- | --- |
| `slop-ai` for Python | FastAPI, services, local tools, Python consumers | `pip install slop-ai[websocket]` | [API](/api/python), [Guide](/guides/python) |
| `slop-hermes` | Hermes Agent integration | `pip install slop-hermes` | [API](/api/slop-hermes), [Guide](/guides/advanced/hermes) |
| `slop-ai` for Go | `net/http` services, daemons, CLI tools, Go consumers | `go get github.com/devteapot/slop/packages/go/slop-ai` | [API](/api/go), [Guide](/guides/go) |
| `slop-ai` for Rust | Axum apps, services, daemons, CLI tools, Rust consumers | `cargo add slop-ai` | [API](/api/rust), [Guide](/guides/rust) |

Expand Down
3 changes: 3 additions & 0 deletions docs/api/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ from slop_ai.transports.asgi import SlopMiddleware

- provider APIs via `SlopServer`
- consumer APIs via `SlopConsumer`
- discovery helpers via `slop_ai.discovery` for provider scanning, bridge relay, lazy connect, and AI-facing tool helpers
- transport modules for ASGI, WebSocket, Unix socket, stdio, and matching client transports
- scaling helpers such as `prepare_tree()` and `truncate_tree()`
- LLM tool helpers such as `affordances_to_tools()` and `format_tree()`
Expand All @@ -30,3 +31,5 @@ from slop_ai.transports.asgi import SlopMiddleware

- [Python guide](/guides/python)
- [Consumer guide](/guides/consumer)
- [Discovery & Bridge](/sdk/discovery)
- [slop-hermes package](/api/slop-hermes) — Hermes Agent integration built on the Python discovery layer
59 changes: 59 additions & 0 deletions docs/api/slop-hermes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# slop-hermes

`slop-hermes` is a Python package that installs a Hermes plugin for SLOP app discovery and control.

It exposes five tools:

- `list_apps` — list available apps
- `connect_app` — connect and inspect an app
- `disconnect_app` — stop tracking an app
- `app_action` — perform a single action
- `app_action_batch` — perform multiple actions in one call

## Install

```bash
pip install slop-hermes
```

For local development from this repo:

```bash
pip install -e /path/to/slop/packages/python/slop-hermes
```

Install it into the same Python environment as Hermes.

## How it works

The package registers a `hermes_agent.plugins` entry point named `slop`.

At runtime it:

- starts a background `slop_ai.discovery.DiscoveryService`
- discovers local and browser-backed SLOP providers
- injects connected provider state through Hermes' `pre_llm_call` hook
- exposes a stable five-tool surface for app lifecycle and actions

## Discovery sources

- `~/.slop/providers/*.json`
- `/tmp/slop/providers/*.json`
- browser extension bridge at `ws://127.0.0.1:9339/slop-bridge`

## Environment variables

- `SLOP_HERMES_MAX_NODES` — max nodes included in injected state trees. Default: `160`
- `SLOP_HERMES_MIN_SALIENCE` — optional salience threshold for injected trees

## Operational notes

- Designed first for local CLI / single-user Hermes
- Uses stable meta-tools rather than per-affordance dynamic tools
- Builds on the mirrored Python discovery layer in `slop_ai.discovery`

## Related pages

- [Hermes integration guide](/guides/advanced/hermes)
- [Python SDK API](/api/python)
- [Discovery & Bridge](/sdk/discovery)
150 changes: 150 additions & 0 deletions docs/guides/advanced/hermes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# Hermes Integration

SLOP ships a Hermes plugin at `packages/python/slop-hermes`.

It gives Hermes five stable tools for discovering and controlling SLOP-enabled applications:

- `list_apps`
- `connect_app`
- `disconnect_app`
- `app_action`
- `app_action_batch`

## What it does

- **Discovers** SLOP apps from local provider descriptors and the browser extension bridge through `slop_ai.discovery`
- **Injects live state** into each Hermes turn through the plugin `pre_llm_call` hook
- **Returns an immediate snapshot** through `connect_app`, including the current state tree and action summary
- **Acts through stable meta-tools** so Hermes always sees the same tool catalog
- **Supports multiple apps** connected simultaneously

## Install

Install `slop-hermes` into the same Python environment as Hermes:

```bash
pip install slop-hermes
```

From a local checkout:

```bash
pip install -e /path/to/slop/packages/python/slop-hermes
```

Verify that Hermes sees the plugin:

```bash
hermes plugins list
```

You should see a `slop` plugin entry.

If you explicitly manage toolsets, make sure the plugin toolset is enabled:

```bash
hermes tools
```

Or include it directly when starting chat:

```bash
hermes chat --toolsets slop,web,terminal
```

## How it works

### Plugin loading

`slop-hermes` is a pip-installed Hermes plugin. It registers itself through the `hermes_agent.plugins` entry point and exposes a `slop` toolset.

### In-process discovery runtime

The plugin starts a background asyncio runtime on first use. That runtime owns a `slop_ai.discovery.DiscoveryService`, which handles:

- `~/.slop/providers/*.json` descriptor discovery
- `/tmp/slop/providers/*.json` descriptor discovery
- browser extension bridge discovery at `ws://127.0.0.1:9339/slop-bridge`
- connection management for Unix socket, WebSocket, and relay-backed providers

### Hook-based state injection

On every Hermes turn, the plugin's `pre_llm_call` hook injects a compact summary of connected and available apps into the current user message:

````text
## SLOP Apps

1 app(s) connected. Read the state trees below before acting...

### Kanban (kanban)

```
[root] kanban: Kanban Board actions: {add_card(title: string)}
[collection] backlog "12 cards"
```

### Available (not connected)

- **Calendar** (id: `calendar`, ws, bridge)
````

Hermes can answer from injected state directly, or use the five SLOP tools when it needs to connect, refresh, or act.

### State compaction

The injected tree is compacted before formatting so prompt usage stays bounded.

Available knobs:

- `SLOP_HERMES_MAX_NODES` — max nodes included in injected trees. Default: `160`
- `SLOP_HERMES_MIN_SALIENCE` — optional salience threshold before rendering

## Tools

| Tool | Purpose |
| --- | --- |
| `list_apps` | List all discovered SLOP-enabled apps and show which are already connected |
| `connect_app` | Connect to an app, return its current state tree plus action summary, and enroll it in injected context |
| `disconnect_app` | Disconnect from an app |
| `app_action` | Invoke one affordance on a node |
| `app_action_batch` | Invoke multiple affordances in a single call |

## Why the Hermes plugin uses meta-tools

The Hermes plugin currently uses the same fixed-tool model as the Codex and OpenClaw integrations:

- Hermes plugin tools are registered once during plugin initialization
- prompt injection gives Hermes live app state before every turn
- actions still go through `app_action` and `app_action_batch`

This keeps the integration simple and predictable while matching Hermes' plugin model.

## Operational scope

This first version is designed primarily for **local CLI / single-user Hermes**.

The discovery runtime is process-global, which is a good fit for a single local Hermes instance controlling apps on the same machine. If you need stricter multi-user isolation or remote-host integration, the MCP route is still the safer boundary.

## Example interaction

```text
User: What apps are available?
→ Hermes calls list_apps

User: Connect to the kanban board
→ Hermes calls connect_app("kanban")

User: Add three cards to backlog
→ Hermes reads the injected Kanban tree from context, then calls app_action_batch with three add_card actions

User: Disconnect from kanban
→ Hermes calls disconnect_app("kanban")
```

## Related

- [slop-hermes package API](/api/slop-hermes)
- [Discovery & Bridge](/sdk/discovery) — shared discovery model used by the plugin
- [Python SDK API](/api/python) — underlying `slop_ai.discovery` implementation
- [Codex integration](/guides/advanced/codex) — another fixed-tool integration
- [OpenClaw integration](/guides/advanced/openclaw) — similar meta-tool pattern
24 changes: 22 additions & 2 deletions docs/sdk/discovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,11 @@ Host-specific wrappers, tool-helper layers, and prompt injection are intentional

## Integrations

Both the Claude Code and OpenClaw plugins follow the same design principles:
The Codex, Claude Code, OpenClaw, and Hermes integrations all follow the same design principles:

- **State injection** — Provider state is injected into the model's context before each turn, not fetched via tool calls
- **Minimal tool usage** — Tools are used only for connecting to apps and performing actions, never for reading state
- **Shared discovery** — Both build on `@slop-ai/discovery/service` for provider scanning and connection orchestration
- **Shared discovery contract** — TypeScript hosts build on `@slop-ai/discovery/service`; Hermes uses the mirrored Python implementation in `slop_ai.discovery`

Where they differ is **action dispatch**, due to host platform limitations.

Expand All @@ -397,6 +397,7 @@ Dynamic tools have proper parameter schemas from the provider's affordance defin
| Codex | No (current plugin) | Stable MCP tools + `UserPromptSubmit` hook-based state injection | No runtime tool registration; actions still go through meta-tools |
| Claude Code (MCP) | Yes | `notifications/tools/list_changed` — server notifies client when tool list changes | None |
| OpenClaw | No | `api.registerTool()` is one-time during `register()` | No runtime tool registration API; tools must be declared in the plugin manifest |
| Hermes | No | `register_tool()` + `pre_llm_call` hook-based state injection | Plugin tools are registered once; current package targets local CLI / single-user use |

Hosts without dynamic tool support fall back to the **meta-tool pattern**: stable tools (`app_action`, `app_action_batch`) that resolve actions at runtime. Depending on the host, the model learns the exact paths and action names from prompt-time state injection or from an explicit `connect_app` inspection step.

Expand Down Expand Up @@ -452,6 +453,24 @@ Design details:

See [OpenClaw guide](/guides/advanced/openclaw) for setup and usage.

### Hermes plugin (`slop-hermes`)

| Component | Purpose |
|---|---|
| **Tools** | `list_apps`, `connect_app`, `disconnect_app`, `app_action`, `app_action_batch` |
| **Hook** (`pre_llm_call`) | Injects connected providers' state trees into the current Hermes turn |
| **Runtime** | Background Python discovery service using `slop_ai.discovery` |

Design details:

- **Fixed tool surface** — The Hermes plugin registers the same stable five-tool catalog as the Codex and OpenClaw integrations.
- **In-process state injection** — The `pre_llm_call` hook injects fresh `## SLOP Apps` markdown directly into the current turn. No file-based IPC is needed.
- **Python discovery parity** — Uses `slop_ai.discovery` for local descriptor watching, bridge support, lazy connect, reconnect, and idle disconnect behavior.
- **Bounded injection** — Connected trees are compacted with `prepare_tree(max_nodes=...)` before rendering so prompt growth stays controlled.
- **Operational scope** — The current package is aimed at local CLI / single-user Hermes. Connected-provider state is process-global.

See [Hermes guide](/guides/advanced/hermes) for setup and usage.

## Related

- [Consumer SDK API](/api/consumer) — protocol client reference
Expand All @@ -460,3 +479,4 @@ See [OpenClaw guide](/guides/advanced/openclaw) for setup and usage.
- [Consumer guide](/guides/consumer) — usage patterns and example workflows
- [Codex guide](/guides/advanced/codex) — Codex plugin setup and usage
- [Claude Code guide](/guides/advanced/claude-code) — Claude Code plugin setup and usage
- [Hermes guide](/guides/advanced/hermes) — Hermes plugin setup and usage
61 changes: 61 additions & 0 deletions packages/python/slop-hermes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# `slop-hermes`

Hermes Agent plugin for the [SLOP protocol](https://slopai.dev).

This package adds a fixed 5-tool SLOP integration to Hermes:

- `list_apps`
- `connect_app`
- `disconnect_app`
- `app_action`
- `app_action_batch`

It also injects connected SLOP app state into each Hermes turn so the model can
see live state before calling actions.

## Install

Install into the same Python environment as Hermes:

```bash
pip install slop-hermes
```

For local development from this repo:

```bash
pip install -e /path/to/slop/packages/python/slop-hermes
```

Hermes discovers the plugin through the `hermes_agent.plugins` entry point.

Verify the plugin is visible:

```bash
hermes plugins list
```

If you explicitly manage toolsets, enable `slop` in `hermes tools` or include it in your session:

```bash
hermes chat --toolsets slop,web,terminal
```

## How it works

- starts a background `slop_ai.discovery.DiscoveryService`
- discovers local providers from `~/.slop/providers/*.json` and `/tmp/slop/providers/*.json`
- connects to browser-backed providers through the extension bridge at `ws://127.0.0.1:9339/slop-bridge`
- injects connected app state into Hermes through the `pre_llm_call` hook
- performs actions through the fixed `app_action` and `app_action_batch` tools

## Environment variables

- `SLOP_HERMES_MAX_NODES` — max nodes included in injected trees. Default: `160`
- `SLOP_HERMES_MIN_SALIENCE` — optional salience threshold for injected trees

## Notes

- This first version is designed primarily for local CLI / single-user Hermes.
- Browser bridge and direct WebSocket discovery use `slop-ai[websocket]`, which
is installed automatically with this package.
39 changes: 39 additions & 0 deletions packages/python/slop-hermes/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "slop-hermes"
version = "0.1.0"
description = "Hermes Agent plugin for discovering and controlling SLOP applications"
readme = "README.md"
license = "MIT"
requires-python = ">=3.11"
dependencies = ["slop-ai[websocket]"]
keywords = ["slop", "hermes", "plugin", "agent", "ai"]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]

[project.optional-dependencies]
test = ["pytest>=9.0"]

[project.entry-points."hermes_agent.plugins"]
slop = "slop_hermes:register"

[project.urls]
Homepage = "https://slopai.dev"
Repository = "https://github.com/devteapot/slop"
Documentation = "https://docs.slopai.dev"

[tool.hatch.build.targets.wheel]
packages = ["src/slop_hermes"]

[tool.pytest.ini_options]
testpaths = ["tests"]
7 changes: 7 additions & 0 deletions packages/python/slop-hermes/pyrightconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"include": ["src", "tests"],
"extraPaths": [
"src",
"../slop-ai/src"
]
}
Loading
Loading