agentx-python 0.6.16__tar.gz → 0.6.18__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 (68) hide show
  1. {agentx_python-0.6.16 → agentx_python-0.6.18}/PKG-INFO +12 -3
  2. {agentx_python-0.6.16 → agentx_python-0.6.18}/README.md +11 -2
  3. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/agentx.py +6 -0
  4. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/client.py +28 -0
  5. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/runner.py +79 -0
  6. agentx_python-0.6.18/agentx/feedback.py +76 -0
  7. agentx_python-0.6.18/agentx/version.py +1 -0
  8. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx_python.egg-info/PKG-INFO +12 -3
  9. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx_python.egg-info/SOURCES.txt +1 -0
  10. agentx_python-0.6.16/agentx/version.py +0 -1
  11. {agentx_python-0.6.16 → agentx_python-0.6.18}/LICENSE +0 -0
  12. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/__init__.py +0 -0
  13. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/cli.py +0 -0
  14. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/__init__.py +0 -0
  15. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/_term.py +0 -0
  16. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/adapters/__init__.py +0 -0
  17. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/adapters/http_endpoint.py +0 -0
  18. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/adapters/precomputed.py +0 -0
  19. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/adapters/raw.py +0 -0
  20. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/datasets.py +0 -0
  21. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/evaluation_settings.py +0 -0
  22. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/models.py +0 -0
  23. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/prompts.py +0 -0
  24. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/redaction.py +0 -0
  25. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/reporting.py +0 -0
  26. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/results.py +0 -0
  27. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/evaluations/tracing.py +0 -0
  28. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/exceptions.py +0 -0
  29. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/__init__.py +0 -0
  30. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/_traced_call.py +0 -0
  31. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/anthropic.py +0 -0
  32. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/autogen.py +0 -0
  33. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/crewai.py +0 -0
  34. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/google_adk.py +0 -0
  35. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/google_genai.py +0 -0
  36. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/langchain.py +0 -0
  37. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/litellm.py +0 -0
  38. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/llamaindex.py +0 -0
  39. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/openai.py +0 -0
  40. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/integrations/openai_agents.py +0 -0
  41. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/monitor/__init__.py +0 -0
  42. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/monitor/client.py +0 -0
  43. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/monitor/models.py +0 -0
  44. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/monitor/online_evaluators.py +0 -0
  45. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/monitor/patterns.py +0 -0
  46. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/monitor/profile.py +0 -0
  47. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/monitor/signals.py +0 -0
  48. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/outcomes.py +0 -0
  49. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/py.typed +0 -0
  50. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/resources/__init__.py +0 -0
  51. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/resources/agent.py +0 -0
  52. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/resources/conversation.py +0 -0
  53. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/resources/workforce.py +0 -0
  54. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/tracing/__init__.py +0 -0
  55. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/tracing/ci_types.py +0 -0
  56. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/tracing/ingest_client.py +0 -0
  57. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/tracing/tracer.py +0 -0
  58. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx/util.py +0 -0
  59. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx_python.egg-info/dependency_links.txt +0 -0
  60. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx_python.egg-info/entry_points.txt +0 -0
  61. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx_python.egg-info/not-zip-safe +0 -0
  62. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx_python.egg-info/requires.txt +0 -0
  63. {agentx_python-0.6.16 → agentx_python-0.6.18}/agentx_python.egg-info/top_level.txt +0 -0
  64. {agentx_python-0.6.16 → agentx_python-0.6.18}/setup.cfg +0 -0
  65. {agentx_python-0.6.16 → agentx_python-0.6.18}/setup.py +0 -0
  66. {agentx_python-0.6.16 → agentx_python-0.6.18}/tests/test_integration.py +0 -0
  67. {agentx_python-0.6.16 → agentx_python-0.6.18}/tests/test_integrations.py +0 -0
  68. {agentx_python-0.6.16 → agentx_python-0.6.18}/tests/test_span_tree.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentx-python
3
- Version: 0.6.16
3
+ Version: 0.6.18
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
@@ -189,7 +189,9 @@ client.evaluations.run(
189
189
  ).execute(my_agent_fn)
