cortexops 0.3.0__tar.gz → 0.5.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 (72) hide show
  1. {cortexops-0.3.0 → cortexops-0.5.0}/.gitignore +1 -0
  2. cortexops-0.5.0/PKG-INFO +306 -0
  3. cortexops-0.5.0/README.md +243 -0
  4. {cortexops-0.3.0 → cortexops-0.5.0}/cortexops/__init__.py +1 -1
  5. {cortexops-0.3.0 → cortexops-0.5.0}/cortexops/cli.py +82 -0
  6. cortexops-0.5.0/cortexops/client.py +150 -0
  7. cortexops-0.5.0/cortexops/dataset.py +242 -0
  8. cortexops-0.5.0/cortexops/judge.py +393 -0
  9. {cortexops-0.3.0 → cortexops-0.5.0}/cortexops/pyproject.toml +13 -9
  10. {cortexops-0.3.0 → cortexops-0.5.0}/cortexops/tracer.py +35 -10
  11. {cortexops-0.3.0 → cortexops-0.5.0}/pyproject.toml +3 -2
  12. cortexops-0.5.0/tests/__init__.py +1 -0
  13. cortexops-0.5.0/tests/conftest.py +38 -0
  14. cortexops-0.5.0/tests/helpers.py +51 -0
  15. cortexops-0.5.0/tests/test_agno.py +7 -0
  16. cortexops-0.5.0/tests/test_api_client.py +25 -0
  17. cortexops-0.5.0/tests/test_async.py +18 -0
  18. cortexops-0.5.0/tests/test_auth.py +17 -0
  19. cortexops-0.5.0/tests/test_autogen.py +12 -0
  20. cortexops-0.5.0/tests/test_cli.py +15 -0
  21. cortexops-0.5.0/tests/test_concurrency.py +17 -0
  22. cortexops-0.5.0/tests/test_config.py +26 -0
  23. cortexops-0.5.0/tests/test_cost_tracking.py +10 -0
  24. cortexops-0.5.0/tests/test_crewai.py +12 -0
  25. cortexops-0.5.0/tests/test_datadog.py +8 -0
  26. cortexops-0.5.0/tests/test_edge_cases.py +21 -0
  27. cortexops-0.5.0/tests/test_end_to_end.py +46 -0
  28. cortexops-0.5.0/tests/test_eval_suite.py +20 -0
  29. cortexops-0.5.0/tests/test_evaluation.py +38 -0
  30. cortexops-0.5.0/tests/test_exceptions.py +8 -0
  31. cortexops-0.5.0/tests/test_exporters.py +11 -0
  32. cortexops-0.5.0/tests/test_framework_detection.py +41 -0
  33. cortexops-0.5.0/tests/test_golden_dataset.py +15 -0
  34. cortexops-0.5.0/tests/test_google_adk.py +12 -0
  35. cortexops-0.5.0/tests/test_grafana.py +8 -0
  36. cortexops-0.5.0/tests/test_haystack.py +12 -0
  37. cortexops-0.5.0/tests/test_honeycomb.py +13 -0
  38. cortexops-0.5.0/tests/test_jaeger.py +9 -0
  39. cortexops-0.5.0/tests/test_langgraph.py +13 -0
  40. cortexops-0.5.0/tests/test_llamaindex.py +12 -0
  41. cortexops-0.5.0/tests/test_llm_calls.py +19 -0
  42. cortexops-0.5.0/tests/test_llm_judge.py +20 -0
  43. cortexops-0.5.0/tests/test_logging.py +12 -0
  44. cortexops-0.5.0/tests/test_metrics.py +35 -0
  45. cortexops-0.5.0/tests/test_nodes.py +25 -0
  46. cortexops-0.5.0/tests/test_openai_agents.py +7 -0
  47. cortexops-0.5.0/tests/test_otlp.py +7 -0
  48. cortexops-0.5.0/tests/test_pydantic_ai.py +14 -0
  49. cortexops-0.5.0/tests/test_redaction.py +9 -0
  50. cortexops-0.5.0/tests/test_regressions.py +19 -0
  51. cortexops-0.5.0/tests/test_retry.py +21 -0
  52. cortexops-0.5.0/tests/test_sampling.py +9 -0
  53. cortexops-0.5.0/tests/test_serialization.py +12 -0
  54. cortexops-0.5.0/tests/test_smolagents.py +12 -0
  55. cortexops-0.5.0/tests/test_spans.py +19 -0
  56. cortexops-0.5.0/tests/test_tools.py +23 -0
  57. cortexops-0.5.0/tests/test_tracing.py +54 -0
  58. cortexops-0.3.0/PKG-INFO +0 -168
  59. cortexops-0.3.0/cortexops/README.md +0 -106
  60. cortexops-0.3.0/cortexops/client.py +0 -83
  61. cortexops-0.3.0/cortexops/judge.py +0 -154
  62. cortexops-0.3.0/tests/__init__.py +0 -0
  63. cortexops-0.3.0/tests/conftest.py +0 -8
  64. cortexops-0.3.0/tests/test_cortexops.py +0 -211
  65. cortexops-0.3.0/tests/test_enhancements.py +0 -398
  66. {cortexops-0.3.0 → cortexops-0.5.0}/LICENSE +0 -0
  67. {cortexops-0.3.0 → cortexops-0.5.0}/cortexops/LICENSE +0 -0
  68. {cortexops-0.3.0 → cortexops-0.5.0/cortexops}/README.md +0 -0
  69. {cortexops-0.3.0 → cortexops-0.5.0}/cortexops/auth.py +0 -0
  70. {cortexops-0.3.0 → cortexops-0.5.0}/cortexops/eval.py +0 -0
  71. {cortexops-0.3.0 → cortexops-0.5.0}/cortexops/metrics.py +0 -0
  72. {cortexops-0.3.0 → cortexops-0.5.0}/cortexops/models.py +0 -0
