atbash-hermes-plugin 0.1.3.dev0__tar.gz → 0.1.3.dev2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atbash-hermes-plugin
3
- Version: 0.1.3.dev0
3
+ Version: 0.1.3.dev2
4
4
  Summary: Atbash safety plugin for Hermes Agent
5
5
  Author: atbash
6
6
  License-Expression: LicenseRef-Atbash-Proprietary
@@ -10,7 +10,7 @@ Keywords: atbash,hermes,hermes-agent,agent-safety,ai-safety,tool-guard,judge,pol
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: atbash-sdk==0.1.3.dev0
13
+ Requires-Dist: atbash-sdk==0.1.3.dev2
14
14
  Dynamic: license-file
15
15
 
16
16
  # Atbash Hermes Plugin
@@ -35,13 +35,13 @@ stopped before execution.
35
35
  Install the plugin into the same Python environment that runs Hermes:
36
36
 
37
37
  ```bash
38
- pip install atbash-hermes-plugin
38
+ pip install atbash-hermes-plugin==0.1.3.dev2
39
39
  ```
40
40
 
41
41
  If Hermes is installed in a virtual environment, use that environment's Python:
42
42
 
43
43
  ```bash
44
- /path/to/hermes/venv/bin/python -m pip install atbash-hermes-plugin
44
+ /path/to/hermes/venv/bin/python -m pip install atbash-hermes-plugin==0.1.3.dev2
45
45
  ```
46
46
 
47
47
  ## Configure Atbash
@@ -77,6 +77,7 @@ Add:
77
77
  ATBASH_KEY_PATH=$HOME/.config/atbash/guard-client-key
78
78
  ATBASH_ENFORCE_DECISION=true
79
79
  ATBASH_DEBUG=false
80
+ ATBASH_ORG_NAME=your-org-name
80
81
  ```
81
82
 
82
83
  Restart Hermes after changing `.env`.
@@ -97,12 +98,21 @@ hermes
97
98
  # Override the Atbash API endpoint.
98
99
  ATBASH_ENDPOINT=https://api.atbash.io
99
100
 
101
+ # Set to self-hosted when using your own judge endpoint. Self-hosted judges
102
+ # require ATBASH_JUDGE_VERIFY_PUBKEY so the SDK can verify signed responses.
103
+ ATBASH_JUDGE_ENDPOINT_POLICY=default
104
+ ATBASH_JUDGE_VERIFY_PUBKEY=
105
+
100
106
  # Fail closed when Atbash cannot be reached. Default: true.
101
107
  ATBASH_ENFORCE_DECISION=true
102
108
 
103
109
  # Emit verbose plugin logs. Default: false.
104
110
  ATBASH_DEBUG=false
105
111
 
112
+ # Resolve the Atbash organization subscription/network. This lets the SDK
113
+ # choose the public or private chain for that org.
114
+ ATBASH_ORG_NAME=your-org-name
115
+
106
116
  # Override where learned Hermes tool classifications are saved.
107
117
  ATBASH_TOOL_MAP_PATH=$HOME/.config/atbash/hermes-tool-map.json
108
118
  ```
@@ -166,6 +176,7 @@ Example `~/.hermes/.env` for Docker:
166
176
  ATBASH_KEY_PATH=/opt/data/atbash/guard-client-key
167
177
  ATBASH_ENFORCE_DECISION=true
168
178
  ATBASH_DEBUG=false
179
+ ATBASH_ORG_NAME=your-org-name
169
180
  ```
170
181
 
171
182
  Run Hermes:
@@ -184,6 +195,7 @@ docker run --rm -it \
184
195
  -e ATBASH_KEY_PATH=/opt/data/atbash/guard-client-key \
185
196
  -e ATBASH_ENFORCE_DECISION=true \
186
197
  -e ATBASH_DEBUG=false \
198
+ -e ATBASH_ORG_NAME=your-org-name \
187
199
  nousresearch/hermes-agent
188
200
  ```
189
201
 
@@ -211,6 +223,18 @@ Hermes sessions.
211
223
  - `ATBASH_ENFORCE_DECISION=true`: fail closed and block.
212
224
  - `ATBASH_ENFORCE_DECISION=false`: fail open and allow.
