Metadata-Version: 2.5
Name: agentguard-spend-hermes
Version: 0.3.0
Summary: AgentGuard for Hermes Agent: local spend caps, tool guards, sub-agent limits and signed decisions.
Project-URL: Homepage, https://agentguard.run
Project-URL: AgentGuard SDK (PyPI), https://pypi.org/project/agentguard-spend/
Project-URL: AgentGuard SDK (npm), https://www.npmjs.com/package/@agentguard-run/spend
Project-URL: Hermes Agent, https://github.com/NousResearch/hermes-agent
Project-URL: Source, https://github.com/MerchantGuard/merchantguard-website/tree/main/packages/agentguard-spend-hermes
Author-email: "Dunecrest Ventures Inc." <hello@agentguard.run>
License: AgentGuard(R) Spend plugin for Hermes Agent - Alpha License
        Copyright (c) 2026 Dunecrest Ventures Inc.
        
        1. SCOPE.
        This software is the distribution published to PyPI as agentguard-spend-hermes,
        comprising the Python package agentguard_spend_hermes/ as it appears in an
        installed copy. It is licensed by Dunecrest Ventures Inc. ("Licensor") subject to
        the following thresholds:
        
          (a) Evaluation Use. Internal evaluation, prototyping, and non-commercial
              development at any call volume.
        
          (b) Free Production Threshold. Production deployments processing 10,000
              or fewer enforcement calls per calendar month, in aggregate across
              all instances operated by the licensee, are permitted under this
              License without additional fee.
        
          (c) Commercial License Required. Production deployments processing more
              than 10,000 enforcement calls per calendar month, deployments
              operated for the benefit of third parties as a service, redistribution,
              sublicensing, public hosting, and republication each require a
              separate commercial license agreement with Licensor.
        
        Commercial-license inquiries: invest@agentguard.run
        
        2. NO PATENT LICENSE GRANTED.
        Nothing in this License grants, expressly or by implication, any patent license
        to any patent, patent application, or other intellectual property right of
        Licensor. All patent rights are expressly reserved.
        
        3. SEPARATE GRANT FOR DEMONSTRATION ASSETS.
        The following assets, and ONLY these assets, are released under the BSD
        2-Clause License, reproduced in full below:
        
          - The project description distributed as the package README in the
            distribution metadata
        
          Copyright (c) 2026 Dunecrest Ventures Inc.
        
          Redistribution and use in source and binary forms, with or without
          modification, are permitted provided that the following conditions are met:
        
          1. Redistributions of source code must retain the above copyright notice,
             this list of conditions and the following disclaimer.
        
          2. Redistributions in binary form must reproduce the above copyright notice,
             this list of conditions and the following disclaimer in the documentation
             and/or other materials provided with the distribution.
        
          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
          AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
          IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
          ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
          LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
          CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
          SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
          INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
          CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
          ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
          POSSIBILITY OF SUCH DAMAGE.
        
        This grant conveys copyright permission only. It grants no patent license,
        express or implied, no covenant not to sue, and no exhaustion, estoppel, or
        implied-license rights under any patent or patent application of Licensor,
        consistent with Section 2 above. The BSD 2-Clause License is used for these
        assets precisely because it is silent as to patents.
        
        The code under agentguard_spend_hermes/ is NOT included in the grant above. The
        Hermes Agent bridge is licensed only under the alpha evaluation terms of
        Section 1 above.
        
        
        4. WARRANTY DISCLAIMER.
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
        DUNECREST VENTURES INC. BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY
        ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
        DEALINGS IN THE SOFTWARE.
        
        5. SUCCESSORS AND ASSIGNS.
        This License binds and benefits the parties' respective successors and assigns.
        In the event of an asset sale, merger, change of control, or other transfer of
        the Licensor's rights in this software, all rights and obligations under this
        License inure to the benefit of and are binding upon Licensor's successor or
        assignee. Outstanding evaluation grants survive change-of-control, but the
        successor or assignee may, upon thirty (30) days' written notice, terminate
        ongoing evaluation grants in favor of a commercial-license requirement.
        
        6. TERMINATION.
        Licensor may terminate this License with thirty (30) days' written notice for
        any reason or no reason. Upon termination, Licensee shall cease all use of the
        software under agentguard_spend_hermes/ and shall destroy all copies in Licensee's possession.
        
        7. PATENT NOTICE (35 U.S.C. § 287).
        Certain AgentGuard technologies are patent pending. All patent rights are
        expressly reserved per Section 2 above.
        
        AgentGuard(R) is a registered trademark of Dunecrest Ventures Inc.
        (U.S. Reg. No. 8281464). MerchantGuard(TM) is a trademark of Dunecrest
        Ventures Inc. (USPTO Serial No. 99051215, pending).
        
        For commercial licensing: invest@agentguard.run
