agentx-python 0.6.11__tar.gz → 0.6.12__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 (66) hide show
  1. {agentx_python-0.6.11/agentx_python.egg-info → agentx_python-0.6.12}/PKG-INFO +15 -2
  2. {agentx_python-0.6.11 → agentx_python-0.6.12}/README.md +14 -1
  3. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/client.py +2 -0
  4. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/models.py +1 -1
  5. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/prompts.py +6 -0
  6. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/monitor/client.py +49 -1
  7. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/monitor/models.py +59 -0
  8. agentx_python-0.6.12/agentx/monitor/online_evaluators.py +120 -0
  9. agentx_python-0.6.12/agentx/version.py +1 -0
  10. {agentx_python-0.6.11 → agentx_python-0.6.12/agentx_python.egg-info}/PKG-INFO +15 -2
  11. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx_python.egg-info/SOURCES.txt +1 -0
  12. agentx_python-0.6.11/agentx/version.py +0 -1
  13. {agentx_python-0.6.11 → agentx_python-0.6.12}/LICENSE +0 -0
  14. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/__init__.py +0 -0
  15. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/agentx.py +0 -0
  16. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/cli.py +0 -0
  17. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/__init__.py +0 -0
  18. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/_term.py +0 -0
  19. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/adapters/__init__.py +0 -0
  20. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/adapters/http_endpoint.py +0 -0
  21. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/adapters/precomputed.py +0 -0
  22. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/adapters/raw.py +0 -0
  23. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/datasets.py +0 -0
  24. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/evaluation_settings.py +0 -0
  25. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/redaction.py +0 -0
  26. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/reporting.py +0 -0
  27. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/results.py +0 -0
  28. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/runner.py +0 -0
  29. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/evaluations/tracing.py +0 -0
  30. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/exceptions.py +0 -0
  31. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/__init__.py +0 -0
  32. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/_perf.py +0 -0
  33. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/_traced_call.py +0 -0
  34. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/anthropic.py +0 -0
  35. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/autogen.py +0 -0
  36. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/crewai.py +0 -0
  37. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/google_adk.py +0 -0
  38. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/google_genai.py +0 -0
  39. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/langchain.py +0 -0
  40. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/litellm.py +0 -0
  41. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/llamaindex.py +0 -0
  42. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/openai.py +0 -0
  43. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/integrations/openai_agents.py +0 -0
  44. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/monitor/__init__.py +0 -0
  45. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/monitor/patterns.py +0 -0
  46. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/monitor/profile.py +0 -0
  47. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/monitor/signals.py +0 -0
  48. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/py.typed +0 -0
  49. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/resources/__init__.py +0 -0
  50. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/resources/agent.py +0 -0
  51. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/resources/conversation.py +0 -0
  52. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/resources/workforce.py +0 -0
  53. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/tracing/__init__.py +0 -0
  54. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/tracing/ci_types.py +0 -0
  55. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/tracing/ingest_client.py +0 -0
  56. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/tracing/tracer.py +0 -0
  57. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx/util.py +0 -0
  58. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx_python.egg-info/dependency_links.txt +0 -0
  59. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx_python.egg-info/entry_points.txt +0 -0
  60. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx_python.egg-info/not-zip-safe +0 -0
  61. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx_python.egg-info/requires.txt +0 -0
  62. {agentx_python-0.6.11 → agentx_python-0.6.12}/agentx_python.egg-info/top_level.txt +0 -0
  63. {agentx_python-0.6.11 → agentx_python-0.6.12}/setup.cfg +0 -0
  64. {agentx_python-0.6.11 → agentx_python-0.6.12}/setup.py +0 -0
  65. {agentx_python-0.6.11 → agentx_python-0.6.12}/tests/test_integration.py +0 -0
  66. {agentx_python-0.6.11 → agentx_python-0.6.12}/tests/test_integrations.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentx-python