213
225
 
226
+ For `HOLD`, the user-facing block message is:
227
+
228
+ ```text
229
+ Action held for operator review. The agent will not be jailed — please approve or reject this request from the Atbash dashboard, then ask the agent to try again.
230
+ Reason: <original reason from judge>
231
+ Judgment ID: <held judgment id, when provided by the SDK>
232
+ ```
233
+
234
+ After dashboard approval or rejection, the SDK can query held-action status with
235
+ the judgment ID. The Hermes plugin blocks the original tool call and asks the
236
+ user to retry after review, rather than automatically re-running the action.
237
+
214
238
  ## Troubleshooting
215
239
 
216
240
  If Hermes does not show the plugin:
@@ -20,13 +20,13 @@ stopped before execution.
20
20
  Install the plugin into the same Python environment that runs Hermes:
21
21
 
22
22
  ```bash
23
- pip install atbash-hermes-plugin
23
+ pip install atbash-hermes-plugin==0.1.3.dev2
24
24
  ```
25
25
 
26
26
  If Hermes is installed in a virtual environment, use that environment's Python:
27
27
 
28
28
  ```bash
29
- /path/to/hermes/venv/bin/python -m pip install atbash-hermes-plugin
29
+ /path/to/hermes/venv/bin/python -m pip install atbash-hermes-plugin==0.1.3.dev2
30
30
  ```
31
31
 
32
32
  ## Configure Atbash
@@ -62,6 +62,7 @@ Add:
62
62
  ATBASH_KEY_PATH=$HOME/.config/atbash/guard-client-key
63
63
  ATBASH_ENFORCE_DECISION=true
64
64
  ATBASH_DEBUG=false
65
+ ATBASH_ORG_NAME=your-org-name
65
66
  ```
66
67
 
67
68
  Restart Hermes after changing `.env`.
@@ -82,12 +83,21 @@ hermes
82
83
  # Override the Atbash API endpoint.
83
84
  ATBASH_ENDPOINT=https://api.atbash.io
84
85
 
86
+ # Set to self-hosted when using your own judge endpoint. Self-hosted judges
87
+ # require ATBASH_JUDGE_VERIFY_PUBKEY so the SDK can verify signed responses.
88
+ ATBASH_JUDGE_ENDPOINT_POLICY=default
89
+ ATBASH_JUDGE_VERIFY_PUBKEY=
90
+
85
91
  # Fail closed when Atbash cannot be reached. Default: true.
86
92
  ATBASH_ENFORCE_DECISION=true
87
93
 
88
94
  # Emit verbose plugin logs. Default: false.
89
95
  ATBASH_DEBUG=false
90
96
 
97
+ # Resolve the Atbash organization subscription/network. This lets the SDK
98
+ # choose the public or private chain for that org.
99
+ ATBASH_ORG_NAME=your-org-name
100
+
91
101
  # Override where learned Hermes tool classifications are saved.
92
102
  ATBASH_TOOL_MAP_PATH=$HOME/.config/atbash/hermes-tool-map.json
93
103
  ```
@@ -151,6 +161,7 @@ Example `~/.hermes/.env` for Docker:
151
161
  ATBASH_KEY_PATH=/opt/data/atbash/guard-client-key
152
162
  ATBASH_ENFORCE_DECISION=true
153
163
  ATBASH_DEBUG=false
164
+ ATBASH_ORG_NAME=your-org-name
154
165
  ```
155
166
 
156
167
  Run Hermes:
@@ -169,6 +180,7 @@ docker run --rm -it \
169
180
  -e ATBASH_KEY_PATH=/opt/data/atbash/guard-client-key \
170
181
  -e ATBASH_ENFORCE_DECISION=true \
171
182
  -e ATBASH_DEBUG=false \
183
+ -e ATBASH_ORG_NAME=your-org-name \
172
184
  nousresearch/hermes-agent
173
185
  ```
174
186
 
@@ -196,6 +208,18 @@ Hermes sessions.
196
208
  - `ATBASH_ENFORCE_DECISION=true`: fail closed and block.
197
209
  - `ATBASH_ENFORCE_DECISION=false`: fail open and allow.