License-File: LICENSE
Keywords: agent-plugin,agentguard,ai-agent-security,hermes,hermes-agent,llm-governance,nous-research,spend-control
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: agentguard-spend>=0.15.4
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: hatchling>=1.18; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.11; extra == 'dev'
Description-Content-Type: text/markdown

# AgentGuard for Hermes Agent

Local spend caps, tool-call guarding, sub-agent limits and Ed25519-signed decisions for Hermes Agent. The PyPI package name remains `agentguard-spend-hermes`.

## Install

Install into the same Python environment Hermes runs from, then explicitly enable the plugin in the same `HERMES_HOME` used by your CLI or gateway. For Hermes's default install location:

```bash
uv pip install --python ~/.hermes/hermes-agent/venv/bin/python agentguard-spend-hermes==0.3.0
hermes plugins enable agentguard-spend
```

The PyPI entry point and a directory copy under `~/.hermes/plugins/agentguard-spend` share the plugin name. Hermes loads only one of them, and the PyPI entry point wins.

For a public repository assembled with the script below, replace `owner/repo` with its actual location:

```bash
uv pip install 'agentguard-spend>=0.15.4' 'pyyaml>=6.0'
hermes plugins install owner/repo
hermes plugins enable agentguard-spend
```

Install from PyPI. Hermes's install-time scan flags the rule data, because the rules quote the commands they block, so Hermes 0.21.0 refuses `hermes plugins install owner/repo` and `--force` does not override that verdict. Replacing an existing directory copy with `hermes plugins install` also needs `--force`.

Hermes displays declared Python dependencies but does not install them. If one is missing, or the policy or keys cannot be read, AgentGuard does not let Hermes run unguarded: it registers a lockdown before any setup step, and a failed setup leaves that lockdown refusing every model call and every tool call with this message, also written to the log:

```text
AgentGuard setup failed: <reason>. Fix it, or set AGENTGUARD_DISABLE=1 to run without AgentGuard.
```

When setup succeeds the lockdown passes every call through. Enablement is required for both the PyPI entry point and directory installation. Restart the Hermes process you want to protect after installation or a policy change.

On first load AgentGuard creates `agentguard/policy.yaml`, a signing keypair and, on the first decision, `agentguard/decisions.ndjson` under `HERMES_HOME` (default `~/.hermes`). The directory is owner-only, with a private key created using mode `0600`.

The startup log identifies the active path:

```text
AgentGuard 0.3.0: official middleware active (policy=...)
```

When the host has no `register_middleware`, the 0.2.x Anthropic/OpenAI client wrappers remain available and the log says `legacy fallback active`. That fallback provides legacy spend guarding; tool guards and delegation limits require the middleware API. `AGENTGUARD_DISABLE=1` explicitly disables the plugin, including the lockdown. The legacy fallback still raises on a setup failure, and Hermes then runs without it.

## What it blocks

The shared AgentGuard rule pack checks terminal commands, text typed into a background process with Hermes's `process` tool, Python code execution and file writes. It covers credential uploads (including GnuPG, SSH and cloud credentials), destructive deletion, shared Git history changes, unsafe infrastructure changes, sensitive file writes, secret-shaped arguments, security setting changes, remote package sources, disk formatting and database wipes.

For example, uploading `~/.gnupg` with rsync is denied. Copying `.env.example` to `.env` within a project is allowed. Code execution checks literal calls to terminal, subprocess and file-writing functions as well as the shared native-code rules. Computed command or path arguments require approval.

