Metadata-Version: 2.4
Name: agentmint-hermes-runner
Version: 0.11.0
Summary: Route Hermes delegate_task(background=True) to named, persistent AgentMint subagents.
Project-URL: Homepage, https://github.com/mesutcelik/agentmint-hermes
Project-URL: Repository, https://github.com/mesutcelik/agentmint-hermes
Project-URL: Issues, https://github.com/mesutcelik/agentmint-hermes/issues
Author: AgentMint
License: MIT
License-File: LICENSE
Keywords: agentmint,ai-agents,delegation,hermes,mpp,stripe-link,subagents,tempo
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.7; extra == 'dev'
Description-Content-Type: text/markdown

# agentmint-hermes-runner

Python adapter that bridges Hermes' `delegate_task(background=True)` to **named, persistent AgentMint subagents** — specialists that accumulate `/workspace/MEMORY.md` across calls.

One install path: monkey-patch `delegate_task` so every async delegation can route to AgentMint. The LLM picks the target subagent via either `default_agent_name` (set at install) or by including `"agentmint-<name>"` in the `toolsets` list (per-call routing).

> The Hermes-installable skill that drives this adapter lives in a separate catalog repo: **[mesutcelik/agentmint-skills](https://github.com/mesutcelik/agentmint-skills)** — `hermes skills install mesutcelik/agentmint-skills/hermes-delegate-task`. The skill references this package by its PyPI name (`pip install agentmint-hermes-runner`).

## Status

**v0.11.0** — alpha. Auth backends: `BearerAuth` (any rail — Stripe-Link / x402 / Tempo MPP), `TempoAuth` (Tempo USDC.e — Tier 1 direct only; the `delegate_task` patches require Bearer).

**Breaking change in 0.11.0**: routing is now strictly **opt-in** via the `toolsets` directive — no catch-all. `agentmint-hermes-init` bootstraps the wallet only; it no longer mints a `general-worker`. The LLM has to include `"agentmint-<name>"` in the `toolsets` list for the patch to dispatch to AgentMint; otherwise `delegate_task` falls through to Hermes-native untouched. Operators mint each subagent separately per use case.

## Routing model

**Opt-in only.** The patched `delegate_task`:

- LLM includes `"agentmint-<name>"` in the `toolsets` list → routes to that AgentMint subagent
- LLM does NOT include the directive → falls through to Hermes-native `delegate_task` unchanged

There is no catch-all default. AgentMint is never selected transparently — the LLM has to consciously opt in by emitting the toolsets directive. Install the `hermes-delegate-task` skill so the LLM knows the convention.

If you want a catch-all for a specific deployment, set `$AGENTMINT_DEFAULT_AGENT_NAME` in Hermes' env before boot — explicit override only.

### Setup — four commands

```bash
# 1. Install the runner inside Hermes' Python environment
pip install agentmint-hermes-runner

# 2. One-time interactive bootstrap — picks a rail, tops up the wallet,
#    caches the JWT to ~/.agentmint/credentials.json. Does NOT mint any
#    subagents — that's use-case-specific (next step).
agentmint-hermes-init

# 3. Install the routing-convention skill so the LLM knows the
#    `toolsets=["agentmint-<name>"]` directive exists.
hermes skills install mesutcelik/agentmint-skills/hermes-delegate-task

# 4. Restart Hermes
#    The runner's `hermes_agent.plugins` entry-point fires at boot,
#    reads the cached JWT, and auto-wires `delegate_task` in opt-in mode.
```

Then mint subagents per use case (one curl per specialist). For example, a code-review specialist:

```bash
JWT=$(jq -r '.tokens | to_entries[0].value.access_token' ~/.agentmint/credentials.json)
curl -X POST https://api.agentmint.store/a2a \
  -H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"agent.create","params":{
    "name":"pr-reviewer",
    "mode":"all-inclusive",
    "persona":"You review GitHub PRs. Follow the pr-review skill exactly.",
    "skills":["mesutcelik/agentmint-skills/pr-review"]
  }}'
```

After that, the Hermes LLM can dispatch to it:

```python
delegate_task(
    background=True,
    goal="Review PR 42 in owner/repo",
    toolsets=["terminal", "file", "agentmint-pr-reviewer"],
)
```

If you'd rather wire the adapter by hand (e.g. injecting the JWT from a secret manager, not a file on disk), the lower-level API still works:

```python
import os
from agentmint_hermes_runner import AgentMintDispatcher, BearerAuth, install_delegate_task_wrapper

dispatcher = AgentMintDispatcher(auth=BearerAuth(jwt=os.environ["AGENTMINT_JWT"]))
install_delegate_task_wrapper(dispatcher, default_agent_name=None)
```

The autoload entry-point becomes a no-op if `AGENTMINT_JWT` is unset AND `~/.agentmint/credentials.json` is absent — safe to leave installed even in setups that bring their own wiring.

### Setup — per-call specialist routing

The LLM picks the target specialist on each call via the `toolsets` list:

```python
# Operator setup is identical — generic default + LLM-driven overrides.
install_delegate_task_wrapper(dispatcher, default_agent_name="general-worker")

# The LLM then dispatches like this:
delegate_task(
    background=True,
    goal="Review PR 42 in mesutcelik/agentmint-mono",
    toolsets=["terminal", "file", "agentmint-pr-reviewer"],
)
```

The adapter parses `agentmint-pr-reviewer` from `toolsets`, routes that call to that subagent (overriding `default_agent_name`), and strips the entry from the toolset list before composing the prompt the subagent receives.

This is a **workaround** for Hermes' `delegate_task` not accepting a dispatcher-target argument. A formal proposal is in `docs/hermes-feature-request.md` — when an upstream extension lands, this hack will be deprecated in favor of a first-class `dispatcher` or `metadata` parameter.

### Pattern discipline

- `default_agent_name` → generic worker only (`general-worker`, `default-worker`, etc.)
- Specialists → only via `toolsets=["agentmint-<name>"]`
- Never name a specialist as the default. Specialists scale; defaults are catch-all.

See `examples/persistent.py` for a complete operator setup snippet.

## Install

```bash
pip install agentmint-hermes-runner
```

## Test

```bash
pip install -e ".[dev]"
pytest
ruff check .
```

## Lower-level surface

If you want to drive AgentMint directly without the `delegate_task` patch:

```python
result = dispatcher.dispatch(
    agent_name="reviewer-myrepo",
    goal="Review the diff at /workspace/pr-42.diff and flag risks.",
    context="Project at /workspace, Python 3.11, uses Flask + PyJWT.",
    toolsets=["terminal", "file"],     # "web" raises UnsupportedToolset
    role="leaf",                        # or "orchestrator"
    max_iterations=50,
    child_timeout_seconds=600,
    workspace_files=[                   # ship inputs into the sandbox before the run
        {"path": "/workspace/pr-42.diff", "content": "diff --git a/foo ..."},
    ],
    cleanup_paths=["/workspace/pr-42.diff"],  # wipe them after the run
)

# Batch dispatch (Hermes tasks=[…] analog):
results = dispatcher.dispatch_batch(
    tasks=[
        Task(agent_name="researcher-wasm", goal="WASM 2026 survey"),
        Task(agent_name="researcher-riscv", goal="RISC-V 2026 survey"),
    ],
    max_concurrent_children=3,
    child_timeout_seconds=900,
)
```

## Known unsupported

- **`toolsets=["web"]`** — no canonical AgentMint web-fetch skill yet. Raises `UnsupportedToolset`.
- **`max_spawn_depth`** — AgentMint sandboxes aren't structurally bounded by depth.
- **Tempo + the `delegate_task` patches** — polling against `agent.run.status` is Bearer-only. Tempo customers can use Tier 1 (direct curl) but not the install/plugin paths above.

## License

MIT
