agentmint-hermes-runner 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. agentmint_hermes_runner-0.4.0/.github/workflows/ci.yml +22 -0
  2. agentmint_hermes_runner-0.4.0/.github/workflows/release.yml +20 -0
  3. agentmint_hermes_runner-0.4.0/.gitignore +12 -0
  4. agentmint_hermes_runner-0.4.0/LICENSE +21 -0
  5. agentmint_hermes_runner-0.4.0/PKG-INFO +117 -0
  6. agentmint_hermes_runner-0.4.0/README.md +92 -0
  7. agentmint_hermes_runner-0.4.0/agentmint-hermes/SKILL.md +221 -0
  8. agentmint_hermes_runner-0.4.0/examples/hermes_strategy_b.py +51 -0
  9. agentmint_hermes_runner-0.4.0/examples/stripe_link.py +38 -0
  10. agentmint_hermes_runner-0.4.0/examples/tempo_wallet.py +38 -0
  11. agentmint_hermes_runner-0.4.0/pyproject.toml +49 -0
  12. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/__init__.py +40 -0
  13. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/auth/__init__.py +5 -0
  14. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/auth/base.py +18 -0
  15. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/auth/bearer.py +29 -0
  16. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/auth/tempo.py +37 -0
  17. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/client.py +40 -0
  18. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/dispatcher.py +226 -0
  19. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/exceptions.py +28 -0
  20. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/hermes_patch.py +213 -0
  21. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/models.py +61 -0
  22. agentmint_hermes_runner-0.4.0/src/agentmint_hermes_runner/translation.py +93 -0
  23. agentmint_hermes_runner-0.4.0/tests/__init__.py +0 -0
  24. agentmint_hermes_runner-0.4.0/tests/test_bearer_auth.py +34 -0
  25. agentmint_hermes_runner-0.4.0/tests/test_client.py +43 -0
  26. agentmint_hermes_runner-0.4.0/tests/test_dispatch_batch.py +111 -0
  27. agentmint_hermes_runner-0.4.0/tests/test_dispatcher.py +70 -0
  28. agentmint_hermes_runner-0.4.0/tests/test_hermes_patch.py +163 -0
  29. agentmint_hermes_runner-0.4.0/tests/test_tempo_auth.py +33 -0
  30. agentmint_hermes_runner-0.4.0/tests/test_timeout.py +53 -0
  31. agentmint_hermes_runner-0.4.0/tests/test_translation.py +95 -0