Hermes's existing availability, approval and deny checks remain in its execution chain. AgentGuard can add a restriction; it never replaces a Hermes restriction with an allow. A gate error denies operations with effects and permits known read-only tools to continue through Hermes's checks.

## How ASK works unattended

An ASK decision in an interactive CLI with a TTY uses Hermes's own approval prompt. Approval applies to one operation. A decline, timeout or prompt error denies it.

Cron, gateway, single-query and sessions without a TTY never wait for a prompt. They deny and record this exact reason:

```text
AgentGuard: this needs a person's approval
```

Rules default to their shared settings. An operator can change a rule in `policy.yaml`, for example `guard_rules: {GP009: warn}` to ask before a sensitive write. `stop` denies, `warn` asks, and `off` disables that AgentGuard rule. Hermes's own checks still apply.

## Spend and delegation policy

The default policy has a $5 daily soft cap, a $20 daily hard cap and a $2 per-minute hard cap. Amounts are integer USD cents. At the soft cap, request middleware swaps to the provider's mapped model only when that exact model id appears in the provider's catalog data Hermes keeps locally and costs less per input token and per output token than the current model. Otherwise it keeps the model, logs one line, and the hard cap stops spending. Execution middleware checks hard caps before calling the provider and records cost afterwards.

The default downgrade targets are Sonnet for Anthropic and OpenRouter, GPT-5 mini for OpenAI, and Gemini 3.1 Flash Lite for Gemini. A provider without a mapping never swaps. Prices come from the Spend price table, Hermes's own price table and Hermes's on-disk copy of OpenRouter's model list; AgentGuard never fetches them. Existing 0.2.x policies keep their caps and can add this mapping:

```yaml
model_downgrades:
  openrouter: anthropic/claude-sonnet-4.6
  anthropic: claude-sonnet-4-6
  openai: gpt-5-mini
  gemini: gemini-3.1-flash-lite-preview

delegation:
  short_launches: 15
  short_minutes: 15
  long_launches: 40
  long_minutes: 120
  idle_seconds: 60
```

The 16th launch inside 15 active minutes, or the 41st inside 120 active minutes, requires approval. A batch counts each child. List, steer and stop operations do not count as launches. Accepted attempts count even if the downstream tool later fails, so failures cannot reset the limit.

An old policy's Anthropic downgrade target is translated to the default for direct OpenAI or Gemini calls and to OpenRouter's dotted id on OpenRouter, and then passes the same catalog and price checks. A configured `requiredCapability` stays closed because Hermes does not supply Spend capability claims.

The active clock advances during model/tool execution. Between calls it advances by at most `idle_seconds`; long idle gaps do not clear launch history. Counters are shared by child agents using the same runtime. Before each model call, AgentGuard reserves the call's estimated cost in every spend window under a short lock. The provider call runs without the lock, then the actual cost replaces the reservation; a failed, interrupted or cancelled call releases it. Reserved estimates count as spent, so calls running at the same time cannot spend the same remaining budget, and sessions, cron jobs and background sub-agents no longer wait for each other's model calls or for a pending approval prompt. Calls in flight together can pass a hard cap only by the amount their actual cost exceeds their estimates.

## Signed decisions and privacy

Every guarded model call, tool decision and delegation is a signed Spend receipt in `decisions.ndjson`. The existing Spend schema holds the metadata under `decision.governanceReceipt`: `kind` (`model_call`, `tool_call` or `delegate`), `rule_id`, `decision` and a reason. Tool receipts also include `tool_name`, `arguments_sha256` and the initial `gate_decision`, so an approved ASK remains visible.

Tool gates are recorded before execution. If Hermes itself then blocks a terminal, code, file-write or process call, or leaves it waiting for approval, a second receipt with `stage: host_result` records that restriction and the result is preserved. Results of other tools carry outside data and are not read for this.

AgentGuard never stores prompts, completions or raw tool arguments in this log. Argument hashes use SHA-256 over deterministic JSON. Rule scanning runs locally and never executes inspected commands. AgentGuard itself makes no network requests. The LLM call still goes to the provider configured in Hermes.

