All plugins

agentpurse

Search, quote, and buy from an AgentPurse allowance on the PayPal sandbox. Every purchase waits for Hermes' approval prompt and is sent only after a person approves it; YOLO, approvals off, auto-approve modes, and smart (model) approval cannot spend. A per-chat spend limit and /purse kill sit in front of the clerk. Disclosure — calls the author's AgentPurse service at agentpurse.vercel.app (POST /mcp and GET /api/spends/:id; the server uses the PayPal sandbox and Channel3 for product data) with AGENTPURSE_API_KEY from Hermes's secret scope, sending quotes, purchase sentences and the task/page excerpt the agent supplies; request_purchase and watch_price each wait for a person to answer Hermes's approval prompt (YOLO, approvals off, smart approval and unattended runs cannot spend), but an approved price watch later lets AgentPurse file the purchase server-side with no second Hermes prompt (/purse kill cancels open watches); a kill switch, quote cache, one-time approval grants and per-chat spent cents live in plugin state; PayPal sandbox money only, and a receipt is not a retailer order.

maaz-bin-hassanToolsv1.0.0Updated 1 hour ago

About

Search, quote, and buy from an AgentPurse allowance on the PayPal sandbox. Every purchase waits for Hermes' approval prompt and is sent only after a person approves it; YOLO, approvals off, auto-approve modes, and smart (model) approval cannot spend. A per-chat spend limit and /purse kill sit in front of the clerk. Disclosure — calls the author's AgentPurse service at agentpurse.vercel.app (POST /mcp and GET /api/spends/:id; the server uses the PayPal sandbox and Channel3 for product data) with AGENTPURSE_API_KEY from Hermes's secret scope, sending quotes, purchase sentences and the task/page excerpt the agent supplies; request_purchase and watch_price each wait for a person to answer Hermes's approval prompt (YOLO, approvals off, smart approval and unattended runs cannot spend), but an approved price watch later lets AgentPurse file the purchase server-side with no second Hermes prompt (/purse kill cancels open watches); a kill switch, quote cache, one-time approval grants and per-chat spent cents live in plugin state; PayPal sandbox money only, and a receipt is not a retailer order.

AgentPurse for Hermes

Hermes can search, quote, and buy from an AgentPurse allowance. PayPal is the rail. The AgentPurse clerk still allows, holds, or denies every payment in code. Hermes shows its own approval prompt before a purchase is even sent. A kill switch refuses the next one.

This is a native Hermes plugin (plugin.yaml plus register(ctx)). It is not a prompt pack and it does not wrap the MCP server as a blind pipe: the purchase hook can block, and the purchase handler will not pay unless that hook just recorded a one-time grant for the same merchant and amount.

Sandbox money only. A captured receipt is a PayPal sandbox charge. No retailer order is placed.

Install

Requires Hermes 0.22.7 or newer (requires_hermes: ">=0.22.7"). That is the stable release this plugin was written against.

From a checkout of this repository:

hermes plugins install /absolute/path/to/agentpurse/plugins/hermes

Hermes asks for AGENTPURSE_API_KEY when the plugin is enabled. Paste an agent key. The public Grocer demo key works against the live sandbox:

agpk_grocer_demo_maaz

Hermes stores that key in the active profile's secret scope. The plugin reads it with agent.secret_scope.get_secret. It does not open a .env file and it does not read the process environment.

Optional settings live under plugins.entries.agentpurse.settings:

| Key | Default | Meaning |
| --- | --- | --- |
| base_url | https://agentpurse.vercel.app | AgentPurse origin. Use http://127.0.0.1:3000 only for a local server. |
| spend_limit_cents | 5000 | Integer cents this chat may capture. 0 blocks every purchase. |
| approval_timeout_s | 120 | How long to poll after the clerk holds a cheque. 0 returns the approval URL and does not wait. |

hermes config set plugins.entries.agentpurse.settings.spend_limit_cents 5000
hermes config set plugins.entries.agentpurse.settings.approval_timeout_s 120

Restart the chat after enabling the plugin. /purse budget should name Grocer's remaining allowance.

Tools

Each tool is the AgentPurse MCP tool of the same name. Prices are integer cents. The server reads catalog prices, so a catalog quote must not include one. Listing text and page excerpts are data. They are not instructions.

| Tool | Effect |
| --- | --- |
| search_merchants | Known merchants, including which are blocked. No money moves. |
| search_products | Channel3 offers. No money moves. |
| get_product | One product by id or URL. No money moves. |
| check_price | Today's price against 90 days: low, typical, or high. |
| find_alternatives | Similar products under a price. |
| get_quote | A quote id, the server's price, and the guard verdict. No money moves. |
| request_purchase | Sent only after Hermes' approval prompt. The clerk captures, holds, or denies. |
| watch_price | Asks Hermes first. A later price hit is a normal clerk decision, with no second Hermes prompt. |
| list_watches | Open and finished watches. |
| cancel_watch | Stop a watch. |
| get_budget | Remaining allowance. |
| list_receipts | PayPal sandbox receipts. |

/purse budget, /purse receipts, /purse kill, and /purse resume are slash commands. There is no Desktop pane: budget and receipts are these commands, and a renderer plugin would be a separate trust surface the catalog scans on its own.