@@ -2,6 +2,7 @@
2
2
  __pycache__/
3
3
  *.py[cod]
4
4
  *.pyo
5
+ .venv-e2e/
5
6
  .venv/
6
7
  venv/
7
8
  .env
@@ -0,0 +1,306 @@
1
+ Metadata-Version: 2.4
2
+ Name: cortexops
3
+ Version: 0.5.0
4
+ Summary: AI agent observability & eval platform — trace, monitor, and eval-gate LangGraph, CrewAI, OpenAI Agents, PydanticAI, Agno, AutoGen, Haystack, DSPy, LlamaIndex, Smolagents, and Google ADK
5
+ Project-URL: Homepage, https://getcortexops.com
6
+ Project-URL: Repository, https://github.com/ashishodu2023/cortexops
7
+ Project-URL: Documentation, https://docs.getcortexops.com
8
+ Project-URL: Bug Tracker, https://github.com/ashishodu2023/cortexops/issues
9
+ Project-URL: Changelog, https://github.com/ashishodu2023/cortexops/releases
10
+ Author-email: Ashish <ashish@getcortexops.com>
11
+ License: MIT License
12
+
13
+ Copyright (c) 2025 CortexOps Contributors
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+ License-File: LICENSE
33
+ Keywords: agents,ai,autogen,crewai,evaluation,langgraph,llm,observability,testing
34
+ Classifier: Development Status :: 4 - Beta
35
+ Classifier: Intended Audience :: Developers
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: OS Independent
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.10
40
+ Classifier: Programming Language :: Python :: 3.11
41
+ Classifier: Programming Language :: Python :: 3.12
42
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
43
+ Classifier: Topic :: Software Development :: Quality Assurance
44
+ Classifier: Topic :: Software Development :: Testing
45
+ Classifier: Typing :: Typed
46
+ Requires-Python: >=3.10
47
+ Requires-Dist: httpx>=0.27
48
+ Requires-Dist: pydantic>=2.0
49
+ Requires-Dist: pyyaml>=6.0
50
+ Provides-Extra: all
51
+ Requires-Dist: httpx>=0.27; extra == 'all'
52
+ Provides-Extra: dev
53
+ Requires-Dist: httpx>=0.27; extra == 'dev'
54
+ Requires-Dist: mypy>=1.10; extra == 'dev'
55
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
56
+ Requires-Dist: pytest>=8.0; extra == 'dev'
57
+ Requires-Dist: ruff>=0.4; extra == 'dev'
58
+ Provides-Extra: http
59
+ Requires-Dist: httpx>=0.27; extra == 'http'
60
+ Provides-Extra: llm
61
+ Requires-Dist: httpx>=0.27; extra == 'llm'
62
+ Description-Content-Type: text/markdown
63
+
64
+ # CortexOps
65
+
66
+ **Reliability infrastructure for AI agents.**
67
+ Evaluate · Observe · Operate — for LangGraph, CrewAI, and AutoGen.
68
+
69
+ [![PyPI version](https://img.shields.io/pypi/v/cortexops.svg)](https://pypi.org/project/cortexops/)
70
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
71
+ [![CI](https://github.com/ashishodu2023/cortexops/actions/workflows/eval.yml/badge.svg)](https://github.com/ashishodu2023/cortexops/actions/workflows/eval.yml)
72
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
73
+
74
+ ---
75
+
76
+ ## What's New in v0.4.0
77
+
78
+ ### LLM-as-judge evaluation
79
+ ```python
80
+ from cortexops.judge import LLMJudge
81
+
82
+ judge = LLMJudge(api_key="sk-...")
83
+ result = judge.evaluate(
84
+ case_id="case-001",
85
+ input="Process refund for order #4821",
86
+ output="Refund of $49.99 approved and processed.",
87
+ rubric="task_completion",
88
+ )
89
+ print(result.score, result.passed, result.reasoning)
90
+ ```
91
+
92
+ ### Golden dataset API
93
+ ```python
94
+ from cortexops.dataset import GoldenDataset
95
+
96
+ ds = GoldenDataset(name="refund-agent-v1")
97
+ ds.add(input="Refund order #4821", expected="refund_approved")
98
+ ds.add(input="Cancel subscription", expected="subscription_cancelled")
99
+ ds.save("datasets/refund_agent.yaml")
100
+
101
+ results = ds.run(agent=your_agent, fail_on="task_completion < 0.90")
102
+ ```
103
+
104
+ ### CI/CD eval gate
105
+ ```bash
106
+ cortexops eval run \
107
+ --dataset datasets/refund_agent.yaml \
108
+ --judge \
109
+ --fail-on "task_completion < 0.90"
110
+ # Exit code 1 if regression detected — drop into GitHub Actions
111
+ ```
112
+
113
+
114
+ ## The problem
115
+
116
+ You deployed an agent. You have no idea if it regressed overnight.
117
+
118
+ No standard eval format. No failure traces. No CI gate before the next prompt change ships.
119
+ CortexOps fixes that.
120
+
121
+ ---
122
+
123
+ ## Quickstart
124
+
125
+ ```bash
126
+ pip install cortexops # v0.4.0
127
+ ```
128
+
129
+ ```python
130
+ from cortexops import CortexTracer, EvalSuite
131
+
132
+ # Wrap your LangGraph app — zero refactor required
133
+ tracer = CortexTracer(project="payments-agent")
134
+ graph = tracer.wrap(your_langgraph_app)
135
+
136
+ # Run evaluations against a golden dataset
137
+ results = EvalSuite.run(
138
+ dataset="golden_v1.yaml",
139
+ agent=graph,
140
+ )
141
+
142
+ print(results.summary())
143
+ # CortexOps eval — payments-agent
144
+ # Cases : 9 (7 passed, 2 failed)
145
+ # Task completion : 91.4%
146
+ # Tool accuracy : 97.0/100
147
+ # Latency p50/p95 : 42ms / 187ms
148
+ # Failed cases:
149
+ # - escalation_router: tool_call_mismatch (score 41)
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Golden dataset format
155
+
156
+ Define test cases in YAML. Run them locally or in CI.
157
+
158
+ ```yaml
159
+ # golden_v1.yaml
160
+ version: 1
161
+ project: payments-agent
162
+
163
+ cases:
164
+ - id: refund_lookup_01
165
+ input: "What is the status of refund REF-8821?"
166
+ expected_tool_calls: [lookup_refund]
167
+ expected_output_contains: ["approved", "REF-8821"]
168
+ max_latency_ms: 3000
169
+
170
+ - id: dispute_escalation_01
171
+ input: "I was charged twice — this is unauthorized"
172
+ expected_tool_calls: [classify_dispute, route_escalation]
173
+ expected_output_contains: ["escalated"]
174
+ max_latency_ms: 5000
175
+ ```
176
+
177
+ ---
178
+
179
+ ## CI eval gate
180
+
181
+ Add to `.github/workflows/eval.yml`:
182
+
183
+ ```yaml
184
+ - name: CortexOps eval gate
185
+ run: |
186
+ python examples/langgraph_payments/run_eval.py \
187
+ --dataset golden_v1.yaml \
188
+ --fail-on "task_completion < 0.90"
189
+ ```
190
+
191
+ If the eval drops below threshold, the job exits non-zero and the PR is blocked.
192
+
193
+ ---
194
+
195
+ ## Repo structure
196
+
197
+ ```
198
+ cortexops/
199
+ ├── sdk/ # pip install cortexops # v0.4.0
200
+ │ ├── cortexops/
201
+ │ │ ├── tracer.py # CortexTracer — wraps LangGraph / CrewAI
202
+ │ │ ├── eval.py # EvalSuite — golden dataset runner
203
+ │ │ ├── metrics.py # task_completion, tool_accuracy, latency, hallucination
204
+ │ │ ├── models.py # Pydantic data models
205
+ │ │ └── client.py # HTTP client for hosted API
206
+ │ └── tests/
207
+ ├── backend/ # FastAPI + Celery + SQLite/Postgres
208
+ │ ├── app/
209
+ │ │ ├── main.py
210
+ │ │ ├── routers/ # /v1/evals, /v1/traces
211
+ │ │ ├── models/ # DB records + API schemas
212
+ │ │ └── worker/ # Celery async eval tasks
213
+ │ └── Dockerfile
214
+ ├── frontend/ # React + TypeScript dashboard
215
+ ├── examples/
216
+ │ └── langgraph_payments/ # Full runnable demo
217
+ │ ├── agent.py
218
+ │ ├── golden_v1.yaml
219
+ │ └── run_eval.py
220
+ └── docker-compose.yml
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Run the full stack locally
226
+
227
+ ```bash
228
+ git clone https://github.com/ashishodu2023/cortexops
229
+ cd cortexops
230
+
231
+ # Start API + worker + Redis
232
+ docker compose up --build
233
+
234
+ # In another terminal — run the demo eval
235
+ cd examples/langgraph_payments
236
+ pip install -e ../../sdk/
237
+ python run_eval.py
238
+
239
+ # API docs at http://localhost:8000/docs
240
+ # Dashboard at http://localhost:3000
241
+ ```
242
+
243
+ ---
244
+
245
+ ## Supported frameworks
246
+
247
+ | Framework | Status |
248
+ |---|---|
249
+ | LangGraph | Stable |
250
+ | CrewAI | Stable |
251
+ | AutoGen | Beta |
252
+ | LlamaIndex agents | Coming soon |
253
+ | Custom callables | Supported via `CortexTracer.wrap()` |
254
+
255
+ ---
256
+
257
+ ## Built-in metrics
258
+
259
+ | Metric | What it checks |
260
+ |---|---|
261
+ | `task_completion` | Agent produced a valid, non-error output |
262
+ | `tool_accuracy` | Expected tool calls were actually made |
263
+ | `latency` | Response within `max_latency_ms` budget |
264
+ | `hallucination` | Detects fabrication signals in output |
265
+
266
+ Add custom metrics by subclassing `cortexops.Metric`.
267
+
268
+ ---
269
+
270
+ ## Contributing
271
+
272
+ ```bash
273
+ git clone https://github.com/ashishodu2023/cortexops
274
+ cd cortexops/sdk
275
+ pip install -e ".[dev]"
276
+ pytest tests/ -v
277
+ ```
278
+
279
+ See [CONTRIBUTING.md](CONTRIBUTING.md). Issues labeled `good first issue` are a great place to start.
280
+
281
+ ---
282
+
283
+ ## Citation
284
+
285
+ ```bibtex
286
+ @software{cortexops2025,
287
+ author = {Ashish, et al.},
288
+ title = {CortexOps: Reliability Infrastructure for AI Agents},
289
+ year = {2025},
290
+ url = {https://github.com/ashishodu2023/cortexops},
291
+ }
292
+ ```
293
+
294
+ ---
295
+
296
+ ## License
297
+
298
+ MIT — see [LICENSE](LICENSE).
299
+
300
+ ---
301
+
302
+ <p align="center">
303
+ <a href="https://cortexops.ai">cortexops.ai</a> ·
304
+ <a href="https://github.com/ashishodu2023/cortexops/issues">Issues</a> ·
305
+ <a href="https://github.com/ashishodu2023/cortexops/discussions">Discussions</a>
306
+ </p>
@@ -0,0 +1,243 @@
1
+ # CortexOps
2
+
3
+ **Reliability infrastructure for AI agents.**
4
+ Evaluate · Observe · Operate — for LangGraph, CrewAI, and AutoGen.
5
+
6
+ [![PyPI version](https://img.shields.io/pypi/v/cortexops.svg)](https://pypi.org/project/cortexops/)
7
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
8
+ [![CI](https://github.com/ashishodu2023/cortexops/actions/workflows/eval.yml/badge.svg)](https://github.com/ashishodu2023/cortexops/actions/workflows/eval.yml)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
10
+
11
+ ---
12
+
13
+ ## What's New in v0.4.0
14
+
15
+ ### LLM-as-judge evaluation
16
+ ```python
17
+ from cortexops.judge import LLMJudge
18
+
19
+ judge = LLMJudge(api_key="sk-...")
20
+ result = judge.evaluate(
21
+ case_id="case-001",
22
+ input="Process refund for order #4821",
23
+ output="Refund of $49.99 approved and processed.",
24
+ rubric="task_completion",
25
+ )
26
+ print(result.score, result.passed, result.reasoning)
27
+ ```
28
+
29
+ ### Golden dataset API
30
+ ```python
31
+ from cortexops.dataset import GoldenDataset
32
+
33
+ ds = GoldenDataset(name="refund-agent-v1")
34
+ ds.add(input="Refund order #4821", expected="refund_approved")
35
+ ds.add(input="Cancel subscription", expected="subscription_cancelled")
36
+ ds.save("datasets/refund_agent.yaml")
37
+
38
+ results = ds.run(agent=your_agent, fail_on="task_completion < 0.90")
39
+ ```
40
+
41
+ ### CI/CD eval gate
42
+ ```bash
43
+ cortexops eval run \
44
+ --dataset datasets/refund_agent.yaml \
45
+ --judge \
46
+ --fail-on "task_completion < 0.90"
47
+ # Exit code 1 if regression detected — drop into GitHub Actions
48
+ ```
49
+
50
+
51
+ ## The problem
52
+
53
+ You deployed an agent. You have no idea if it regressed overnight.
54
+
55
+ No standard eval format. No failure traces. No CI gate before the next prompt change ships.
56
+ CortexOps fixes that.
57
+
58
+ ---
59
+
60
+ ## Quickstart
61
+
62
+ ```bash
63
+ pip install cortexops # v0.4.0
64
+ ```
65
+
66
+ ```python
67
+ from cortexops import CortexTracer, EvalSuite
68
+
69
+ # Wrap your LangGraph app — zero refactor required
70
+ tracer = CortexTracer(project="payments-agent")
71
+ graph = tracer.wrap(your_langgraph_app)
72
+
73
+ # Run evaluations against a golden dataset
74
+ results = EvalSuite.run(
75
+ dataset="golden_v1.yaml",
76
+ agent=graph,
77
+ )
78
+
79
+ print(results.summary())
80
+ # CortexOps eval — payments-agent
81
+ # Cases : 9 (7 passed, 2 failed)
82
+ # Task completion : 91.4%
83
+ # Tool accuracy : 97.0/100
84
+ # Latency p50/p95 : 42ms / 187ms
85
+ # Failed cases:
86
+ # - escalation_router: tool_call_mismatch (score 41)
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Golden dataset format
92
+
93
+ Define test cases in YAML. Run them locally or in CI.
94
+
95
+ ```yaml
96
+ # golden_v1.yaml
97
+ version: 1
98
+ project: payments-agent
99
+
100
+ cases:
101
+ - id: refund_lookup_01
102
+ input: "What is the status of refund REF-8821?"
103
+ expected_tool_calls: [lookup_refund]
104
+ expected_output_contains: ["approved", "REF-8821"]
105
+ max_latency_ms: 3000
106
+
107
+ - id: dispute_escalation_01
108
+ input: "I was charged twice — this is unauthorized"
109
+ expected_tool_calls: [classify_dispute, route_escalation]
110
+ expected_output_contains: ["escalated"]
111
+ max_latency_ms: 5000
112
+ ```
113
+
114
+ ---
115
+
116
+ ## CI eval gate
117
+
118
+ Add to `.github/workflows/eval.yml`:
119
+
120
+ ```yaml
121
+ - name: CortexOps eval gate
122
+ run: |
123
+ python examples/langgraph_payments/run_eval.py \
124
+ --dataset golden_v1.yaml \
125
+ --fail-on "task_completion < 0.90"
126
+ ```
127
+
128
+ If the eval drops below threshold, the job exits non-zero and the PR is blocked.
129
+
130
+ ---
131
+
132
+ ## Repo structure
133
+
134
+ ```
135
+ cortexops/
136
+ ├── sdk/ # pip install cortexops # v0.4.0
137
+ │ ├── cortexops/
138
+ │ │ ├── tracer.py # CortexTracer — wraps LangGraph / CrewAI
139
+ │ │ ├── eval.py # EvalSuite — golden dataset runner
140
+ │ │ ├── metrics.py # task_completion, tool_accuracy, latency, hallucination
141
+ │ │ ├── models.py # Pydantic data models
142
+ │ │ └── client.py # HTTP client for hosted API
143
+ │ └── tests/
144
+ ├── backend/ # FastAPI + Celery + SQLite/Postgres
145
+ │ ├── app/
146
+ │ │ ├── main.py
147
+ │ │ ├── routers/ # /v1/evals, /v1/traces
148
+ │ │ ├── models/ # DB records + API schemas
149
+ │ │ └── worker/ # Celery async eval tasks
150
+ │ └── Dockerfile
151
+ ├── frontend/ # React + TypeScript dashboard
152
+ ├── examples/
153
+ │ └── langgraph_payments/ # Full runnable demo
154
+ │ ├── agent.py
155
+ │ ├── golden_v1.yaml
156
+ │ └── run_eval.py
157
+ └── docker-compose.yml
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Run the full stack locally
163
+
164
+ ```bash
165
+ git clone https://github.com/ashishodu2023/cortexops
166
+ cd cortexops
167
+
168
+ # Start API + worker + Redis
169
+ docker compose up --build
170
+
171
+ # In another terminal — run the demo eval
172
+ cd examples/langgraph_payments
173
+ pip install -e ../../sdk/
174
+ python run_eval.py
175
+
176
+ # API docs at http://localhost:8000/docs
177
+ # Dashboard at http://localhost:3000
178
+ ```
179
+
180
+ ---
181
+
182
+ ## Supported frameworks
183
+
184
+ | Framework | Status |
185
+ |---|---|
186
+ | LangGraph | Stable |
187
+ | CrewAI | Stable |
188
+ | AutoGen | Beta |
189
+ | LlamaIndex agents | Coming soon |
190
+ | Custom callables | Supported via `CortexTracer.wrap()` |
191
+
192
+ ---
193
+
194
+ ## Built-in metrics
195
+
196
+ | Metric | What it checks |
197
+ |---|---|
198
+ | `task_completion` | Agent produced a valid, non-error output |
199
+ | `tool_accuracy` | Expected tool calls were actually made |
200
+ | `latency` | Response within `max_latency_ms` budget |
201
+ | `hallucination` | Detects fabrication signals in output |
202
+
203
+ Add custom metrics by subclassing `cortexops.Metric`.
204
+
205
+ ---
206
+
207
+ ## Contributing
208
+
209
+ ```bash
210
+ git clone https://github.com/ashishodu2023/cortexops
211
+ cd cortexops/sdk
212
+ pip install -e ".[dev]"
213
+ pytest tests/ -v
214
+ ```
215
+
216
+ See [CONTRIBUTING.md](CONTRIBUTING.md). Issues labeled `good first issue` are a great place to start.
217
+
218
+ ---
219
+
220
+ ## Citation
221
+
222
+ ```bibtex
223
+ @software{cortexops2025,
224
+ author = {Ashish, et al.},
225
+ title = {CortexOps: Reliability Infrastructure for AI Agents},
226
+ year = {2025},
227
+ url = {https://github.com/ashishodu2023/cortexops},
228
+ }
229
+ ```
230
+
231
+ ---
232
+
233
+ ## License
234
+
235
+ MIT — see [LICENSE](LICENSE).
236
+
237
+ ---
238
+
239
+ <p align="center">
240
+ <a href="https://cortexops.ai">cortexops.ai</a> ·
241
+ <a href="https://github.com/ashishodu2023/cortexops/issues">Issues</a> ·
242
+ <a href="https://github.com/ashishodu2023/cortexops/discussions">Discussions</a>
243
+ </p>
@@ -34,7 +34,7 @@ from .models import (
34
34
  )
35
35
  from .tracer import CortexTracer
36
36
 
37
- __version__ = "0.3.0"
37
+ __version__ = "0.5.0"
38
38
 
39
39
  __all__ = [
40
40
  "CortexTracer",
@@ -127,6 +127,88 @@ def cmd_version(_: argparse.Namespace) -> int:
127
127
  return 0
128
128
 
129
129
 
130
+
131
+
132
+ def cmd_dataset_create(args: argparse.Namespace) -> int:
133
+ """cortexops dataset create --name my-dataset --output dataset.yaml"""
134
+ sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
135
+ from cortexops.dataset import GoldenDataset
136
+
137
+ ds = GoldenDataset(name=args.name, description=args.description or "")
138
+ ds.save(args.output)
139
+ print(f"Created dataset: {args.output}")
140
+ print(" Add cases by editing the YAML file or using ds.add() in Python.")
141
+ return 0
142
+
143
+
144
+ def cmd_eval_judge(args: argparse.Namespace) -> int:
145
+ """cortexops eval judge --input <str> --output <str> --rubric task_completion"""
146
+ sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
147
+ from cortexops.judge import RUBRICS, LLMJudge
148
+
149
+ api_key = args.api_key or os.getenv("OPENAI_API_KEY", "")
150
+ if not api_key:
151
+ print("Error: OPENAI_API_KEY not set. Pass --api-key or set the env var.", file=sys.stderr)
152
+ return 1
153
+
154
+ judge = LLMJudge(api_key=api_key, model=args.model or "gpt-4o-mini")
155
+ result = judge.evaluate(
156
+ case_id="cli-eval",
157
+ input=args.input,
158
+ output=args.output,
159
+ rubric=args.rubric or "task_completion",
160
+ expected=args.expected,
161
+ )
162
+
163
+ icon = "✓ PASS" if result.passed else "✗ FAIL"
164
+ print(f"\nLLM Judge Result: {icon}")
165
+ rubric_obj = RUBRICS.get(args.rubric or 'task_completion')
166
+ threshold = rubric_obj.pass_threshold if rubric_obj else 0.70
167
+ print(f" Score: {result.score:.3f} (threshold: {threshold:.2f})")
168
+ print(f" Model: {result.model} ({result.latency_ms}ms)")
169
+ print(f" Reasoning: {result.reasoning}")
170
+ if args.verbose:
171
+ print(f" Criteria: {result.criteria_scores}")
172
+
173
+ return 0 if result.passed else 1
174
+
175
+
176
+ def cmd_eval_run_with_judge(args: argparse.Namespace) -> int:
177
+ """cortexops eval run --dataset d.yaml --judge --fail-on task_completion<0.90"""
178
+ sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
179
+ from cortexops.dataset import GoldenDataset
180
+
181
+ ds = GoldenDataset.load(args.dataset)
182
+ print("CortexOps eval gate")
183
+ print(f" dataset : {args.dataset} ({len(ds)} cases)")
184
+ print(f" project : {args.project or ds.name}")
185
+ if args.fail_on:
186
+ print(f" fail-on : {args.fail_on}")
187
+ if args.judge:
188
+ print(f" judge : LLM-as-judge ({args.model or 'gpt-4o-mini'})")
189
+ print()
190
+
191
+ def passthrough_agent(inp):
192
+ return {"output": f"[no agent] input: {inp}"}
193
+
194
+ try:
195
+ agent = _load_agent(args.agent) if getattr(args, "agent", None) else passthrough_agent
196
+ result = ds.run(
197
+ agent=agent,
198
+ fail_on=args.fail_on,
199
+ verbose=True,
200
+ use_judge=getattr(args, "judge", False),
201
+ judge_rubric=getattr(args, "rubric", "task_completion"),
202
+ judge_api_key=os.getenv("OPENAI_API_KEY"),
203
+ )
204
+ result.print_report()
205
+ return 0 if result.passed() else 1
206
+ except Exception as e:
207
+ print(f"\nEval failed: {e}", file=sys.stderr)
208
+ return 1
209
+
210
+
211
+
130
212
  def _load_agent(agent_path: str):
131
213
  """Load an agent from a dotted path like 'mymodule:my_agent'."""
132
214
  if ":" not in agent_path: