onlymetrix 0.2.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OnlyMetrix
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.4
2
+ Name: onlymetrix
3
+ Version: 0.2.0
4
+ Summary: Governed data access for AI agents. Connect to Snowflake, Postgres, or any warehouse with curated metrics, PII masking, and audit trails.
5
+ License: MIT
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: httpx>=0.25
10
+ Requires-Dist: click>=8.0
11
+ Provides-Extra: langchain
12
+ Requires-Dist: langchain-core>=0.2; extra == "langchain"
13
+ Provides-Extra: crewai
14
+ Requires-Dist: crewai>=0.80; extra == "crewai"
15
+ Provides-Extra: all
16
+ Requires-Dist: langchain-core>=0.2; extra == "all"
17
+ Requires-Dist: crewai>=0.80; extra == "all"
18
+ Provides-Extra: dev
19
+ Requires-Dist: pytest>=8.0; extra == "dev"
20
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
21
+ Requires-Dist: respx>=0.21; extra == "dev"
22
+ Dynamic: license-file
23
+
24
+ # OnlyMetrix
25
+
26
+ Your AI agents shouldn't write SQL. Your data team defines the metrics once. The agent just picks which one to run.
27
+
28
+ ```bash
29
+ pip install onlymetrix
30
+ ```
31
+
32
+ ```python
33
+ from onlymetrix import OnlyMetrix
34
+
35
+ om = OnlyMetrix("https://api.onlymetrix.com", api_key="omx_sk_...")
36
+
37
+ result = om.metrics.query("total_revenue")
38
+ print(f"Revenue: £{result.rows[0]['revenue_gbp']:,.2f}")
39
+ # → Revenue: £17,743,429.16
40
+ # Deterministic. Auditable. No SQL generated.
41
+ ```
42
+
43
+ ## What It Does
44
+
45
+ OnlyMetrix sits between your AI agents and your warehouse. Agents query governed metrics — not raw SQL. Every query is PII-masked, audit-logged, and rate-limited.
46
+
47
+ ```python
48
+ # Search by intent — semantic, not keyword
49
+ metrics = om.metrics.list(search="customer churn risk")
50
+
51
+ # Query with filters and dimensions
52
+ result = om.metrics.query("churn_by_country", filters={"country": "United Kingdom"})
53
+
54
+ # Schema discovery
55
+ tables = om.tables.list()
56
+ desc = om.tables.describe("customers")
57
+ ```
58
+
59
+ ## Analysis — Not Just Queries, Reasoning
60
+
61
+ The analysis layer lets agents explain *why* a metric changed, not just report the number.
62
+
63
+ ```python
64
+ # "Why did revenue drop?"
65
+ root = om.analysis.root_cause(
66
+ "quarterly_revenue",
67
+ compare={"current": "2025-02", "previous": "2025-01"},
68
+ dimensions=["country", "tier"],
69
+ )
70
+ print(root["explanation"])
71
+ # → "Revenue decreased. Primary driver: country=Germany (72% of change)."
72
+ print(root["suggested_actions"])
73
+ # → ["Investigate DACH expansion strategy"]
74
+
75
+ # "What's our concentration risk?"
76
+ risk = om.analysis.sensitivity("revenue", "country", scenario="remove_top_3")
77
+ print(f"{risk['value']['impact_pct']}% of revenue in top 3 countries — {risk['value']['risk']}")
78
+ # → 94% of revenue in top 3 countries — critical
79
+
80
+ # "Do churned customers overlap with high spenders?"
81
+ corr = om.analysis.correlate("churned_customers", "high_spenders")
82
+ print(f"Jaccard: {corr['value']['jaccard']:.3f} — {corr['value']['interpretation']}")
83
+ # → Jaccard: 0.049 — independent (churn isn't a spending problem)
84
+ ```
85
+
86
+ Every analysis returns structured output agents can parse:
87
+
88
+ ```python
89
+ {
90
+ "value": {...}, # the finding
91
+ "explanation": "...", # plain English
92
+ "confidence": 0.85, # 0.0-1.0
93
+ "warnings": [...], # data quality issues
94
+ "suggested_actions": [...], # what to do next
95
+ }
96
+ ```
97
+
98
+ ### Available Analyses
99
+
100
+ | Method | Question it answers |
101
+ |--------|-------------------|
102
+ | `root_cause` | Why did this metric change? |
103
+ | `sensitivity` | What's our concentration risk? |
104
+ | `correlate` | Are these populations related? |
105
+ | `threshold` | What's the optimal cutoff? |
106
+ | `segment_performance` | How does this metric vary across segments? |
107
+ | `contribution` | What drove the change between periods? |
108
+ | `drivers` | Which dimension explains variance most? |
109
+ | `anomalies` | Which segments are behaving abnormally? |
110
+ | `pareto` | What's the precision-recall frontier? |
111
+ | `trends` | Is this accelerating or decelerating? |
112
+ | `forecast` | Where is this heading? |
113
+ | `compare` | How do these two groups differ? |
114
+ | `health` | Can I trust this data? |
115
+
116
+ ## Custom Analysis
117
+
118
+ Define your own analytical workflows by composing primitives. No raw SQL — just governed API calls.
119
+
120
+ ```python
121
+ @om.analysis.custom("store_risk")
122
+ def store_risk(ctx, dimension="region"):
123
+ s = ctx.sensitivity(dimension=dimension, scenario="remove_top_3")
124
+ d = ctx.drivers(dimensions=[dimension])
125
+ return {
126
+ "risk": s["value"]["risk"],
127
+ "top_driver": d["dimensions"][0]["dimension"],
128
+ }
129
+
130
+ # Export as JSON DAG — storable, shareable, auditable
131
+ dag = om.analysis.export_dag("store_risk", save_to_server=True)
132
+
133
+ # Anyone on your team can load and run it
134
+ om.analysis.load_from_server("store_risk")
135
+ result = om.analysis.run_custom("store_risk", metric="revenue")
136
+ ```
137
+
138
+ ## CLI
139
+
140
+ ```bash
141
+ omx health
142
+ omx metrics list --search revenue
143
+ omx metrics query total_revenue --filter time_start=2025-01-01
144
+ omx analysis sensitivity churn_by_country -d country
145
+ omx analysis at-risk-profile churn_risk --compare high_spenders
146
+ ```
147
+
148
+ Set `OMX_API_URL` and `OMX_API_KEY` environment variables, or pass them to the client.
149
+
150
+ ## Autoresearch
151
+
152
+ Automatically discover better metric definitions by testing variations against ground truth.
153
+
154
+ ```python
155
+ result = om.autoresearch.run("churn_risk_entities", max_variations=30)
156
+ print(f"Baseline F1: {result['baseline']['f1']:.3f}")
157
+ print(f"Best variation: +{result['improvements']} improvements found")
158
+ # → Baseline F1: 0.660
159
+ # → Best variation: +3 improvements found
160
+ ```
161
+
162
+ ## Agent Integrations
163
+
164
+ ### LangChain
165
+
166
+ ```python
167
+ from onlymetrix.integrations.langchain import onlymetrix_tools
168
+ tools = onlymetrix_tools(url, api_key=key)
169
+ ```
170
+
171
+ ### CrewAI
172
+
173
+ ```python
174
+ from onlymetrix.integrations.crewai import onlymetrix_tools
175
+ tools = onlymetrix_tools(url, api_key=key)
176
+ ```
177
+
178
+ ## Install
179
+
180
+ ```bash
181
+ pip install onlymetrix # core
182
+ pip install onlymetrix[langchain] # + LangChain tools
183
+ pip install onlymetrix[crewai] # + CrewAI tools
184
+ pip install onlymetrix[all] # everything
185
+ ```
186
+
187
+ Python 3.9+. Async client included (`AsyncOnlyMetrix`).
188
+
189
+ ## Links
190
+
191
+ - [Documentation](https://docs.onlymetrix.com)
192
+ - [API Reference](https://api.onlymetrix.com)
193
+ - [Changelog](CHANGELOG.md)
194
+
195
+ ## License
196
+
197
+ MIT
@@ -0,0 +1,174 @@
1
+ # OnlyMetrix
2
+
3
+ Your AI agents shouldn't write SQL. Your data team defines the metrics once. The agent just picks which one to run.
4
+
5
+ ```bash
6
+ pip install onlymetrix
7
+ ```
8
+
9
+ ```python
10
+ from onlymetrix import OnlyMetrix
11
+
12
+ om = OnlyMetrix("https://api.onlymetrix.com", api_key="omx_sk_...")
13
+
14
+ result = om.metrics.query("total_revenue")
15
+ print(f"Revenue: £{result.rows[0]['revenue_gbp']:,.2f}")
16
+ # → Revenue: £17,743,429.16
17
+ # Deterministic. Auditable. No SQL generated.
18
+ ```
19
+
20
+ ## What It Does
21
+
22
+ OnlyMetrix sits between your AI agents and your warehouse. Agents query governed metrics — not raw SQL. Every query is PII-masked, audit-logged, and rate-limited.
23
+
24
+ ```python
25
+ # Search by intent — semantic, not keyword
26
+ metrics = om.metrics.list(search="customer churn risk")
27
+
28
+ # Query with filters and dimensions
29
+ result = om.metrics.query("churn_by_country", filters={"country": "United Kingdom"})
30
+
31
+ # Schema discovery
32
+ tables = om.tables.list()
33
+ desc = om.tables.describe("customers")
34
+ ```
35
+
36
+ ## Analysis — Not Just Queries, Reasoning
37
+
38
+ The analysis layer lets agents explain *why* a metric changed, not just report the number.
39
+
40
+ ```python
41
+ # "Why did revenue drop?"
42
+ root = om.analysis.root_cause(
43
+ "quarterly_revenue",
44
+ compare={"current": "2025-02", "previous": "2025-01"},
45
+ dimensions=["country", "tier"],
46
+ )
47
+ print(root["explanation"])
48
+ # → "Revenue decreased. Primary driver: country=Germany (72% of change)."
49
+ print(root["suggested_actions"])
50
+ # → ["Investigate DACH expansion strategy"]
51
+
52
+ # "What's our concentration risk?"
53
+ risk = om.analysis.sensitivity("revenue", "country", scenario="remove_top_3")
54
+ print(f"{risk['value']['impact_pct']}% of revenue in top 3 countries — {risk['value']['risk']}")
55
+ # → 94% of revenue in top 3 countries — critical
56
+
57
+ # "Do churned customers overlap with high spenders?"
58
+ corr = om.analysis.correlate("churned_customers", "high_spenders")
59
+ print(f"Jaccard: {corr['value']['jaccard']:.3f} — {corr['value']['interpretation']}")
60
+ # → Jaccard: 0.049 — independent (churn isn't a spending problem)
61
+ ```
62
+
63
+ Every analysis returns structured output agents can parse:
64
+
65
+ ```python
66
+ {
67
+ "value": {...}, # the finding
68
+ "explanation": "...", # plain English
69
+ "confidence": 0.85, # 0.0-1.0
70
+ "warnings": [...], # data quality issues
71
+ "suggested_actions": [...], # what to do next
72
+ }
73
+ ```
74
+
75
+ ### Available Analyses
76
+
77
+ | Method | Question it answers |
78
+ |--------|-------------------|
79
+ | `root_cause` | Why did this metric change? |
80
+ | `sensitivity` | What's our concentration risk? |
81
+ | `correlate` | Are these populations related? |
82
+ | `threshold` | What's the optimal cutoff? |
83
+ | `segment_performance` | How does this metric vary across segments? |
84
+ | `contribution` | What drove the change between periods? |
85
+ | `drivers` | Which dimension explains variance most? |
86
+ | `anomalies` | Which segments are behaving abnormally? |
87
+ | `pareto` | What's the precision-recall frontier? |
88
+ | `trends` | Is this accelerating or decelerating? |
89
+ | `forecast` | Where is this heading? |
90
+ | `compare` | How do these two groups differ? |
91
+ | `health` | Can I trust this data? |
92
+
93
+ ## Custom Analysis
94
+
95
+ Define your own analytical workflows by composing primitives. No raw SQL — just governed API calls.
96
+
97
+ ```python
98
+ @om.analysis.custom("store_risk")
99
+ def store_risk(ctx, dimension="region"):
100
+ s = ctx.sensitivity(dimension=dimension, scenario="remove_top_3")
101
+ d = ctx.drivers(dimensions=[dimension])
102
+ return {
103
+ "risk": s["value"]["risk"],
104
+ "top_driver": d["dimensions"][0]["dimension"],
105
+ }
106
+
107
+ # Export as JSON DAG — storable, shareable, auditable
108
+ dag = om.analysis.export_dag("store_risk", save_to_server=True)
109
+
110
+ # Anyone on your team can load and run it
111
+ om.analysis.load_from_server("store_risk")
112
+ result = om.analysis.run_custom("store_risk", metric="revenue")
113
+ ```
114
+
115
+ ## CLI
116
+
117
+ ```bash
118
+ omx health
119
+ omx metrics list --search revenue
120
+ omx metrics query total_revenue --filter time_start=2025-01-01
121
+ omx analysis sensitivity churn_by_country -d country
122
+ omx analysis at-risk-profile churn_risk --compare high_spenders
123
+ ```
124
+
125
+ Set `OMX_API_URL` and `OMX_API_KEY` environment variables, or pass them to the client.
126
+
127
+ ## Autoresearch
128
+
129
+ Automatically discover better metric definitions by testing variations against ground truth.
130
+
131
+ ```python
132
+ result = om.autoresearch.run("churn_risk_entities", max_variations=30)
133
+ print(f"Baseline F1: {result['baseline']['f1']:.3f}")
134
+ print(f"Best variation: +{result['improvements']} improvements found")
135
+ # → Baseline F1: 0.660
136
+ # → Best variation: +3 improvements found
137
+ ```
138
+
139
+ ## Agent Integrations
140
+
141
+ ### LangChain
142
+
143
+ ```python
144
+ from onlymetrix.integrations.langchain import onlymetrix_tools
145
+ tools = onlymetrix_tools(url, api_key=key)
146
+ ```
147
+
148
+ ### CrewAI
149
+
150
+ ```python
151
+ from onlymetrix.integrations.crewai import onlymetrix_tools
152
+ tools = onlymetrix_tools(url, api_key=key)
153
+ ```
154
+
155
+ ## Install
156
+
157
+ ```bash
158
+ pip install onlymetrix # core
159
+ pip install onlymetrix[langchain] # + LangChain tools
160
+ pip install onlymetrix[crewai] # + CrewAI tools
161
+ pip install onlymetrix[all] # everything
162
+ ```
163
+
164
+ Python 3.9+. Async client included (`AsyncOnlyMetrix`).
165
+
166
+ ## Links
167
+
168
+ - [Documentation](https://docs.onlymetrix.com)
169
+ - [API Reference](https://api.onlymetrix.com)
170
+ - [Changelog](CHANGELOG.md)
171
+
172
+ ## License
173
+
174
+ MIT
@@ -0,0 +1,18 @@
1
+ from onlymetrix.client import OnlyMetrix, AsyncOnlyMetrix, OnlyMetrixError
2
+ from onlymetrix.models import Metric, MetricResult, MetricRequest, QueryResult, Table, Column, TableDescription
3
+ from onlymetrix.analysis import Analysis
4
+
5
+ __version__ = "0.2.0"
6
+ __all__ = [
7
+ "OnlyMetrix",
8
+ "AsyncOnlyMetrix",
9
+ "OnlyMetrixError",
10
+ "Analysis",
11
+ "Metric",
12
+ "MetricResult",
13
+ "MetricRequest",
14
+ "QueryResult",
15
+ "Table",
16
+ "Column",
17
+ "TableDescription",
18
+ ]