198
210
 
211
+ For `HOLD`, the user-facing block message is:
212
+
213
+ ```text
214
+ Action held for operator review. The agent will not be jailed — please approve or reject this request from the Atbash dashboard, then ask the agent to try again.
215
+ Reason: <original reason from judge>
216
+ Judgment ID: <held judgment id, when provided by the SDK>
217
+ ```
218
+
219
+ After dashboard approval or rejection, the SDK can query held-action status with
220
+ the judgment ID. The Hermes plugin blocks the original tool call and asks the
221
+ user to retry after review, rather than automatically re-running the action.
222
+
199
223
  ## Troubleshooting
200
224
 
201
225
  If Hermes does not show the plugin:
@@ -8,6 +8,12 @@ from typing import Any, Dict, Optional
8
8
 
9
9
  logger = logging.getLogger("atbash-hermes-plugin")
10
10
 
11
+ HOLD_MESSAGE = (
12
+ "Action held for operator review. The agent will not be jailed — please approve "
13
+ "or reject this request from the Atbash dashboard, then ask the agent to try "
14
+ "again.\nReason: {reason}"
15
+ )
16
+
11
17
  DEFAULT_TOOL_CLASS_MAP = {
12
18
  "browser_click": "browser_interaction",
13
19
  "browser_navigate": "network",
@@ -136,6 +142,27 @@ def _extract_reason(raw: Any) -> str:
136
142
  return str(raw)
137
143
 
138
144
 
145
+ def _extract_judgment_id(raw: Any) -> str:
146
+ for attr in ("tool_call_id", "judgment_id", "id"):
147
+ value = getattr(raw, attr, None)
148
+ if isinstance(value, str) and value.strip():
149
+ return value.strip()
150
+
151
+ if isinstance(raw, dict):
152
+ for key in ("tool_call_id", "judgment_id", "id"):
153
+ value = raw.get(key)
154
+ if isinstance(value, str) and value.strip():
155
+ return value.strip()
156
+ return ""
157
+
158
+
159
+ def _format_hold_message(reason: str, judgment_id: str = "") -> str:
160
+ message = HOLD_MESSAGE.format(reason=reason)
161
+ if judgment_id:
162
+ message += f"\nJudgment ID: {judgment_id}"
163
+ return message
164
+
165
+
139
166
  def _safe_json_value(value: Any) -> Any:
140
167
  if value is None or isinstance(value, (str, int, float, bool)):
141
168
  return value
@@ -155,8 +182,11 @@ class AtbashHermesGuard:
155
182
  self.debug = _as_bool(os.getenv("ATBASH_DEBUG"), False)
156
183
  self.fail_closed = _as_bool(os.getenv("ATBASH_ENFORCE_DECISION"), True)
157
184
  self.endpoint = os.getenv("ATBASH_ENDPOINT")
185
+ self.judge_endpoint_policy = os.getenv("ATBASH_JUDGE_ENDPOINT_POLICY")
186
+ self.judge_verify_pubkey = os.getenv("ATBASH_JUDGE_VERIFY_PUBKEY")
158
187
  self.key_path = os.getenv("ATBASH_KEY_PATH")
159
188
  self.privkey = os.getenv("ATBASH_AGENT_PRIVKEY")
189
+ self.org_name = os.getenv("ATBASH_ORG_NAME")
160
190
  self.provider = os.getenv("HERMES_PROVIDER")
161
191
  self.model = os.getenv("HERMES_MODEL")
162
192
  self.tool_map_path = Path(
@@ -190,25 +220,53 @@ class AtbashHermesGuard:
190
220
  from atbash import Atbash # type: ignore
191
221
  from atbash.types import ToolCallInput # type: ignore
192
222
  except Exception:
193
- raise RuntimeError("atbash-sdk is required. Install with: pip install atbash-sdk==0.1.3") from e
223
+ raise RuntimeError("atbash-sdk is required. Install with: pip install atbash-sdk==0.1.3.dev2") from e
194
224
 
195
225
  self.ToolCallInput = ToolCallInput
196
- judge_cfg = {"endpoint": self.endpoint} if self.endpoint else None
226
+ judge_cfg = self._judge_config()
197
227
 
198
228
  # Prefer explicit key material if provided.
199
229
  if self.privkey:
200
230
  try:
201
- return Atbash(self.privkey, endpoint=self.endpoint or "https://atbash.ai")
231
+ return Atbash.from_config(
232
+ agent_key=self.privkey,
233
+ judge=judge_cfg,
234
+ org_name=self.org_name,
235
+ fail_closed=self.fail_closed,
236
+ )
202
237
  except TypeError:
203
- return Atbash(self.privkey)
238
+ kwargs: Dict[str, Any] = {
239
+ "org_name": self.org_name,
240
+ "fail_closed": self.fail_closed,
241
+ }
242
+ if self.endpoint:
243
+ kwargs["endpoint"] = self.endpoint
244
+ if self.judge_verify_pubkey:
245
+ kwargs["verify_pubkey"] = self.judge_verify_pubkey
246
+ return Atbash(self.privkey, **kwargs)
204
247
 
205
248
  # Use SDK-native config loader for key file/env/config.
206
249
  return Atbash.from_config(
207
250
  key_path=self.key_path,
208
251
  judge=judge_cfg,
252
+ org_name=self.org_name,
209
253
  fail_closed=self.fail_closed,
210
254
  )
211
255
 
256
+ def _judge_config(self) -> Optional[Dict[str, str]]:
257
+ if not self.endpoint:
258
+ return None
259
+ if self.judge_endpoint_policy == "self-hosted":
260
+ return {
261
+ "policy": "self-hosted",
262
+ "endpoint": self.endpoint,
263
+ "verify_pubkey": self.judge_verify_pubkey or "",
264
+ }
265
+ return {
266
+ "policy": "default",
267
+ "endpoint": self.endpoint,
268
+ }
269
+
212
270
  def _judge(
213
271
  self,
214
272
  tool_name: str,
@@ -288,12 +346,22 @@ class AtbashHermesGuard:
288
346
  reason = _extract_reason(verdict_raw)
289
347
 
290
348
  if self.debug:
291
- logger.info("Atbash verdict tool=%s verdict=%s reason=%s", tool_name, verdict, reason)
349
+ logger.info(
350
+ "Atbash verdict tool=%s verdict=%s reason=%s judgment_id=%s",
351
+ tool_name,
352
+ verdict,
353
+ reason,
354
+ _extract_judgment_id(verdict_raw),
355
+ )
292
356
 
293
357
  if verdict == "HOLD":
358
+ hold_message = _format_hold_message(
359
+ reason,
360
+ _extract_judgment_id(verdict_raw),
361
+ )
294
362
  return {
295
363
  "action": "block",
296
- "message": f"Held by Atbash for operator review: {reason}",
364
+ "message": hold_message,
297
365
  }
298
366
 
299
367
  if verdict in {"BLOCK", "DENY", "REJECT", "DISALLOW"}:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atbash-hermes-plugin
3
- Version: 0.1.3.dev0
3
+ Version: 0.1.3.dev2
4
4
  Summary: Atbash safety plugin for Hermes Agent
5
5
  Author: atbash
6
6
  License-Expression: LicenseRef-Atbash-Proprietary
@@ -10,7 +10,7 @@ Keywords: atbash,hermes,hermes-agent,agent-safety,ai-safety,tool-guard,judge,pol
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: atbash-sdk==0.1.3.dev0
13
+ Requires-Dist: atbash-sdk==0.1.3.dev2
14
14
  Dynamic: license-file
15
15
 
16
16
  # Atbash Hermes Plugin
@@ -35,13 +35,13 @@ stopped before execution.
35
35
  Install the plugin into the same Python environment that runs Hermes:
36
36
 
37
37
  ```bash
38
- pip install atbash-hermes-plugin
38
+ pip install atbash-hermes-plugin==0.1.3.dev2
39
39
  ```
40
40
 
41
41
  If Hermes is installed in a virtual environment, use that environment's Python:
42
42
 
43
43
  ```bash
44
- /path/to/hermes/venv/bin/python -m pip install atbash-hermes-plugin
44
+ /path/to/hermes/venv/bin/python -m pip install atbash-hermes-plugin==0.1.3.dev2
45
45
  ```
46
46
 
47
47
  ## Configure Atbash
@@ -77,6 +77,7 @@ Add:
77
77
  ATBASH_KEY_PATH=$HOME/.config/atbash/guard-client-key
78
78
  ATBASH_ENFORCE_DECISION=true
79
79
  ATBASH_DEBUG=false
80
+ ATBASH_ORG_NAME=your-org-name
80
81
  ```
81
82
 
82
83
  Restart Hermes after changing `.env`.
@@ -97,12 +98,21 @@ hermes
97
98
  # Override the Atbash API endpoint.
98
99
  ATBASH_ENDPOINT=https://api.atbash.io
99
100
 
101
+ # Set to self-hosted when using your own judge endpoint. Self-hosted judges
102
+ # require ATBASH_JUDGE_VERIFY_PUBKEY so the SDK can verify signed responses.
103
+ ATBASH_JUDGE_ENDPOINT_POLICY=default
104
+ ATBASH_JUDGE_VERIFY_PUBKEY=
105
+
100
106
  # Fail closed when Atbash cannot be reached. Default: true.
101
107
  ATBASH_ENFORCE_DECISION=true
102
108
 
103
109
  # Emit verbose plugin logs. Default: false.
104
110
  ATBASH_DEBUG=false
105
111
 
112
+ # Resolve the Atbash organization subscription/network. This lets the SDK
113
+ # choose the public or private chain for that org.
114
+ ATBASH_ORG_NAME=your-org-name
115
+
106
116
  # Override where learned Hermes tool classifications are saved.
107
117
  ATBASH_TOOL_MAP_PATH=$HOME/.config/atbash/hermes-tool-map.json
108
118
  ```
@@ -166,6 +176,7 @@ Example `~/.hermes/.env` for Docker:
166
176
  ATBASH_KEY_PATH=/opt/data/atbash/guard-client-key
167
177
  ATBASH_ENFORCE_DECISION=true
168
178
  ATBASH_DEBUG=false
179
+ ATBASH_ORG_NAME=your-org-name
169
180
  ```
170
181
 
171
182
  Run Hermes:
@@ -184,6 +195,7 @@ docker run --rm -it \
184
195
  -e ATBASH_KEY_PATH=/opt/data/atbash/guard-client-key \
185
196
  -e ATBASH_ENFORCE_DECISION=true \
186
197
  -e ATBASH_DEBUG=false \
198
+ -e ATBASH_ORG_NAME=your-org-name \
187
199
  nousresearch/hermes-agent
188
200
  ```
189
201
 
@@ -211,6 +223,18 @@ Hermes sessions.
211
223
  - `ATBASH_ENFORCE_DECISION=true`: fail closed and block.
212
224
  - `ATBASH_ENFORCE_DECISION=false`: fail open and allow.
213
225
 
226
+ For `HOLD`, the user-facing block message is:
227
+
228
+ ```text
229
+ Action held for operator review. The agent will not be jailed — please approve or reject this request from the Atbash dashboard, then ask the agent to try again.
230
+ Reason: <original reason from judge>
231
+ Judgment ID: <held judgment id, when provided by the SDK>
232
+ ```
233
+
234
+ After dashboard approval or rejection, the SDK can query held-action status with
235
+ the judgment ID. The Hermes plugin blocks the original tool call and asks the
236
+ user to retry after review, rather than automatically re-running the action.
237
+
214
238
  ## Troubleshooting
215
239
 
216
240
  If Hermes does not show the plugin:
@@ -0,0 +1 @@
1
+ atbash-sdk==0.1.3.dev2
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "atbash-hermes-plugin"
7
- version = "0.1.3.dev0"
7
+ version = "0.1.3.dev2"
8
8
  description = "Atbash safety plugin for Hermes Agent"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -24,7 +24,7 @@ keywords = [
24
24
  "policy"
25
25
  ]
26
26
  dependencies = [
27
- "atbash-sdk==0.1.3.dev0"
27
+ "atbash-sdk==0.1.3.dev2"
28
28
  ]
29
29
 
30
30
  [project.urls]
@@ -1 +0,0 @@
1
- atbash-sdk==0.1.3.dev0