190
190
  ```
191
191
 
192
- See [Prompt registry](EVALUATIONS.md#prompt-registry) in the full guide, or [self-host's docs](https://docs.agentx.so/self-host#prompt-management) for the "Suggest improvement" dashboard flow (self-host only - no hosted-SaaS equivalent yet).
192
+ See [Prompt registry](EVALUATIONS.md#prompt-registry) in the full guide, or [self-host's docs](https://docs.agentx.so/improve/prompt-management) for the "Suggest improvement" dashboard flow (self-host only - no hosted-SaaS equivalent yet).
193
+
194
+ On self-host, a finalized run can also **gate a CI job**: `report.gate(fail_under=7, no_regression=True)` checks the run's average rating against an absolute floor and/or the dataset's previous run, prints per-check verdicts into the CI log, and returns an exit code - `sys.exit(gate.exit_code)` blocks the merge on regression. Recorded gates appear in the dashboard's CI Gates tab. See [self-host's CI docs](https://docs.agentx.so/integrations/self-host-ci) for the GitHub Actions recipe.
193
195
 
194
196
  See **[EVALUATIONS.md](EVALUATIONS.md)** for the full guide - dataset builder, framework adapters, similarity metrics, smoke testing, judge configuration, prompt registry, and the complete API reference.
195
197
 
@@ -311,7 +313,7 @@ evaluator = client.monitor.online_evaluators.builder(
311
313
  client.monitor.online_evaluators.ratings(evaluator.id, window="7d")
312
314
  ```
313
315
 
