Human-in-the-loop for Hermes

Human-in-the-loop for Hermes agents, on a phone.

Register one tool in a Hermes plugin and your agent asks a real person on their phone.

The integration

Add it to your Hermes agent

Run pip install pushary and register a tool in a Hermes plugin whose handler calls decisions.ask(). When the agent hits a step that needs a person, the question is pushed to that person's phone and the handler blocks until they decide. Anything short of an explicit approval comes back as not approved. The external_id is your own id for the end-user, connected once with a keyless one-tap link.

pip install pusharytwo calls
import os
from pushary import PusharyServer

px = PusharyServer(api_key=os.environ["PUSHARY_API_KEY"])

def ask_human(params, **kwargs):
    d = px.decisions.ask(
        question=params["question"],
        external_id=params["external_id"],
        type="confirm",
    )
    return "approved" if d["approved"] else f"not approved ({d['status']})"

def register(ctx):
    ctx.register_tool(
        name="ask_human",
        toolset="approvals",
        schema={"type": "object", "properties": {
            "question": {"type": "string"},
            "external_id": {"type": "string"},
        }, "required": ["question", "external_id"]},
        handler=ask_human,
        description="Ask a real person to approve before acting.",
    )

Why you need it

Hermes pauses the agent. Pushary reaches the human.

A Hermes tool handler is a plain Python function, so the whole integration is one decisions.ask() call inside it. Pushary delivers the question to the right person's phone, holds the handler open until they decide, and writes the outcome to a durable ledger. Hermes' gateway mode runs many users through one agent, so pass each user's external_id from your own user model rather than a session id. That distinction is the one thing worth getting right up front. A session identifies a conversation and a person identifies who is accountable for the action, and in gateway mode the two drift apart as soon as someone opens a second tab or comes back tomorrow. Keying on your own user id keeps every approval attributable to a human rather than to a transcript.

How it works

From ask to resume

Connect the phone once, then ask a human from the tool or step that guards the action. The waiting, the delivery, and the record are handled for you.

  1. 01

    Install the Python SDK

    Run pip install pushary into Hermes' environment and set PUSHARY_API_KEY.

  2. 02

    Connect the phone

    Call px.enroll(external_id) once per end-user to connect their phone with a keyless one-tap link.

  3. 03

    Register an ask_human tool

    In a Hermes plugin's register(ctx), call ctx.register_tool with a handler that calls px.decisions.ask(). The schema tells the model what to pass.

  4. 04

    Keep it fail-closed

    Return not approved for anything short of an explicit yes. A declined, expired, or unanswered decision means the agent does not act.

A decision is a yes or no confirm, a multiple-choice select, or a free-text input. Every one is stored with its outcome and kept in the audit log.

The Partner plan

Your agent asks your users, not just you

Ship the agent to real users and let each of them approve their own decisions from their phone, under your brand.

$99/ month, every framework included

Your users never see a Pushary login or bill.

Your users answer on their own phones

The externalId is your own id for the end-user. Connect their phone once with a keyless one-tap link, and every approval lands with the right person. No account, no app, no key on their side.

Durable, fail-closed waits

The agent stays open on a durable wait backed by a decisions ledger. If nobody answers in the window you set, the decision comes back denied, so a timeout or a restart never turns into an unapproved action.

Phone-first delivery

Pushary reaches the person on the device they carry: native app push first, then PWA push notifications, then Slack if you route it there. You do not build a delivery pipeline.

Signed webhooks and an audit trail

Every decision is written to a durable ledger you can query and export, and resolved decisions post a signed webhook to your callback URL. You have the record of who approved what and when.

FAQ

Questions, answered

Is there a Hermes-specific Pushary package?
No. Hermes integrates through pip install pushary: one registered tool whose handler calls enroll and decisions.ask is the whole integration.
How does the agent wait for the answer?
decisions.ask blocks the tool handler on a durable wait until the person responds or the window closes. Hermes holds the tool call open, so the agent continues on the human's decision.
Can each end-user get approvals on their own phone?
Yes. Pass each user's external_id from your own user model. In gateway mode, do not reuse the Hermes session id as the external_id, because the session is not the person.
What does the agent see on a decline or a timeout?
The handler returns not approved with the status, so the model knows the action was refused rather than silently skipped, and the ledger keeps the record. Telling the two apart matters, because a refusal is information the model should act on and a timeout usually means try a different person.
Can one Hermes deployment serve approvals for many customers?
That is what gateway mode plus a per-user external_id gives you. One agent process serves everyone, and each decisions.ask reaches the specific person whose data or money the action touches. On the Partner plan those people connect keyless, so none of your customers needs a Pushary account, and the decide page they land on carries your branding rather than ours.

Let your Hermes agent ask a human.

Connect a user with one tap, ask a human with one call, and act on a fail-closed decision. Every decision is saved to a durable ledger you can audit.

Partner plan, $99 a month. Your users never see a Pushary login or bill.