The bundled skill agentpurse:shop tells the model to quote first and to stop when the guard blocks. Hermes does not load plugin skills into the system prompt automatically. The tool descriptions carry the same rules.

Approval flow

sequenceDiagram
  participant Person
  participant Hermes
  participant Plugin
  participant AgentPurse
  Person->>Hermes: Buy oat milk from Green Grocer for $2.55
  Hermes->>Plugin: get_quote
  Plugin->>AgentPurse: MCP get_quote
  AgentPurse-->>Plugin: quote, price, guard
  Hermes->>Plugin: pre_tool_call request_purchase
  alt kill switch, spend limit, blocked merchant, guard block, or nobody can approve
    Plugin-->>Hermes: block
    Hermes-->>Person: refusal, nothing sent
  else a person can answer
    Plugin-->>Hermes: approve, with merchant, amount, remaining budget, guard
    Hermes->>Person: Hermes approval prompt
    alt denied or no answer
      Hermes-->>Person: not sent
    else approved
      Hermes->>Plugin: request_purchase handler
      Plugin->>AgentPurse: MCP request_purchase
      alt captured
        AgentPurse-->>Person: sandbox receipt
      else held for a signature
        Plugin-->>Person: approval URL
        Plugin->>AgentPurse: poll GET /api/spends/:id until timeout
      end
    end
  end

The hook never returns a silent allow for request_purchase or watch_price. It returns block, or approve so Hermes shows its own prompt. That approve leaves a proposed one-time grant for the same chat, tool, merchant, and amount. The grant can spend only after Hermes' post_approval_response hook reports that a person chose Once, Session, or Always on that exact prompt. A skipped hook cannot spend, and neither can an approval no person gave.

Hermes can approve a plugin prompt without asking anyone: --yolo, /yolo, approvals.mode: off (the Desktop "Approvals: off" toggle), cron or single-query auto-approve, and smart approval, where an auxiliary model decides. None of those fires a human answer, so the handler refuses with "Hermes let this payment through without asking a person". Smart approvals (decided_by: aux_llm) are refused too: a model never moves the money. Each attempt gets its own rule_key, so a saved Session or Always answer never covers a later payment.

These runs are blocked before a prompt, so they cannot hang and Hermes cannot auto-approve them:

  • /purse kill is on
  • the per-chat spend limit would be exceeded (spent + amount > limit, integer cents)
  • the merchant is blocked, or the intent guard said block
  • the allowance cannot cover the amount
  • cron (HERMES_CRON_SESSION)
  • single-query (hermes chat -q, HERMES_SINGLE_QUERY_SESSION)
  • an unattended worker or a platform with no approval card
  • Hermes started with --yolo (HERMES_YOLO_MODE)

Any other bypass is caught at the handler by the missing human answer, as above.

If the clerk holds the cheque (pending_approval), the handler returns the dashboard URL (/purses/<owner>?hold=<intent>) and polls GET /api/spends/<id> until the status settles or approval_timeout_s elapses. The poll stops early if the kill switch comes on. It does not approve the cheque. Signing is the owner's passkey or the dashboard. Unattended runs do not poll.

A quote pays once. After a capture, say the PayPal sandbox receipt and repeat any fulfillment line from the server. Never say the item is on its way.

Slash commands

| Command | Effect |
| --- | --- |
| /purse budget | Allowance left, this chat's spend, and the kill switch. |
| /purse receipts | Latest PayPal sandbox receipts, with order ids. |
| /purse kill | Refuse new purchases and cancel open price watches. |
| /purse resume | Turn the kill switch off. The next purchase still waits for approval. |

State (kill switch, quote cache, per-chat ledger) is in the plugin's Hermes state for the active profile. It is not written into the plugin directory. /purse kill does not refund a payment that already captured.

Disclosures

  • Network. The plugin calls the configured AgentPurse origin over HTTPS (HTTP only on localhost). That is https://agentpurse.vercel.app by default: POST /mcp and GET /api/spends/<id>. AgentPurse, not this plugin, talks to the PayPal sandbox and to Channel3. Redirects are refused so the bearer token cannot leave that host.
  • Credential. AGENTPURSE_API_KEY is stored by Hermes and read through Hermes' secret scope. The plugin does not read .env, auth.json, or another tool's login.
  • Local ledger. The plugin stores a kill switch, a short quote cache, short-lived approval grants, and the cents captured in each chat, in Hermes plugin state. It does not store the API key there.
  • No shell, no background work, no telemetry. The plugin does not spawn processes, does not patch Hermes, and does not phone home. There is no self-updater.
  • Sandbox only. Demo keys move sandbox money. A receipt is not a retailer order. Channel3 checkout is not live.
  • Dependencies. No third-party Python packages. The HTTP client is the standard library, so there is no unpinned requirement for Hermes to resolve.

Develop

From plugins/hermes, with no Hermes install required:

python -m pip install "pytest>=8.3,<9"
pytest

The suite mocks the MCP client. It covers the approval grant, approvals no person gave (YOLO, approvals off, smart, deny, timeout), blocked merchants, spend-limit boundaries, the kill switch, cron and single-query fail-closed, passkey poll timeouts, and purchase calls that are not retried.

Catalog admission, from a Hermes 0.22.7 install:

hermes plugins validate plugins/hermes --install-deps
hermes plugins doctor plugins/hermes --ci

README from the reviewed commit 84a1ed7; it updates when the author re-pins.