3
- Version: 0.6.11
3
+ Version: 0.6.12
4
4
  Summary: Official Python SDK for AgentX (https://www.agentx.so/)
5
5
  Home-page: https://github.com/AgentX-ai/AgentX-python
6
6
  Author: Robin Wang and AgentX Team
@@ -298,6 +298,19 @@ Per-agent coverage/threshold settings (sample rate, retention, and threshold ove
298
298
  client.monitor.profile.update("agent_123", threshold_overrides={"latencyMs": 15000})
299
299
  ```
300
300
 
301
+ Self-host also has **online evaluators**: a real LLM judge scoring a sample of live traffic continuously, distinct from a pattern's rule-matching. A score below `alert_threshold` raises a signal the same way a failing pattern does, deduped and triage-ready in `client.monitor.signals`.
302
+
303
+ ```python
304
+ evaluator = client.monitor.online_evaluators.builder(
305
+ name="Helpfulness",
306
+ evaluation_settings_id=settings.id,
307
+ sample_rate=0.1,
308
+ alert_threshold=5,
309
+ ).publish()
310
+
311
+ client.monitor.online_evaluators.ratings(evaluator.id, window="7d")
312
+ ```
313
+
301
314
  See **[TRACING.md](TRACING.md)** for the complete Monitor guide.
302
315
 
303
316
  ---
@@ -330,7 +343,7 @@ Ask a case's question several extra ways each run, LLM-paraphrased server-side,
330
343
  Since AgentX doesn't own your agent's code, `client.evaluations.prompts` lets AgentX become your prompt's *source of truth* instead — the same problem LangSmith's Prompt Hub and Langfuse's Prompt Management solve. Pull a version at runtime, tag your eval runs (or live traces) with it, and let a judge propose a rewrite from your real worst-rated results — a human always has to approve before it publishes:
331
344
 
332
345
  ```python
333
- prompt = client.evaluations.prompts.get("support-agent-system-prompt")
346
+ prompt = client.evaluations.prompts.get("support-agent-system-prompt") # or prompt.id
334
347
  # use prompt.text as your own agent's system prompt
335
348
 
336
349
  client.evaluations.run(
@@ -236,6 +236,19 @@ Per-agent coverage/threshold settings (sample rate, retention, and threshold ove
236
236
  client.monitor.profile.update("agent_123", threshold_overrides={"latencyMs": 15000})
237
237
  ```
238
238
 
239
+ Self-host also has **online evaluators**: a real LLM judge scoring a sample of live traffic continuously, distinct from a pattern's rule-matching. A score below `alert_threshold` raises a signal the same way a failing pattern does, deduped and triage-ready in `client.monitor.signals`.
240
+
241
+ ```python
242
+ evaluator = client.monitor.online_evaluators.builder(
243
+ name="Helpfulness",
244
+ evaluation_settings_id=settings.id,
245
+ sample_rate=0.1,
246
+ alert_threshold=5,
247
+ ).publish()
248
+
249
+ client.monitor.online_evaluators.ratings(evaluator.id, window="7d")
250
+ ```
251
+
239
252
  See **[TRACING.md](TRACING.md)** for the complete Monitor guide.
240
253
 
241
254
  ---
@@ -268,7 +281,7 @@ Ask a case's question several extra ways each run, LLM-paraphrased server-side,
268
281
  Since AgentX doesn't own your agent's code, `client.evaluations.prompts` lets AgentX become your prompt's *source of truth* instead — the same problem LangSmith's Prompt Hub and Langfuse's Prompt Management solve. Pull a version at runtime, tag your eval runs (or live traces) with it, and let a judge propose a rewrite from your real worst-rated results — a human always has to approve before it publishes:
269
282
 
270
283
  ```python
271
- prompt = client.evaluations.prompts.get("support-agent-system-prompt")
284
+ prompt = client.evaluations.prompts.get("support-agent-system-prompt") # or prompt.id
272
285
  # use prompt.text as your own agent's system prompt
273
286
 
274
287
  client.evaluations.run(
@@ -213,6 +213,8 @@ class EvaluationsClient:
213
213
  return [Prompt(**p) for p in (data if isinstance(data, list) else data.get("prompts", []))]
214
214
 
215
215
  def get_prompt(self, name: str, version: Optional[int] = None) -> Prompt:
216
+ # `name` doubles as an id: the backend route tries a name match first, then falls back to
217
+ # an id match (see engine's getPromptRowByNameOrId), so callers can pass either.
216
218
  params = self._workspace_params() or {}
217
219
  if version is not None:
218
220
  params = {**params, "version": version}
@@ -132,7 +132,7 @@ class EvaluationSettings(BaseModel):
132
132
  # Prompt registry — the external-agent analog to AgentX's native autotune. AgentX doesn't own
133
133
  # your agent's code, so instead of branching/applying a config it becomes the prompt's source of
134
134
  # truth (same shape as LangSmith's Prompt Hub / Langfuse's Prompt Management): pull a version at
135
- # runtime with ``client.evaluations.prompts.get(name)``, use ``prompt.text`` as your agent's
135
+ # runtime with ``client.evaluations.prompts.get(name_or_id)``, use ``prompt.text`` as your agent's
136
136
  # system prompt, and tag your eval runs so the existing version-comparison view can tell you
137
137
  # which published version scored higher — see ``client.evaluations.prompts`` docs.
138
138
  # ---------------------------------------------------------------------------
@@ -34,6 +34,9 @@ class PromptClient:
34
34
  }
35
35
  ),
36
36
  )
37
+
38
+ ``get()`` also accepts a prompt's ``id`` in place of its name, e.g.
39
+ ``client.evaluations.prompts.get(prompt.id)``.
37
40
  """
38
41
 
39
42
  def __init__(self, client: "EvaluationsClient"):
@@ -43,6 +46,9 @@ class PromptClient:
43
46
  return self._client.create_prompt({"name": name, "text": text, "description": description})
44
47
 
45
48
  def get(self, name: str, version: Optional[int] = None) -> Prompt:
49
+ """Accepts either the prompt's name or its ``id`` (e.g. ``prompt.id`` from an earlier
50
+ ``get``/``create`` call), useful for round-tripping an id you already have without a
51
+ second lookup method."""
46
52
  return self._client.get_prompt(name, version=version)
47
53
 
48
54
  def list(self) -> List[Prompt]:
@@ -7,7 +7,14 @@ from typing import Any, List, Optional
7
7
 
8
8
  import requests
9
9
 
10
- from agentx.monitor.models import MonitorPattern, MonitorProfile, MonitorSignal
10
+ from agentx.monitor.models import (
11
+ MonitorPattern,
12
+ MonitorProfile,
13
+ MonitorSignal,
14
+ MonitorOnlineEvaluator,
15
+ OnlineEvaluatorRatingPoint,
16
+ OnlineEvaluatorEvent,
17
+ )
11
18
 
12
19
  logger = logging.getLogger(__name__)
13
20
 
@@ -71,10 +78,12 @@ class MonitorClient:
71
78
  from agentx.monitor.patterns import MonitorPatternClient
72
79
  from agentx.monitor.signals import MonitorSignalClient
73
80
  from agentx.monitor.profile import MonitorProfileClient
81
+ from agentx.monitor.online_evaluators import MonitorOnlineEvaluatorClient
74
82
 
75
83
  self.patterns = MonitorPatternClient(self)
76
84
  self.signals = MonitorSignalClient(self)
77
85
  self.profile = MonitorProfileClient(self)
86
+ self.online_evaluators = MonitorOnlineEvaluatorClient(self)
78
87
 
79
88
  # ------------------------------------------------------------------
80
89
  # Low-level HTTP
@@ -137,6 +146,45 @@ class MonitorClient:
137
146
  )
138
147
  return MonitorPattern(**data["pattern"])
139
148
 
149
+ # ------------------------------------------------------------------
150
+ # Online evaluator endpoints
151
+ # ------------------------------------------------------------------
152
+
153
+ def create_online_evaluator(self, payload: dict) -> MonitorOnlineEvaluator:
154
+ data = self._request("POST", "/online-evaluators", json=self._with_workspace(payload))
155
+ return MonitorOnlineEvaluator(**data["evaluator"])
156
+
157
+ def list_online_evaluators(self) -> List[MonitorOnlineEvaluator]:
158
+ data = self._request("GET", "/online-evaluators", params=self._workspace_params())
159
+ return [MonitorOnlineEvaluator(**e) for e in data.get("evaluators", [])]
160
+
161
+ def get_online_evaluator(self, evaluator_id: str) -> MonitorOnlineEvaluator:
162
+ data = self._request(
163
+ "GET", f"/online-evaluators/{evaluator_id}", params=self._workspace_params()
164
+ )
165
+ return MonitorOnlineEvaluator(**data["evaluator"])
166
+
167
+ def update_online_evaluator(self, evaluator_id: str, payload: dict) -> MonitorOnlineEvaluator:
168
+ data = self._request(
169
+ "PUT", f"/online-evaluators/{evaluator_id}", json=self._with_workspace(payload)
170
+ )
171
+ return MonitorOnlineEvaluator(**data["evaluator"])
172
+
173
+ def delete_online_evaluator(self, evaluator_id: str) -> None:
174
+ self._request(
175
+ "DELETE", f"/online-evaluators/{evaluator_id}", params=self._workspace_params()
176
+ )
177
+
178
+ def get_online_evaluator_ratings(self, evaluator_id: str, window: str) -> List[OnlineEvaluatorRatingPoint]:
179
+ params = {**(self._workspace_params() or {}), "window": window}
180
+ data = self._request("GET", f"/online-evaluators/{evaluator_id}/ratings", params=params)
181
+ return [OnlineEvaluatorRatingPoint(**p) for p in data.get("points", [])]
182
+
183
+ def get_online_evaluator_events(self, evaluator_id: str, window: str) -> List[OnlineEvaluatorEvent]:
184
+ params = {**(self._workspace_params() or {}), "window": window}
185
+ data = self._request("GET", f"/online-evaluators/{evaluator_id}/events", params=params)
186
+ return [OnlineEvaluatorEvent(**e) for e in data.get("events", [])]
187
+
140
188
  # ------------------------------------------------------------------
141
189
  # Signal endpoints
142
190
  # ------------------------------------------------------------------
@@ -37,6 +37,65 @@ class MonitorPattern(BaseModel):
37
37
  extra = "ignore"
38
38
 
39
39
 
40
+ class MonitorOnlineEvaluator(BaseModel):
41
+ """Continuous LLM-judge scoring of a sample of live production traffic, distinct from a
42
+ MonitorPattern (which matches rules, not judgment). Built via
43
+ ``client.monitor.online_evaluators.builder(...).publish()``. References an
44
+ ``evaluation_settings_id`` (an Evaluator config: criteria, judge prompt, judge model) rather
45
+ than storing its own copy, the same config datasets/Evaluate runs use.
46
+
47
+ A score below ``alert_threshold`` raises/updates a Signal (``client.monitor.signals``), the
48
+ same triage surface a failing MonitorPattern already lands on, tagged with ``severity``. Set
49
+ ``alert_threshold=None`` to score without ever raising a Signal.
50
+ """
51
+
52
+ id: str = Field(alias="_id")
53
+ name: str
54
+ evaluation_settings_id: str = Field(alias="evaluationSettingsId")
55
+ sample_rate: float = Field(default=0.1, alias="sampleRate")
56
+ scope_mode: str = Field(default="all", alias="scopeMode")
57
+ agent_ids: List[str] = Field(default_factory=list, alias="agentIds")
58
+ enabled: bool = True
59
+ alert_threshold: Optional[float] = Field(default=5, alias="alertThreshold")
60
+ severity: str = "medium"
61
+ created_at: Optional[str] = Field(default=None, alias="createdAt")
62
+
63
+ class Config:
64
+ populate_by_name = True
65
+ extra = "ignore"
66
+
67
+
68
+ class OnlineEvaluatorRatingPoint(BaseModel):
69
+ """One bucket of a ratings-over-time series, see
70
+ ``client.monitor.online_evaluators.ratings(evaluator_id)``."""
71
+
72
+ label: str
73
+ ts: int
74
+ average_rating: Optional[float] = Field(default=None, alias="averageRating")
75
+ count: int = 0
76
+
77
+ class Config:
78
+ populate_by_name = True
79
+ extra = "ignore"
80
+
81
+
82
+ class OnlineEvaluatorEvent(BaseModel):
83
+ """One individually scored trace behind a point on the ratings series, worst-rated first,
84
+ see ``client.monitor.online_evaluators.events(evaluator_id)``."""
85
+
86
+ id: str
87
+ trace_id: str = Field(alias="traceId")
88
+ rating: float
89
+ justification: Optional[str] = None
90
+ created_at: str = Field(alias="createdAt")
91
+ input: str
92
+ output: str
93
+
94
+ class Config:
95
+ populate_by_name = True
96
+ extra = "ignore"
97
+
98
+
40
99
  class SignalOccurrence(BaseModel):
41
100
  """One hit behind a signal, capped at the server's most recent N per signal."""
42
101
 
@@ -0,0 +1,120 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from typing import Any, Dict, List, Optional, TYPE_CHECKING
5
+
6
+ from agentx.monitor.models import MonitorOnlineEvaluator, OnlineEvaluatorRatingPoint, OnlineEvaluatorEvent
7
+
8
+ if TYPE_CHECKING:
9
+ from agentx.monitor.client import MonitorClient
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class MonitorOnlineEvaluatorBuilder:
15
+ """Fluent builder for creating an online evaluator: continuous LLM-judge scoring of a
16
+ sample of live production traffic, distinct from a MonitorPattern's rule matching.
17
+ ``evaluation_settings_id`` must reference an existing Evaluator config (criteria, judge
18
+ prompt, judge model), the same config datasets/Evaluate runs use, see
19
+ ``client.evaluations.settings.builder(...)``.
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ client: "MonitorClient",
25
+ name: str,
26
+ evaluation_settings_id: str,
27
+ sample_rate: float = 0.1,
28
+ scope_mode: str = "all",
29
+ agent_ids: Optional[List[str]] = None,
30
+ enabled: bool = True,
31
+ alert_threshold: Optional[float] = 5,
32
+ severity: str = "medium",
33
+ ):
34
+ self._client = client
35
+ self._payload: Dict[str, Any] = {
36
+ "name": name,
37
+ "evaluationSettingsId": evaluation_settings_id,
38
+ # Every check here is a real LLM call against your own API key: keep this low
39
+ # unless you want to score every trace.
40
+ "sampleRate": sample_rate,
41
+ "scopeMode": scope_mode,
42
+ "agentIds": agent_ids or [],
43
+ "enabled": enabled,
44
+ # A score below this raises/updates a Signal, same triage surface a failing
45
+ # MonitorPattern already lands on. None scores without ever raising one.
46
+ "alertThreshold": alert_threshold,
47
+ "severity": severity,
48
+ }
49
+
50
+ def publish(self) -> MonitorOnlineEvaluator:
51
+ logger.info("Publishing online evaluator '%s'", self._payload["name"])
52
+ return self._client.create_online_evaluator(self._payload)
53
+
54
+
55
+ class MonitorOnlineEvaluatorClient:
56
+ """Thin wrapper surfaced as ``client.monitor.online_evaluators``."""
57
+
58
+ def __init__(self, client: "MonitorClient"):
59
+ self._client = client
60
+
61
+ def builder(
62
+ self,
63
+ name: str,
64
+ evaluation_settings_id: str,
65
+ sample_rate: float = 0.1,
66
+ scope_mode: str = "all",
67
+ agent_ids: Optional[List[str]] = None,
68
+ enabled: bool = True,
69
+ alert_threshold: Optional[float] = 5,
70
+ severity: str = "medium",
71
+ ) -> MonitorOnlineEvaluatorBuilder:
72
+ return MonitorOnlineEvaluatorBuilder(
73
+ self._client,
74
+ name=name,
75
+ evaluation_settings_id=evaluation_settings_id,
76
+ sample_rate=sample_rate,
77
+ scope_mode=scope_mode,
78
+ agent_ids=agent_ids,
79
+ enabled=enabled,
80
+ alert_threshold=alert_threshold,
81
+ severity=severity,
82
+ )
83
+
84
+ def get(self, evaluator_id: str) -> MonitorOnlineEvaluator:
85
+ return self._client.get_online_evaluator(evaluator_id)
86
+
87
+ def list(self) -> List[MonitorOnlineEvaluator]:
88
+ return self._client.list_online_evaluators()
89
+
90
+ def update(self, evaluator_id: str, **fields: Any) -> MonitorOnlineEvaluator:
91
+ """Partial update: pass only the fields you want to change, e.g.
92
+ ``client.monitor.online_evaluators.update(id, enabled=False)`` to pause one, or
93
+ ``sample_rate=0.25`` to change its sampling. Field names match the builder's
94
+ (``evaluation_settings_id``, ``sample_rate``, ``scope_mode``, ``agent_ids``, ``enabled``,
95
+ ``alert_threshold``, ``severity``). Pass ``alert_threshold=None`` to stop this evaluator
96
+ from ever raising a Signal.
97
+ """
98
+ alias_map = {
99
+ "evaluation_settings_id": "evaluationSettingsId",
100
+ "sample_rate": "sampleRate",
101
+ "scope_mode": "scopeMode",
102
+ "agent_ids": "agentIds",
103
+ "alert_threshold": "alertThreshold",
104
+ }
105
+ payload = {alias_map.get(key, key): value for key, value in fields.items()}
106
+ return self._client.update_online_evaluator(evaluator_id, payload)
107
+
108
+ def delete(self, evaluator_id: str) -> None:
109
+ self._client.delete_online_evaluator(evaluator_id)
110
+
111
+ def ratings(self, evaluator_id: str, window: str = "7d") -> List[OnlineEvaluatorRatingPoint]:
112
+ """Bucketed average-rating-over-time for this evaluator. ``window`` is one of
113
+ ``"24h"``, ``"7d"``, ``"30d"``."""
114
+ return self._client.get_online_evaluator_ratings(evaluator_id, window)
115
+
116
+ def events(self, evaluator_id: str, window: str = "7d") -> List[OnlineEvaluatorEvent]:
117
+ """Individually scored traces behind the ratings series, worst-rated first and capped
118
+ (see the dashboard's Online Evaluators tab for the same view), lets a low point on the
119
+ ratings series be traced back to exactly which conversation(s) caused it and why."""
120
+ return self._client.get_online_evaluator_events(evaluator_id, window)
@@ -0,0 +1 @@
1
+ VERSION = "0.6.12"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentx-python
3
- Version: 0.6.11
3
+ Version: 0.6.12
4
4
  Summary: Official Python SDK for AgentX (https://www.agentx.so/)
5
5
  Home-page: https://github.com/AgentX-ai/AgentX-python
6
6
  Author: Robin Wang and AgentX Team
@@ -298,6 +298,19 @@ Per-agent coverage/threshold settings (sample rate, retention, and threshold ove
298
298
  client.monitor.profile.update("agent_123", threshold_overrides={"latencyMs": 15000})
299
299
  ```
300
300
 
301
+ Self-host also has **online evaluators**: a real LLM judge scoring a sample of live traffic continuously, distinct from a pattern's rule-matching. A score below `alert_threshold` raises a signal the same way a failing pattern does, deduped and triage-ready in `client.monitor.signals`.
302
+
303
+ ```python
304
+ evaluator = client.monitor.online_evaluators.builder(
305
+ name="Helpfulness",
306
+ evaluation_settings_id=settings.id,
307
+ sample_rate=0.1,
308
+ alert_threshold=5,
309
+ ).publish()
310
+
311
+ client.monitor.online_evaluators.ratings(evaluator.id, window="7d")
312
+ ```
313
+
301
314
  See **[TRACING.md](TRACING.md)** for the complete Monitor guide.
302
315
 
303
316
  ---
@@ -330,7 +343,7 @@ Ask a case's question several extra ways each run, LLM-paraphrased server-side,
330
343
  Since AgentX doesn't own your agent's code, `client.evaluations.prompts` lets AgentX become your prompt's *source of truth* instead — the same problem LangSmith's Prompt Hub and Langfuse's Prompt Management solve. Pull a version at runtime, tag your eval runs (or live traces) with it, and let a judge propose a rewrite from your real worst-rated results — a human always has to approve before it publishes:
331
344
 
332
345
  ```python
333
- prompt = client.evaluations.prompts.get("support-agent-system-prompt")
346
+ prompt = client.evaluations.prompts.get("support-agent-system-prompt") # or prompt.id
334
347
  # use prompt.text as your own agent's system prompt
335
348
 
336
349
  client.evaluations.run(
@@ -40,6 +40,7 @@ agentx/integrations/openai_agents.py
40
40
  agentx/monitor/__init__.py
41
41
  agentx/monitor/client.py
42
42
  agentx/monitor/models.py
43
+ agentx/monitor/online_evaluators.py
43
44
  agentx/monitor/patterns.py
44
45
  agentx/monitor/profile.py
45
46
  agentx/monitor/signals.py
@@ -1 +0,0 @@
1
- VERSION = "0.6.11"
File without changes
File without changes
File without changes