Model receipts identify the cost source:

| Source | Meaning |
| --- | --- |
| `gateway_reported` | Provider response includes a cost in USD, including OpenRouter usage cost. |
| `api_list_price_estimate` | Usage tokens are priced with Spend's local price table. |
| `unpriced` | No provider cost and no usable local price or usage information. |

Reported USD cost rounds up to integer cents. Estimates use Spend's rounding and include Anthropic cache tokens at base input price. These are local accounting records, not provider invoices.

Verify with the existing Spend command using your public key encoded as hex:

```bash
agentguard verify --trace ~/.hermes/agentguard/decisions.ndjson --public-key PUBLIC_KEY_HEX
```

The private key never belongs in that command. Existing 0.2.x receipts can remain at the beginning of the chain. New receipt appends use a local file lock so concurrent writers preserve sequence and signature linkage.

## Limits

This is a lexical guard, not a sandbox. Encoded programs, files fetched and executed in separate calls, and arbitrary dynamic Python can exceed what local rule matching can infer. Python cannot determine every effect of an unknown function. Known limitations of the shared guard fixtures remain visible in parity tests.

Budget and launch counters live in the Hermes process and reset on restart. Separate processes do not share live caps, even when their signed decisions share a file. Use a separate `HERMES_HOME` for separate policies. Scope labels identify the budget; they do not split one policy into independent budgets.

Before a provider call, cost is a character/token estimate over the messages, system prompt, instructions and tool schemas, with `max_tokens` (or 4096) as the output. A provider's actual charge can exceed it. Unpriced calls cannot be charged accurately and are recorded as unpriced; previously reached hard caps still block them. A missing or malformed model payload is denied. A malformed usage response latches the model gate closed until restart. A signing failure is logged as an error and prevents subsequent model calls; tool gate failures follow the read-only rule above.

Protection applies at Hermes's registered middleware boundaries. The plugin must be enabled and importable; if Hermes cannot import it at all (for example its files are removed), Hermes runs without it. Calls outside those boundaries and the legacy fallback do not gain the new tool controls. Hermes's auxiliary model calls (for example context compression, session titles, vision, smart approvals, MCP sampling and mixture-of-agents) do not pass through `llm_execution`, so they are neither capped nor recorded. The `codex_app_server` runtime hands whole turns to Codex and bypasses both boundaries.

Hermes does not pass the working directory to middleware, so AgentGuard cannot tell which branch a git command runs on and treats every branch as shared: `git reset --hard` and `git push --force` always ask or deny, on any branch. They deny by default; set `GP003` or `GP004` to `warn` under `guard_rules` to be asked instead.

## Assemble and test offline

From this monorepo:

```bash
node packages/agentguard-spend-hermes/scripts/export-guard-pack.cjs
uv run python packages/agentguard-spend-hermes/scripts/assemble-hermes-repo.py
```

This creates `dist-hermes-repo/` containing the native `plugin.yaml` and root entry point plus the Python package. It does not publish anything and refuses to overwrite an existing folder. That folder is the root layout for an eventual `owner/repo` installation.

Run pytest and ruff in an environment containing the local Spend SDK, pytest, ruff and PyYAML. Set `HERMES_TEST_PYTHON` to the installed Hermes venv's Python and `HERMES_TEST_ROOT` to its source folder to include the real-loader smoke. The smoke uses temporary homes, fake provider calls and disabled network sockets. It writes no files to the Hermes installation.

The Node exporter copies rules and matcher constants from `guard-pack.cjs` and `guard-dangerous.cjs`. Tests require the checked-in JSON to match a fresh export and compare Python and Node scans and decisions on the same original fixtures. Rule changes belong in those shared sources first.

## License

BUSL-1.1. Free for production deployments processing **up to 10,000 enforcement calls per calendar month**. Commercial licensing for higher volumes or service redistribution: `invest@agentguard.run`.

Certain AgentGuard technologies are patent pending in the United States. See https://agentguard.run/patents.