314
- An online evaluator can also judge **whole conversations** instead of single traces: pass `scope="session"` and the engine scores each multi-turn session once it's been idle for `idle_seconds`, re-scoring if the conversation resumes. And to close the loop with reality, `client.outcomes.report(...)` records what actually happened after the fact (a reopened ticket, a human confirmation) against a trace, feeding the dashboard's Judge Calibration view, which measures how often AgentX's automated verdicts agree with real outcomes. Both are self-host features.
316
+ An online evaluator can also judge **whole conversations** instead of single traces: pass `scope="session"` and the engine scores each multi-turn session once it's been idle for `idle_seconds`, re-scoring if the conversation resumes. And to close the loop with reality, two ground-truth streams feed the dashboard's Judge Calibration view (which measures how often AgentX's automated verdicts agree with what actually happened): `client.outcomes.report(...)` for after-the-fact system results (a reopened ticket, a human confirmation), and `client.feedback.report(...)` for end-user votes forwarded from your own app's UI - a "down" raises a "Negative user feedback" signal directly, no sampling or judge call involved. All self-host features.
315
317
 
316
318
  ```python
317
319
  client.monitor.online_evaluators.builder(
@@ -328,6 +330,13 @@ client.outcomes.report(
328
330
  is_negative=True,
329
331
  reason="Customer reopened the ticket within 3 days",
330
332
  )
333
+
334
+ client.feedback.report(
335
+ trace_id=trace_id,
336
+ rating="down", # "up" or "down"
337
+ comment="It never answered my question", # optional, the user's own words
338
+ end_user_id=current_user.id, # optional, opaque to AgentX
339
+ )
331
340
  ```
332
341
 
333
342
  See **[TRACING.md](TRACING.md)** for the complete Monitor guide.
@@ -127,7 +127,9 @@ client.evaluations.run(
127
127
  ).execute(my_agent_fn)
128
128
  ```
129
129
 
130
- See [Prompt registry](EVALUATIONS.md#prompt-registry) in the full guide, or [self-host's docs](https://docs.agentx.so/self-host#prompt-management) for the "Suggest improvement" dashboard flow (self-host only - no hosted-SaaS equivalent yet).
130
+ See [Prompt registry](EVALUATIONS.md#prompt-registry) in the full guide, or [self-host's docs](https://docs.agentx.so/improve/prompt-management) for the "Suggest improvement" dashboard flow (self-host only - no hosted-SaaS equivalent yet).
131
+
132
+ On self-host, a finalized run can also **gate a CI job**: `report.gate(fail_under=7, no_regression=True)` checks the run's average rating against an absolute floor and/or the dataset's previous run, prints per-check verdicts into the CI log, and returns an exit code - `sys.exit(gate.exit_code)` blocks the merge on regression. Recorded gates appear in the dashboard's CI Gates tab. See [self-host's CI docs](https://docs.agentx.so/integrations/self-host-ci) for the GitHub Actions recipe.
131
133
 
132
134
  See **[EVALUATIONS.md](EVALUATIONS.md)** for the full guide - dataset builder, framework adapters, similarity metrics, smoke testing, judge configuration, prompt registry, and the complete API reference.
133
135
 
@@ -249,7 +251,7 @@ evaluator = client.monitor.online_evaluators.builder(
249
251
  client.monitor.online_evaluators.ratings(evaluator.id, window="7d")
250
252
  ```
251
253
 
252
- An online evaluator can also judge **whole conversations** instead of single traces: pass `scope="session"` and the engine scores each multi-turn session once it's been idle for `idle_seconds`, re-scoring if the conversation resumes. And to close the loop with reality, `client.outcomes.report(...)` records what actually happened after the fact (a reopened ticket, a human confirmation) against a trace, feeding the dashboard's Judge Calibration view, which measures how often AgentX's automated verdicts agree with real outcomes. Both are self-host features.
254
+ An online evaluator can also judge **whole conversations** instead of single traces: pass `scope="session"` and the engine scores each multi-turn session once it's been idle for `idle_seconds`, re-scoring if the conversation resumes. And to close the loop with reality, two ground-truth streams feed the dashboard's Judge Calibration view (which measures how often AgentX's automated verdicts agree with what actually happened): `client.outcomes.report(...)` for after-the-fact system results (a reopened ticket, a human confirmation), and `client.feedback.report(...)` for end-user votes forwarded from your own app's UI - a "down" raises a "Negative user feedback" signal directly, no sampling or judge call involved. All self-host features.
253
255
 
254
256
  ```python
255
257
  client.monitor.online_evaluators.builder(
@@ -266,6 +268,13 @@ client.outcomes.report(
266
268
  is_negative=True,
267
269
  reason="Customer reopened the ticket within 3 days",
268
270
  )
271
+
272
+ client.feedback.report(
273
+ trace_id=trace_id,
274
+ rating="down", # "up" or "down"
275
+ comment="It never answered my question", # optional, the user's own words
276
+ end_user_id=current_user.id, # optional, opaque to AgentX
277
+ )
269
278
  ```
270
279
 
271
280
  See **[TRACING.md](TRACING.md)** for the complete Monitor guide.
@@ -60,6 +60,12 @@ class AgentX:
60
60
  # ground truth behind the dashboard's Judge Calibration card. Self-host only.
61
61
  self.outcomes = OutcomesClient(api_key=self.api_key)
62
62
 
63
+ from agentx.feedback import FeedbackClient
64
+
65
+ # Forward end-user votes ("up"/"down") on traced responses - a "down" raises a signal
66
+ # directly, and every vote feeds Judge Calibration alongside outcomes. Self-host only.
67
+ self.feedback = FeedbackClient(api_key=self.api_key)
68
+
63
69
  _ingest_client = IngestClient(
64
70
  api_key=self.api_key,
65
71
  sdk_version=VERSION,
@@ -265,6 +265,34 @@ class EvaluationsClient:
265
265
  "POST", f"/runs/{run_id}/finalize", json={"status": "completed"}
266
266
  )
267
267
 
268
+ def gate_run(
269
+ self,
270
+ run_id: str,
271
+ *,
272
+ fail_under: Optional[float] = None,
273
+ no_regression: bool = False,
274
+ tolerance: Optional[float] = None,
275
+ record: bool = True,
276
+ caller: Optional[str] = "sdk",
277
+ ) -> Dict[str, Any]:
278
+ # CI gate (self-host): pass/fail a finalized run against an absolute rating floor and/or
279
+ # the dataset's previous completed run. Recorded into gate history by default (the
280
+ # dashboard's CI page lists these); pass record=False for a preview that leaves no trace.
281
+ # `caller` is a free label shown in that history ("sdk", "github-actions", ...). See
282
+ # EvaluationRunContext.gate() for the CI-facing wrapper with printed verdicts.
283
+ params: Dict[str, Any] = {}
284
+ if fail_under is not None:
285
+ params["failUnder"] = fail_under
286
+ if no_regression:
287
+ params["noRegression"] = "true"
288
+ if tolerance is not None:
289
+ params["tolerance"] = tolerance
290
+ if record:
291
+ params["record"] = "true"
292
+ if caller:
293
+ params["caller"] = caller
294
+ return self._request("GET", f"/runs/{run_id}/gate", params=params)
295
+
268
296
  def analyze_run(
269
297
  self,
270
298
  run_id: str,
@@ -55,6 +55,23 @@ _ANALYSIS_LEVEL_LABELS = {
55
55
  _DEFAULT_JUDGE_MODEL = "gpt-5.5"
56
56
 
57
57
 
58
+ class GateResult:
59
+ """Wire result of the CI gate (GET /runs/:id/gate) with attribute access for the fields a
60
+ CI script actually branches on."""
61
+
62
+ def __init__(self, data: Dict[str, Any]):
63
+ self.raw = data
64
+ self.passed: bool = bool(data.get("passed"))
65
+ self.average_rating: Optional[float] = data.get("averageRating")
66
+ self.baseline_average: Optional[float] = data.get("baselineAverage")
67
+ self.baseline_run_id: Optional[str] = data.get("baselineRunId")
68
+ self.checks: List[Dict[str, Any]] = data.get("checks", [])
69
+
70
+ @property
71
+ def exit_code(self) -> int:
72
+ return 0 if self.passed else 1
73
+
74
+
58
75
  class EvaluationRunContext:
59
76
  """
60
77
  Fluent builder returned by client.evaluations.run(...).
@@ -210,6 +227,42 @@ class EvaluationRunContext:
210
227
  logger.error("Finalize failed: %s", exc)
211
228
  return self
212
229
 
230
+ def gate(
231
+ self,
232
+ *,
233
+ fail_under: Optional[float] = None,
234
+ no_regression: bool = False,
235
+ tolerance: Optional[float] = None,
236
+ caller: str = "sdk",
237
+ ) -> "GateResult":
238
+ """CI gate (self-host): pass/fail this finalized run so a CI job can block a merge.
239
+
240
+ ``fail_under`` fails the gate when the run's average rating is below the floor;
241
+ ``no_regression=True`` fails it when the average dropped more than ``tolerance``
242
+ (default 0.5, judge scores are noisy) below the dataset's previous completed run.
243
+ At least one check is required. Prints a CI-log-friendly verdict and returns a
244
+ :class:`GateResult` - the caller decides the exit code::
245
+
246
+ report = client.evaluations.run(...).execute(my_agent).finalize()
247
+ gate = report.gate(fail_under=7, no_regression=True)
248
+ if not gate.passed:
249
+ sys.exit(1)
250
+ """
251
+ data = self._client.gate_run(
252
+ self._run.run_id,
253
+ fail_under=fail_under,
254
+ no_regression=no_regression,
255
+ tolerance=tolerance,
256
+ caller=caller,
257
+ )
258
+ result = GateResult(data)
259
+ print()
260
+ for check in result.checks:
261
+ mark = green("✓") if check.get("passed") else red("✗")
262
+ print(f" {mark} [{check.get('check')}] {check.get('detail')}")
263
+ print(f" {green('✓ GATE PASSED') if result.passed else red('✗ GATE FAILED')}")
264
+ return result
265
+
213
266
  # ------------------------------------------------------------------
214
267
  # Live rating stats - server-computed (Evaluate.liveStatistics), refreshed
215
268
  # from the response of each append_results()/finalize_run() call. Available
@@ -350,6 +403,32 @@ class EvaluationsRunner:
350
403
  script execution)."""
351
404
  return self._client.get_analysis_status(run_id)
352
405
 
406
+ def gate_run(
407
+ self,
408
+ run_id: str,
409
+ *,
410
+ fail_under: Optional[float] = None,
411
+ no_regression: bool = False,
412
+ tolerance: Optional[float] = None,
413
+ record: bool = True,
414
+ caller: Optional[str] = "sdk",
415
+ ) -> GateResult:
416
+ """CI-gate any finalized run by id - the standalone form of
417
+ ``EvaluationRunContext.gate()``, for gating a run created elsewhere or
418
+ re-checking one without re-running it (self-host only). Pass
419
+ ``record=False`` for a check that stays out of the dashboard's CI Gates
420
+ history."""
421
+ return GateResult(
422
+ self._client.gate_run(
423
+ run_id,
424
+ fail_under=fail_under,
425
+ no_regression=no_regression,
426
+ tolerance=tolerance,
427
+ record=record,
428
+ caller=caller,
429
+ )
430
+ )
431
+
353
432
  def run(
354
433
  self,
355
434
  dataset_id: str,
@@ -0,0 +1,76 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from typing import Any, Dict, Optional
5
+
6
+ import requests
7
+
8
+ from agentx.util import api_base, get_headers
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class AgentXFeedbackError(Exception):
14
+ pass
15
+
16
+
17
+ class FeedbackClient:
18
+ """Surfaced as ``client.feedback``: forward an END USER's reaction to a traced response
19
+ (self-host only, ``POST /feedback``) - the vote button in your own app's UI, relayed to
20
+ AgentX. The cheapest ground truth there is: a "down" raises a "Negative user feedback"
21
+ signal directly (the user is the detector, no sampling or judge call), and every report
22
+ also feeds Judge Calibration, so AgentX's automated verdicts get measured against real
23
+ human reactions.
24
+
25
+ Distinct from ``client.outcomes``: an outcome is an after-the-fact SYSTEM result ("ticket
26
+ reopened", reported by a workflow); feedback is a human vote with up/down semantics.
27
+ """
28
+
29
+ def __init__(self, api_key: Optional[str] = None):
30
+ self._api_key = api_key
31
+
32
+ def report(
33
+ self,
34
+ trace_id: str,
35
+ rating: str,
36
+ *,
37
+ comment: Optional[str] = None,
38
+ end_user_id: Optional[str] = None,
39
+ ) -> Dict[str, Any]:
40
+ """Report one end-user vote on a trace.
41
+
42
+ ``rating`` is ``"up"`` or ``"down"``. ``comment`` is the user's own words, if your UI
43
+ collects them (a "down" comment becomes the signal's summary and improvement evidence).
44
+ ``end_user_id`` is your app's identifier for the voter, kept opaque by AgentX.
45
+
46
+ Example, from your app's vote handler::
47
+
48
+ client.feedback.report(
49
+ trace_id=trace_id,
50
+ rating="down",
51
+ comment="It never answered my question",
52
+ end_user_id=current_user.id,
53
+ )
54
+ """
55
+ if rating not in ("up", "down"):
56
+ raise AgentXFeedbackError('rating must be "up" or "down"')
57
+ payload: Dict[str, Any] = {"traceId": trace_id, "rating": rating}
58
+ if comment:
59
+ payload["comment"] = comment
60
+ if end_user_id:
61
+ payload["endUserId"] = end_user_id
62
+
63
+ resp = requests.post(
64
+ f"{api_base()}/feedback",
65
+ headers={**get_headers(self._api_key), "Content-Type": "application/json"},
66
+ json=payload,
67
+ timeout=10,
68
+ )
69
+ if resp.status_code >= 400:
70
+ try:
71
+ detail = resp.json().get("error", resp.reason)
72
+ except ValueError:
73
+ detail = resp.reason
74
+ raise AgentXFeedbackError(f"Failed to report feedback ({resp.status_code}): {detail}")
75
+ logger.info("Reported %s feedback on trace %s", rating, trace_id)
76
+ return resp.json().get("feedback", {})
@@ -0,0 +1 @@
1
+ VERSION = "0.6.18"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentx-python
3
- Version: 0.6.16
3
+ Version: 0.6.18
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
@@ -189,7 +189,9 @@ client.evaluations.run(
189
189
  ).execute(my_agent_fn)
190
190
  ```
191
191
 
192
- See [Prompt registry](EVALUATIONS.md#prompt-registry) in the full guide, or [self-host's docs](https://docs.agentx.so/self-host#prompt-management) for the "Suggest improvement" dashboard flow (self-host only - no hosted-SaaS equivalent yet).
192
+ See [Prompt registry](EVALUATIONS.md#prompt-registry) in the full guide, or [self-host's docs](https://docs.agentx.so/improve/prompt-management) for the "Suggest improvement" dashboard flow (self-host only - no hosted-SaaS equivalent yet).
193
+
194
+ On self-host, a finalized run can also **gate a CI job**: `report.gate(fail_under=7, no_regression=True)` checks the run's average rating against an absolute floor and/or the dataset's previous run, prints per-check verdicts into the CI log, and returns an exit code - `sys.exit(gate.exit_code)` blocks the merge on regression. Recorded gates appear in the dashboard's CI Gates tab. See [self-host's CI docs](https://docs.agentx.so/integrations/self-host-ci) for the GitHub Actions recipe.
193
195
 
194
196
  See **[EVALUATIONS.md](EVALUATIONS.md)** for the full guide - dataset builder, framework adapters, similarity metrics, smoke testing, judge configuration, prompt registry, and the complete API reference.
195
197
 
@@ -311,7 +313,7 @@ evaluator = client.monitor.online_evaluators.builder(
311
313
  client.monitor.online_evaluators.ratings(evaluator.id, window="7d")
312
314
  ```
313
315
 
314
- An online evaluator can also judge **whole conversations** instead of single traces: pass `scope="session"` and the engine scores each multi-turn session once it's been idle for `idle_seconds`, re-scoring if the conversation resumes. And to close the loop with reality, `client.outcomes.report(...)` records what actually happened after the fact (a reopened ticket, a human confirmation) against a trace, feeding the dashboard's Judge Calibration view, which measures how often AgentX's automated verdicts agree with real outcomes. Both are self-host features.
316
+ An online evaluator can also judge **whole conversations** instead of single traces: pass `scope="session"` and the engine scores each multi-turn session once it's been idle for `idle_seconds`, re-scoring if the conversation resumes. And to close the loop with reality, two ground-truth streams feed the dashboard's Judge Calibration view (which measures how often AgentX's automated verdicts agree with what actually happened): `client.outcomes.report(...)` for after-the-fact system results (a reopened ticket, a human confirmation), and `client.feedback.report(...)` for end-user votes forwarded from your own app's UI - a "down" raises a "Negative user feedback" signal directly, no sampling or judge call involved. All self-host features.
315
317
 
316
318
  ```python
317
319
  client.monitor.online_evaluators.builder(
@@ -328,6 +330,13 @@ client.outcomes.report(
328
330
  is_negative=True,
329
331
  reason="Customer reopened the ticket within 3 days",
330
332
  )
333
+
334
+ client.feedback.report(
335
+ trace_id=trace_id,
336
+ rating="down", # "up" or "down"
337
+ comment="It never answered my question", # optional, the user's own words
338
+ end_user_id=current_user.id, # optional, opaque to AgentX
339
+ )
331
340
  ```
332
341
 
333
342
  See **[TRACING.md](TRACING.md)** for the complete Monitor guide.
@@ -5,6 +5,7 @@ agentx/__init__.py
5
5
  agentx/agentx.py
6
6
  agentx/cli.py
7
7
  agentx/exceptions.py
8
+ agentx/feedback.py
8
9
  agentx/outcomes.py
9
10
  agentx/py.typed
10
11
  agentx/util.py
@@ -1 +0,0 @@
1
- VERSION = "0.6.16"
File without changes
File without changes
File without changes