@@ -0,0 +1,22 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ - run: pip install -e ".[dev]"
21
+ - run: ruff check .
22
+ - run: pytest -v
@@ -0,0 +1,20 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ environment: pypi
11
+ permissions:
12
+ id-token: write
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: pip install build
19
+ - run: python -m build
20
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .eggs/
5
+ build/
6
+ dist/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .venv/
10
+ venv/
11
+ .env
12
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AgentMint
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,117 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentmint-hermes-runner
3
+ Version: 0.4.0
4
+ Summary: Route Hermes delegate_task(background=True) to named, persistent AgentMint subagents.
5
+ Project-URL: Homepage, https://github.com/mesutcelik/agentmint-hermes
6
+ Project-URL: Repository, https://github.com/mesutcelik/agentmint-hermes
7
+ Project-URL: Issues, https://github.com/mesutcelik/agentmint-hermes/issues
8
+ Author: AgentMint
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agentmint,ai-agents,delegation,hermes,mpp,stripe-link,subagents,tempo
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: httpx>=0.27
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=8.0; extra == 'dev'
23
+ Requires-Dist: ruff>=0.7; extra == 'dev'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # agentmint-hermes-runner
27
+
28
+ Route Hermes `delegate_task(background=True)` to named, persistent AgentMint subagents.
29
+
30
+ > Positioning + full quickstart in [`agentmint-hermes/SKILL.md`](agentmint-hermes/SKILL.md).
31
+
32
+ ## Status
33
+
34
+ **v0.4.0** — alpha. Auth backends: `BearerAuth` (Stripe-Link), `TempoAuth` (Tempo USDC.e). Polling-only delivery. Hermes feature coverage matrix in [`agentmint-hermes/SKILL.md`](agentmint-hermes/SKILL.md).
35
+
36
+ ## Install in Hermes
37
+
38
+ ```bash
39
+ hermes skills install mesutcelik/agentmint-hermes/agentmint-hermes
40
+ ```
41
+
42
+ (The third segment is the skill subfolder inside the repo, per Hermes' `GitHubSource` convention.)
43
+
44
+ ## Three-line Hermes wiring (Strategy B)
45
+
46
+ ```python
47
+ import os
48
+ from agentmint_hermes_runner import (
49
+ AgentMintDispatcher, BearerAuth, install_delegate_task_wrapper,
50
+ )
51
+
52
+ dispatcher = AgentMintDispatcher(auth=BearerAuth(jwt=os.environ["AGENTMINT_JWT"]))
53
+ install_delegate_task_wrapper(dispatcher, default_agent_name="default-worker")
54
+ ```
55
+
56
+ Every `delegate_task(background=True)` inside Hermes now routes to AgentMint's `default-worker` subagent. Its `/workspace/MEMORY.md` accumulates across every delegation. No HTTPS, no ngrok, no webhook secret — a daemon thread polls `agent.run.status` (free, Bearer-only) every 5 s and pushes completions onto Hermes' `completion_queue` directly. Server-side requires AgentMint API ≥ 0.7.0 for the polling endpoint.
57
+
58
+ ## Install
59
+
60
+ ```bash
61
+ pip install agentmint-hermes-runner
62
+ ```
63
+
64
+ ## Surface
65
+
66
+ ```python
67
+ from agentmint_hermes_runner import (
68
+ AgentMintDispatcher,
69
+ AgentMintWebhookReceiver,
70
+ BearerAuth, TempoAuth,
71
+ Task,
72
+ )
73
+
74
+ dispatcher = AgentMintDispatcher(
75
+ auth=BearerAuth(jwt=os.environ["AGENTMINT_JWT"]),
76
+ webhook_url="https://my-gateway.example.com/agentmint-webhook", # optional
77
+ )
78
+
79
+ # Single dispatch (Hermes delegate_task analog):
80
+ result = dispatcher.dispatch(
81
+ agent_name="reviewer-myrepo",
82
+ goal="Review the diff in /workspace/pr-42 and flag risks.",
83
+ context="Project at /workspace, Python 3.11, uses Flask + PyJWT.",
84
+ toolsets=["terminal", "file"], # "web" raises UnsupportedToolset in v0.2
85
+ role="leaf", # or "orchestrator"
86
+ max_iterations=50,
87
+ child_timeout_seconds=600, # floor 30s; fires agent.cancel on expiry
88
+ )
89
+
90
+ # Batch dispatch (Hermes tasks=[…] analog):
91
+ results = dispatcher.dispatch_batch(
92
+ tasks=[
93
+ Task(agent_name="researcher-wasm", goal="WASM 2026 survey", context="…"),
94
+ Task(agent_name="researcher-riscv", goal="RISC-V 2026 survey", context="…"),
95
+ ],
96
+ max_concurrent_children=3,
97
+ child_timeout_seconds=900,
98
+ )
99
+ # results in input order; failed/timeout/interrupted statuses returned in-band
100
+ ```
101
+
102
+ ## Test
103
+
104
+ ```bash
105
+ pip install -e ".[dev]"
106
+ pytest
107
+ ruff check .
108
+ ```
109
+
110
+ ## Known unsupported (v0.2)
111
+
112
+ - **`toolsets=["web"]`** — no canonical AgentMint web-fetch skill yet. The supported harnesses (claude-code / codex / opencode) all have built-in web access via the harness itself, but we don't expose a Hermes-symmetric toolset for it. Raises `UnsupportedToolset` at compose time so the gap is loud, not silent.
113
+ - **`max_spawn_depth`** — AgentMint sandboxes aren't structurally bounded by depth.
114
+
115
+ ## License
116
+
117
+ MIT
@@ -0,0 +1,92 @@
1
+ # agentmint-hermes-runner
2
+
3
+ Route Hermes `delegate_task(background=True)` to named, persistent AgentMint subagents.
4
+
5
+ > Positioning + full quickstart in [`agentmint-hermes/SKILL.md`](agentmint-hermes/SKILL.md).
6
+
7
+ ## Status
8
+
9
+ **v0.4.0** — alpha. Auth backends: `BearerAuth` (Stripe-Link), `TempoAuth` (Tempo USDC.e). Polling-only delivery. Hermes feature coverage matrix in [`agentmint-hermes/SKILL.md`](agentmint-hermes/SKILL.md).
10
+
11
+ ## Install in Hermes
12
+
13
+ ```bash
14
+ hermes skills install mesutcelik/agentmint-hermes/agentmint-hermes
15
+ ```
16
+
17
+ (The third segment is the skill subfolder inside the repo, per Hermes' `GitHubSource` convention.)
18
+
19
+ ## Three-line Hermes wiring (Strategy B)
20
+
21
+ ```python
22
+ import os
23
+ from agentmint_hermes_runner import (
24
+ AgentMintDispatcher, BearerAuth, install_delegate_task_wrapper,
25
+ )
26
+
27
+ dispatcher = AgentMintDispatcher(auth=BearerAuth(jwt=os.environ["AGENTMINT_JWT"]))
28
+ install_delegate_task_wrapper(dispatcher, default_agent_name="default-worker")
29
+ ```
30
+
31
+ Every `delegate_task(background=True)` inside Hermes now routes to AgentMint's `default-worker` subagent. Its `/workspace/MEMORY.md` accumulates across every delegation. No HTTPS, no ngrok, no webhook secret — a daemon thread polls `agent.run.status` (free, Bearer-only) every 5 s and pushes completions onto Hermes' `completion_queue` directly. Server-side requires AgentMint API ≥ 0.7.0 for the polling endpoint.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install agentmint-hermes-runner
37
+ ```
38
+
39
+ ## Surface
40
+
41
+ ```python
42
+ from agentmint_hermes_runner import (
43
+ AgentMintDispatcher,
44
+ AgentMintWebhookReceiver,
45
+ BearerAuth, TempoAuth,
46
+ Task,
47
+ )
48
+
49
+ dispatcher = AgentMintDispatcher(
50
+ auth=BearerAuth(jwt=os.environ["AGENTMINT_JWT"]),
51
+ webhook_url="https://my-gateway.example.com/agentmint-webhook", # optional
52
+ )
53
+
54
+ # Single dispatch (Hermes delegate_task analog):
55
+ result = dispatcher.dispatch(
56
+ agent_name="reviewer-myrepo",
57
+ goal="Review the diff in /workspace/pr-42 and flag risks.",
58
+ context="Project at /workspace, Python 3.11, uses Flask + PyJWT.",
59
+ toolsets=["terminal", "file"], # "web" raises UnsupportedToolset in v0.2
60
+ role="leaf", # or "orchestrator"
61
+ max_iterations=50,
62
+ child_timeout_seconds=600, # floor 30s; fires agent.cancel on expiry
63
+ )
64
+
65
+ # Batch dispatch (Hermes tasks=[…] analog):
66
+ results = dispatcher.dispatch_batch(
67
+ tasks=[
68
+ Task(agent_name="researcher-wasm", goal="WASM 2026 survey", context="…"),
69
+ Task(agent_name="researcher-riscv", goal="RISC-V 2026 survey", context="…"),
70
+ ],
71
+ max_concurrent_children=3,
72
+ child_timeout_seconds=900,
73
+ )
74
+ # results in input order; failed/timeout/interrupted statuses returned in-band
75
+ ```
76
+
77
+ ## Test
78
+
79
+ ```bash
80
+ pip install -e ".[dev]"
81
+ pytest
82
+ ruff check .
83
+ ```
84
+
85
+ ## Known unsupported (v0.2)
86
+
87
+ - **`toolsets=["web"]`** — no canonical AgentMint web-fetch skill yet. The supported harnesses (claude-code / codex / opencode) all have built-in web access via the harness itself, but we don't expose a Hermes-symmetric toolset for it. Raises `UnsupportedToolset` at compose time so the gap is loud, not silent.
88
+ - **`max_spawn_depth`** — AgentMint sandboxes aren't structurally bounded by depth.
89
+
90
+ ## License
91
+
92
+ MIT
@@ -0,0 +1,221 @@
1
+ ---
2
+ name: agentmint-hermes
3
+ description: Mint AgentMint pay-as-you-go subagents from Hermes. Provisions a persistent sandbox (Claude Code / Codex / OpenCode harness, any model via OpenRouter) for a long-running task; subsequent `delegate_task(background=true)` calls dispatch to it, hibernate the box between calls, and bill per run. Pay via Stripe-Link (link-cli) or Tempo USDC.e.
4
+ version: 0.2.0
5
+ author: AgentMint
6
+ license: MIT
7
+ platforms: [linux, macos]
8
+ metadata:
9
+ hermes:
10
+ tags: [Subagents, Delegation, Payments, MPP, Sandbox]
11
+ related_skills: [mpp-agent, stripe-link-cli]
12
+ ---
13
+
14
+ # AgentMint × Hermes
15
+
16
+ Long-lived, named, USDC-paid subagents that Hermes can `delegate_task` against. Each subagent has its own bounded sandbox (Upstash Box), its own filesystem that persists across calls (`/workspace/MEMORY.md` is the standard memory anchor), and a stable name (`reviewer-myrepo`, `support-acme`, …). Hibernates to zero between calls — billed only when running.
17
+
18
+ ## When to use
19
+
20
+ - Hermes' main session needs a **specialist** (PR reviewer, compliance checker, customer-support agent, codebase oracle, etc.) that accumulates domain knowledge across days/weeks.
21
+ - A task naturally **fans out** into N independent slices and you want each one on its own sandbox.
22
+ - You want **`delegate_task(background=true)`** to dispatch the actual work somewhere with isolated credentials, not the Hermes gateway itself.
23
+ - You want to use a **specific harness × model** combination (e.g. opencode + `openrouter/fusion`, claude-code + claude-sonnet-4-6) without baking those choices into Hermes.
24
+
25
+ Not the right tool when:
26
+ - The task is one-shot and Hermes can answer directly.
27
+ - You need cross-subagent shared state (each subagent's MEMORY is its own).
28
+
29
+ ## Two integration tiers
30
+
31
+ ### Tier 1 — Direct (no Python, no Hermes code changes)
32
+
33
+ Hermes calls AgentMint's JSON-RPC `/a2a` endpoint via `terminal` using whichever wallet skill the user has authenticated. Mint once, run many times.
34
+
35
+ ### Tier 2 — `delegate_task` background dispatch
36
+
37
+ Pip-install `agentmint-hermes-runner` and wire it into Hermes' gateway. After that, `delegate_task(background=True, …)` results route through PR #40946's async-delegation rail (merged 2026-06-15). Hermes' existing `_async_delegation_watcher` re-injects the result as a new turn in the originating session.
38
+
39
+ ## Wallet matrix
40
+
41
+ AgentMint speaks the same `/a2a` endpoint for both wallets — pick whichever Hermes already has authenticated.
42
+
43
+ | Wallet | When | Path |
44
+ |---|---|---|
45
+ | **Stripe-Link** (`link-cli`) | User has a card, no crypto wallet. Best for non-developers. | Bearer JWT against a caller-wide credit wallet — bootstrap once, debits per call |
46
+ | **Tempo Wallet** | User has Tempo wallet authenticated; wants spend controls + service discovery | Per-call x402/MPP, USDC.e on Tempo (`eip155:4217`) |
47
+
48
+ Fetch the underlying wallet skill via `web_extract` before invoking, so its setup steps are in context:
49
+
50
+ - `https://agentmint.store/SKILL.md` — full AgentMint API (every method, every rail)
51
+ - Hermes' built-in `stripe-link-cli` skill for `link-cli`
52
+ - Hermes' built-in `mpp-agent` skill for `tempo request`
53
+
54
+ ## Tier 1 — Direct mint + run
55
+
56
+ ### Path A: Stripe-Link (link-cli + credit wallet)
57
+
58
+ Bootstrap once, then every subsequent `agent.*` call is Bearer-paid against a shared credit wallet — no Stripe per-call fee.
59
+
60
+ ```bash
61
+ # 1) Bootstrap the wallet (min $10) — via the stripe-link-cli skill
62
+ link-cli mpp pay https://api.agentmint.store/a2a \
63
+ -X POST -H 'Content-Type: application/json' \
64
+ -d '{"jsonrpc":"2.0","id":1,"method":"credits.topup","params":{"amount_usd":10}}' \
65
+ --spend-request-id <lsrq_…>
66
+ # → response.access_token = <jwt> (caller-wide; works for any subagent)
67
+
68
+ # 2) Mint a subagent (Bearer-paid, 0.10 USDC equivalent debited from wallet)
69
+ curl -X POST https://api.agentmint.store/a2a \
70
+ -H 'Authorization: Bearer <jwt>' -H 'Content-Type: application/json' \
71
+ -d '{"jsonrpc":"2.0","id":1,"method":"agent.create","params":{"name":"reviewer-myrepo"}}'
72
+
73
+ # 3) Run the subagent (per-call price debited from the same wallet)
74
+ curl -X POST https://api.agentmint.store/a2a \
75
+ -H 'Authorization: Bearer <jwt>' -H 'Content-Type: application/json' \
76
+ -d '{"jsonrpc":"2.0","id":1,"method":"agent.run","params":{"name":"reviewer-myrepo","prompt":"…"}}'
77
+
78
+ # 4) Check the shared balance any time
79
+ curl -X POST https://api.agentmint.store/a2a \
80
+ -H 'Authorization: Bearer <jwt>' -H 'Content-Type: application/json' \
81
+ -d '{"jsonrpc":"2.0","id":1,"method":"credits.balance","params":{}}'
82
+ ```
83
+
84
+ Same JWT works across every subagent the user mints — one balance, N subagents.
85
+
86
+ ### Path B: Tempo Wallet
87
+
88
+ ```bash
89
+ tempo wallet login # one-time, browser-based
90
+ tempo wallet whoami # confirms address + USDC balance
91
+
92
+ tempo request -X POST \
93
+ --json '{"jsonrpc":"2.0","id":1,"method":"agent.create","params":{"name":"reviewer-myrepo"}}' \
94
+ https://api.agentmint.store/a2a
95
+ ```
96
+
97
+ Pin to `tempo-request@0.5.2` — newer versions hit "Invalid base64 JSON header" against AgentMint's challenge. Downgrade with `tempo cli 0.0.0 downgrade tempo request cli to 0.5.2`.
98
+
99
+ ## Tier 2 — `delegate_task(background=True)` dispatch (Strategy B)
100
+
101
+ `install_delegate_task_wrapper` monkey-patches `tools.async_delegation.dispatch_async_delegation` (the PR #40946 hook) so every `delegate_task(background=True, single-task)` call inside Hermes transparently routes to a named, persistent AgentMint subagent. Sync `delegate_task` and batch `delegate_task` are untouched.
102
+
103
+ Completion is delivered via **polling** against AgentMint's `agent.run.status` endpoint (Bearer-only, free). A daemon thread per dispatch polls every 5 s and pushes completions onto Hermes' `completion_queue` via `_push_completion_event`. No public HTTPS endpoint, no webhook secret, no HTTP route to register — polling is the only delivery mode.
104
+
105
+ ### Step-by-step setup
106
+
107
+ **Step 1 — Bootstrap an AgentMint wallet (one-time)**
108
+
109
+ ```bash
110
+ # Stripe-Link (recommended, supports polling) — min $10:
111
+ link-cli mpp pay https://api.agentmint.store/a2a \
112
+ -X POST -H 'Content-Type: application/json' \
113
+ -d '{"jsonrpc":"2.0","id":1,"method":"credits.topup","params":{"amount_usd":10}}'
114
+ # → response.result.access_token = <JWT>
115
+
116
+ export AGENTMINT_JWT=<the JWT>
117
+ ```
118
+
119
+ (Tempo path also works, but polling is Bearer-only — Tempo users must use webhook mode, covered in "Webhook mode" below.)
120
+
121
+ **Step 2 — Pre-mint the subagent (one-time)**
122
+
123
+ ```bash
124
+ curl -X POST https://api.agentmint.store/a2a \
125
+ -H "Authorization: Bearer $AGENTMINT_JWT" \
126
+ -H 'Content-Type: application/json' \
127
+ -d '{"jsonrpc":"2.0","id":1,"method":"agent.create","params":{
128
+ "name":"default-worker",
129
+ "harness":"opencode",
130
+ "model":"openrouter/fusion"}}'
131
+ ```
132
+
133
+ This is the entity that will REMEMBER across every Hermes delegation. Its `/workspace/MEMORY.md` accumulates context across every call. Cost: 0.10 USDC equivalent debited from the credit wallet.
134
+
135
+ **Step 3 — Install the Python adapter in Hermes' venv**
136
+
137
+ ```bash
138
+ pip install agentmint-hermes-runner
139
+ ```
140
+
141
+ Verify: `python -c "import agentmint_hermes_runner; print(agentmint_hermes_runner.__version__)"` → `0.3.0` or higher.
142
+
143
+ **Step 4 — Add three lines to your Hermes gateway startup**
144
+
145
+ Put this in your Hermes gateway entry-point (or wherever you instantiate the gateway), BEFORE any `delegate_task(background=True)` call:
146
+
147
+ ```python
148
+ import os
149
+ from agentmint_hermes_runner import (
150
+ AgentMintDispatcher, BearerAuth, install_delegate_task_wrapper,
151
+ )
152
+
153
+ dispatcher = AgentMintDispatcher(auth=BearerAuth(jwt=os.environ["AGENTMINT_JWT"]))
154
+ install_delegate_task_wrapper(dispatcher, default_agent_name="default-worker")
155
+ ```
156
+
157
+ That's the entire wiring. The function returns an `uninstall()` callable if you want to undo it later (mostly useful in tests).
158
+
159
+ **Step 5 — Restart Hermes and test**
160
+
161
+ Restart the gateway so the new module loads and the patch is in effect. Then from inside a Hermes session:
162
+
163
+ ```
164
+ > use delegate_task with background=true to ask: "Say hello and tell me what
165
+ you remember from prior calls."
166
+ ```
167
+
168
+ The LLM will call `delegate_task(background=True, goal="…")`. Behind the scenes:
169
+ 1. Adapter calls `agent.run` on AgentMint with `async: true`
170
+ 2. AgentMint returns a `run_id` (e.g. `arun_a1b2c3d4`)
171
+ 3. Adapter spawns a daemon thread that polls `agent.run.status` every 5 s
172
+ 4. AgentMint finishes the run (~15-60 s typically)
173
+ 5. Adapter calls `_push_completion_event` → Hermes' `completion_queue`
174
+ 6. Hermes' `_async_delegation_watcher` drains and re-injects the result as a new turn
175
+
176
+ **Step 6 — Verify persistence (the value proposition)**
177
+
178
+ Call `delegate_task(background=true)` twice with different goals against the same Hermes session. The second response should reference details from the first — because `/workspace/MEMORY.md` survived between dispatches. That's the differentiator from Hermes' native `delegate_task` (which always starts fresh).
179
+
180
+
181
+ ## Hermes `delegate_task` coverage (v0.3)
182
+
183
+ | Hermes feature | AgentMint via this runner | Notes |
184
+ |---|---|---|
185
+ | `goal` | ✅ Concatenated under `## Goal` | `dispatcher.dispatch(goal=…)` |
186
+ | `context` | ✅ Concatenated under `## Context` | Client-side concat — no server-side `context` field |
187
+ | `toolsets=["terminal", "file"]` restrictions | ✅ Soft hints in prompt ("Do not run shell commands.", …) | Sandbox can't structurally enforce; the harness should respect the hint |
188
+ | `toolsets=["web"]` | ❌ **Unsupported** — raises `UnsupportedToolset` | No canonical web-fetch skill in the AgentMint catalog yet; tracked separately |
189
+ | `role="leaf"` / `"orchestrator"` | ✅ Soft hint in prompt | Default `"leaf"` |
190
+ | `max_iterations` | ✅ Soft hint ("Soft iteration budget: ~N actions.") | Harness-dependent enforcement |
191
+ | `tasks=[{…}, {…}]` (batch) | ✅ `dispatcher.dispatch_batch(tasks=…)` — parallel via ThreadPoolExecutor, results in input order | Each Task targets a named subagent |
192
+ | `max_concurrent_children` | ✅ `max_concurrent_children=N` param to `dispatch_batch` | Default 3 |
193
+ | `child_timeout_seconds` | ✅ `child_timeout_seconds=N` param; floor 30s; fires `agent.cancel` on expiry | Single + batch |
194
+ | Interrupt cascade | ✅ `cancel_event=threading.Event` to `dispatch_batch` — fires `agent.cancel` on all in-flight | |
195
+ | `background=True` (PR #40946) | ✅ **`install_delegate_task_wrapper(...)` — Strategy B, polling** | Transparent to the LLM; polling-only |
196
+ | Result ordering (by task index) | ✅ `dispatch_batch` returns in input order regardless of completion order | |
197
+ | `max_spawn_depth` (nested delegation) | n/a | AgentMint sandboxes aren't depth-bounded structurally |
198
+ | `/agents` TUI overlay | n/a | Pure Hermes UI feature; use `dispatcher.list()` to enumerate subagents |
199
+ | Credential inheritance | **better** | Each subagent has its own credentials (no parent key sharing) |
200
+ | "Fresh conversation per call" | **inverted** | AgentMint subagents persist `/workspace/MEMORY.md` across calls — this is the core value |
201
+
202
+ ## Pitfalls
203
+
204
+ - **Mode 1 (Stripe-Link) and Mode 2 (Tempo) don't share state.** Funds in the credit wallet (`account:<principal>`) are not transferable to a blockchain address and vice versa. Pick one model per principal.
205
+ - **JWT is caller-wide on Stripe-Link.** One token authorises any agent.* call against any subagent the principal owns. If lost, re-bootstrap via `credits.topup` with no Bearer — the server rotates the canonical jti. The old token is NOT auto-revoked; revoke it explicitly via `credits.revoke_token --jti <jti>` if you know the lost jti.
206
+ - **`name` is global + immutable.** First mint wins. Pick something specific enough to avoid collisions (`reviewer-mesutcelik-agentmint`, not `reviewer`). Released only by `agent.delete`.
207
+ - **Stripe-MPP only accepts `credits.topup`.** Trying `agent.create` over Stripe-MPP returns `400 use_bearer_after_topup`. Bootstrap with `credits.topup` first.
208
+ - **Tempo broadcast is client-side.** `tempo request` broadcasts before AgentMint's server sees the payment, so a server-side failure after `verify` still leaves the customer charged. Grep server logs for `[agentmint/refund-needed]` for manual operator refund triggers.
209
+ - **Wallet keys never enter Hermes context.** Both wallet skills store credentials under their own config dirs; never `cat`/`read_file` them.
210
+
211
+ ## Verification
212
+
213
+ ```bash
214
+ # Confirm the AgentMint endpoint is reachable + supports your wallet
215
+ curl -X POST https://api.agentmint.store/a2a \
216
+ -H 'Content-Type: application/json' \
217
+ -d '{"jsonrpc":"2.0","id":1,"method":"agent.create","params":{}}'
218
+ # → 402 with accepts[] enumerating supported chains. Pick the one matching your wallet.
219
+ ```
220
+
221
+ For Tier 2, the canary is a complete dispatch + webhook + re-injection cycle. See `examples/stripe_link.py` and `examples/tempo_wallet.py` in the agentmint-hermes repo.
@@ -0,0 +1,51 @@
1
+ """Strategy B: wire AgentMint into Hermes so `delegate_task(background=True)`
2
+ transparently routes to a persistent AgentMint subagent.
3
+
4
+ Prerequisites:
5
+ 1. Bootstrap an AgentMint credit wallet via link-cli (one-time, $10 min):
6
+ link-cli mpp pay https://api.agentmint.store/a2a -X POST \\
7
+ -H 'Content-Type: application/json' \\
8
+ -d '{"jsonrpc":"2.0","id":1,"method":"credits.topup","params":{"amount_usd":10}}'
9
+ export AGENTMINT_JWT=<the access_token from the response>
10
+
11
+ 2. Pre-mint your subagent (this is the entity that will REMEMBER across
12
+ every Hermes delegation):
13
+ curl -X POST https://api.agentmint.store/a2a \\
14
+ -H "Authorization: Bearer $AGENTMINT_JWT" \\
15
+ -H 'Content-Type: application/json' \\
16
+ -d '{"jsonrpc":"2.0","id":1,"method":"agent.create",
17
+ "params":{"name":"default-worker","harness":"opencode",
18
+ "model":"openrouter/fusion"}}'
19
+
20
+ 3. pip install agentmint-hermes-runner inside Hermes' virtualenv.
21
+
22
+ Drop this snippet into your Hermes gateway startup code (before any
23
+ delegate_task call). That's the entire wiring — no HTTPS endpoint, no
24
+ webhook secret, no HTTP route.
25
+ """
26
+ import os
27
+
28
+ from agentmint_hermes_runner import (
29
+ AgentMintDispatcher,
30
+ BearerAuth,
31
+ install_delegate_task_wrapper,
32
+ )
33
+
34
+
35
+ def main() -> None:
36
+ dispatcher = AgentMintDispatcher(
37
+ auth=BearerAuth(jwt=os.environ["AGENTMINT_JWT"]),
38
+ )
39
+
40
+ install_delegate_task_wrapper(
41
+ dispatcher=dispatcher,
42
+ default_agent_name="default-worker",
43
+ poll_interval=5.0,
44
+ )
45
+ # From here on, every delegate_task(background=True) call inside Hermes
46
+ # routes to the AgentMint subagent named "default-worker". Its
47
+ # /workspace/MEMORY.md accumulates context across every delegation.
48
+
49
+
50
+ if __name__ == "__main__":
51
+ main()
@@ -0,0 +1,38 @@
1
+ """Dispatch a generic 'hello' goal to a named AgentMint subagent via Stripe-Link.
2
+
3
+ Prerequisites:
4
+ 1. Bootstrap a credit wallet via link-cli (one-time, min $10):
5
+ link-cli mpp pay https://api.agentmint.store/a2a \\
6
+ -X POST -H 'Content-Type: application/json' \\
7
+ -d '{"jsonrpc":"2.0","id":1,"method":"credits.topup","params":{"amount_usd":10}}'
8
+ The response includes `result.access_token` — the wallet JWT.
9
+
10
+ 2. export AGENTMINT_JWT=<the jwt>
11
+ 3. Pre-mint a subagent once (or call dispatcher.create() in code):
12
+ agentmint agent create --name hello-bot
13
+ 4. export AGENT_NAME=hello-bot
14
+
15
+ Run:
16
+ python examples/stripe_link.py
17
+ """
18
+ import os
19
+
20
+ from agentmint_hermes_runner import AgentMintDispatcher, BearerAuth
21
+
22
+
23
+ def main() -> None:
24
+ dispatcher = AgentMintDispatcher(
25
+ endpoint=os.environ.get("AGENTMINT_ENDPOINT", "https://api.agentmint.store/a2a"),
26
+ auth=BearerAuth(jwt=os.environ["AGENTMINT_JWT"]),
27
+ )
28
+
29
+ agent_name = os.environ["AGENT_NAME"]
30
+ result = dispatcher.dispatch(
31
+ agent_name=agent_name,
32
+ goal="Say hello and tell me what you remember from prior calls.",
33
+ )
34
+ print(result)
35
+
36
+
37
+ if __name__ == "__main__":
38
+ main()
@@ -0,0 +1,38 @@
1
+ """Dispatch a generic 'hello' goal via Tempo (per-call USDC.e on eip155:4217).
2
+
3
+ Prerequisites:
4
+ 1. tempo wallet login (one-time, browser-based)
5
+ 2. Funded USDC.e on Tempo mainnet (eip155:4217)
6
+ 3. tempo-request@0.5.2 — newer versions break with "Invalid base64 JSON
7
+ header". Downgrade with: `tempo cli 0.0.0 downgrade tempo request cli to 0.5.2`
8
+ 4. Pre-mint a subagent once:
9
+ tempo request -X POST --json \\
10
+ '{"jsonrpc":"2.0","id":1,"method":"agent.create","params":{"name":"hello-bot"}}' \\
11
+ https://api.agentmint.store/a2a
12
+ 5. export AGENT_NAME=hello-bot
13
+ 6. (optional) export TEMPO_ACCOUNT=<account-name>
14
+
15
+ Run:
16
+ python examples/tempo_wallet.py
17
+ """
18
+ import os
19
+
20
+ from agentmint_hermes_runner import AgentMintDispatcher, TempoAuth
21
+
22
+
23
+ def main() -> None:
24
+ dispatcher = AgentMintDispatcher(
25
+ endpoint=os.environ.get("AGENTMINT_ENDPOINT", "https://api.agentmint.store/a2a"),
26
+ auth=TempoAuth(account=os.environ.get("TEMPO_ACCOUNT")),
27
+ )
28
+
29
+ agent_name = os.environ["AGENT_NAME"]
30
+ result = dispatcher.dispatch(
31
+ agent_name=agent_name,
32
+ goal="Say hello and tell me what you remember from prior calls.",
33
+ )
34
+ print(result)
35
+
36
+
37
+ if __name__ == "__main__":
38
+ main()