Skip to content

Commit 46129f7

Browse files
dschwarz26claude
andauthored
Implement SDK and MCP methods for Classify (#242)
* Add classify SDK & MCP endpoints - Add classify() and classify_async() to SDK ops.py - Add ClassifyInput model to MCP models.py - Add everyrow_classify MCP tool to tools.py - Add classify entry to manifest.json - Add docs/reference/CLASSIFY.md and update docs/api.md - Add integration test for classify Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add classify and forecast to all operation listings Update all documentation, MCP server README, skill reference, and manifest to include classify and forecast alongside existing operations. Rewrite CLASSIFY.md reference with real GICS sector example. Update tool description to describe research scaling rather than implementation phases. Point Classifiers link in README to CLASSIFY instead of SCREEN and replace screen code example with classify. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: format test_classify.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add everyrow_classify to test tool lists Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: bump plugin version to 0.4.1 for skill changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: bump all version files to 0.4.1 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7d18d3b commit 46129f7

22 files changed

Lines changed: 589 additions & 37 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"name": "everyrow",
1212
"source": "./",
1313
"description": "Give Claude Code a research team. Forecast, score, classify, or research every row of a dataset.",
14-
"version": "0.4.0"
14+
"version": "0.4.1"
1515
}
1616
]
1717
}

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "everyrow",
33
"description": "Give Claude Code a research team. Forecast, score, classify, or research every row of a dataset.",
4-
"version": "0.4.0",
4+
"version": "0.4.1",
55
"author": {
66
"name": "FutureSearch"
77
},

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Spin up a team of:
2929
| [**Agents**](https://everyrow.io/docs/reference/RESEARCH) | Research, then analyze | 1–3¢/researcher | 10k rows |
3030
| [**Forecasters**](https://everyrow.io/docs/reference/FORECAST) | Predict outcomes | 20-50¢/researcher | 10k rows |
3131
| [**Scorers**](https://everyrow.io/docs/reference/RANK) | Research, then score | 1-5¢/researcher | 10k rows |
32-
| [**Classifiers**](https://everyrow.io/docs/reference/SCREEN) | Research, then categorize | 0.1-0.7¢/researcher | 10k rows |
32+
| [**Classifiers**](https://everyrow.io/docs/reference/CLASSIFY) | Research, then categorize | 0.1-0.7¢/researcher | 10k rows |
3333
| [**Matchers**](https://everyrow.io/docs/reference/MERGE) | Find matching rows | 0.2-0.5¢/researcher | 20k rows |
3434

3535
See the full [API reference](https://everyrow.io/docs/api), [guides](https://everyrow.io/docs/guides), and [case studies](https://everyrow.io/docs/case-studies), (for example, see our [case study](https://everyrow.io/docs/case-studies/llm-web-research-agents-at-scale) running a `Research` task on 10k rows, running agents that used 120k LLM calls.)
@@ -203,23 +203,23 @@ Requires Python 3.12+. Then you can use the SDK directly:
203203
```python
204204
import asyncio
205205
import pandas as pd
206-
from everyrow.ops import screen
207-
from pydantic import BaseModel, Field
206+
from everyrow.ops import classify
208207

209208
companies = pd.DataFrame([
210-
{"company": "Airtable",}, {"company": "Vercel",}, {"company": "Notion",}
209+
{"company": "Apple"}, {"company": "JPMorgan Chase"}, {"company": "ExxonMobil"},
210+
{"company": "Tesla"}, {"company": "Pfizer"}, {"company": "Duke Energy"},
211211
])
212212

213-
class JobScreenResult(BaseModel):
214-
qualifies: bool = Field(description="True if company lists jobs with all criteria")
215-
216213
async def main():
217-
result = await screen(
218-
task="""Qualifies if: 1. Remote-friendly, 2. Senior, and 3. Discloses salary""",
214+
result = await classify(
215+
task="Classify this company by its GICS industry sector",
216+
categories=["Energy", "Materials", "Industrials", "Consumer Discretionary",
217+
"Consumer Staples", "Health Care", "Financials",
218+
"Information Technology", "Communication Services",
219+
"Utilities", "Real Estate"],
219220
input=companies,
220-
response_model=JobScreenResult,
221221
)
222-
print(result.data.head())
222+
print(result.data[["company", "classification"]])
223223

224224
asyncio.run(main())
225225
```

docs/api.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
title: API Reference
3-
description: Complete API reference for everyrow — screen, rank, dedupe, merge, forecast, and research operations powered by LLM web research agents.
3+
description: Complete API reference for everyrow — screen, rank, dedupe, merge, classify, forecast, and research operations powered by LLM web research agents.
44
---
55

66
# API Reference
77

8-
Six operations for processing data with LLM-powered web research agents. Each takes a DataFrame and a natural-language instruction.
8+
Seven operations for processing data with LLM-powered web research agents. Each takes a DataFrame and a natural-language instruction.
99

1010
## screen
1111

@@ -55,6 +55,20 @@ result = await merge(task=..., left_table=df1, right_table=df2)
5555
Guides: [Fuzzy Join Without Matching Keys](/docs/fuzzy-join-without-keys)
5656
Case Studies: [LLM Merging at Scale](/docs/case-studies/llm-powered-merging-at-scale), [Match Software Vendors to Requirements](/docs/case-studies/match-software-vendors-to-requirements)
5757

58+
## classify
59+
60+
```python
61+
result = await classify(
62+
task="Classify each company by its primary industry sector",
63+
categories=["Technology", "Finance", "Healthcare", "Energy"],
64+
input=companies_df,
65+
)
66+
```
67+
68+
`classify` assigns each row in a DataFrame to one of the provided categories using web research that scales to the difficulty of the classification. Supports binary (yes/no) and multi-category classification with optional reasoning output.
69+
70+
[Full reference →](/docs/reference/CLASSIFY)
71+
5872
## forecast
5973

6074
```python

docs/case-studies.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
---
22
title: Case Studies
3-
description: Runnable case studies demonstrating everyrow operations on real datasets — screen, rank, dedupe, merge, and research with LLM-powered agents.
3+
description: Runnable case studies demonstrating everyrow operations on real datasets — classify, screen, rank, dedupe, merge, forecast, and research with LLM-powered agents.
44
---
55

66
# Case Studies
77

88
Runnable case studies with real datasets. Each case study demonstrates an everyrow operation end-to-end with output you can inspect.
99

10+
## Classify
11+
12+
- [Classify and Label Data](/docs/classify-dataframe-rows-llm)
13+
1014
## Screen
1115

1216
- [Screen 10,000 Rows](/docs/case-studies/llm-powered-screening-at-scale)
@@ -33,6 +37,10 @@ Runnable case studies with real datasets. Each case study demonstrates an everyr
3337
- [Link Records Across Medical Datasets](/docs/case-studies/match-clinical-trials-to-papers)
3438
- [Merge Costs and Speed](/docs/case-studies/understanding-costs-and-speed-for-merge)
3539

40+
## Forecast
41+
42+
- [Automating Forecasting Questions](https://futuresearch.ai/automating-forecasting-questions/)
43+
3644
## Multi-Method
3745

3846
- [Multi-Stage Lead Qualification](/docs/case-studies/multi-stage-lead-qualification)

docs/getting-started.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,15 @@ df = await fetch_task_data("12345678-1234-1234-1234-123456789abc")
150150

151151
## Operations
152152

153-
| Operation | Description |
154-
| ------------------------------- | ------------------------------------------ |
155-
| [Screen](/reference/SCREEN) | Filter rows by criteria requiring judgment |
156-
| [Rank](/reference/RANK) | Score rows by qualitative factors |
157-
| [Dedupe](/reference/DEDUPE) | Deduplicate when fuzzy matching fails |
158-
| [Merge](/reference/MERGE) | Join tables when keys don't match exactly |
159-
| [Research](/reference/RESEARCH) | Run web agents to research each row |
153+
| Operation | Description |
154+
| --------------------------------- | ------------------------------------------ |
155+
| [Classify](/reference/CLASSIFY) | Categorize rows into predefined classes |
156+
| [Screen](/reference/SCREEN) | Filter rows by criteria requiring judgment |
157+
| [Rank](/reference/RANK) | Score rows by qualitative factors |
158+
| [Dedupe](/reference/DEDUPE) | Deduplicate when fuzzy matching fails |
159+
| [Merge](/reference/MERGE) | Join tables when keys don't match exactly |
160+
| [Forecast](/reference/FORECAST) | Predict probabilities for binary questions |
161+
| [Research](/reference/RESEARCH) | Run web agents to research each row |
160162

161163
## See Also
162164

docs/guides.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
---
22
title: Guides
3-
description: Step-by-step tutorials for using everyrow to screen, rank, dedupe, merge, and research data with LLM-powered agents.
3+
description: Step-by-step tutorials for using everyrow to classify, screen, rank, dedupe, merge, forecast, and research data with LLM-powered agents.
44
---
55

66
# Guides
77

88
Practical walkthroughs that show you how to use everyrow for common data processing tasks. Each guide covers a single operation end-to-end with working code.
99

10+
## Classify
11+
12+
- [Classify and Label Rows](/docs/classify-dataframe-rows-llm)
13+
1014
## Screen
1115

1216
- [Filter a Dataset Intelligently](/docs/filter-dataframe-with-llm)
@@ -25,8 +29,11 @@ Practical walkthroughs that show you how to use everyrow for common data process
2529

2630
- [Join Tables Without Shared Keys](/docs/fuzzy-join-without-keys)
2731

32+
## Forecast
33+
34+
- [Forecast Binary Questions](/docs/reference/FORECAST)
35+
2836
## Research
2937

3038
- [Add a Column via Web Research](/docs/add-column-web-lookup)
31-
- [Classify and Label Rows](/docs/classify-dataframe-rows-llm)
3239
- [LLM-Powered Data Labeling](/docs/active-learning-llm-oracle)

docs/mcp-server.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,29 @@ Join two CSVs using intelligent entity matching (LEFT JOIN semantics).
6565

6666
Returns `task_id` and `session_url`. Call `everyrow_progress` to monitor.
6767

68+
### everyrow_classify
69+
70+
Classify each row into one of the provided categories.
71+
72+
| Parameter | Type | Required | Description |
73+
|-----------|------|----------|-------------|
74+
| `task` | string | Yes | Classification instructions. |
75+
| `categories` | list[string] | Yes | Allowed categories (minimum 2). Each row is assigned exactly one. |
76+
| `classification_field` | string | No | Output column name (default: `"classification"`). |
77+
| `include_reasoning` | boolean | No | Include a reasoning column (default: false). |
78+
79+
Returns `task_id` and `session_url`. Call `everyrow_progress` to monitor.
80+
81+
### everyrow_forecast
82+
83+
Forecast the probability of binary questions.
84+
85+
| Parameter | Type | Required | Description |
86+
|-----------|------|----------|-------------|
87+
| `context` | string | No | Optional batch-level context for all questions. |
88+
89+
Returns `task_id` and `session_url`. Call `everyrow_progress` to monitor.
90+
6891
### everyrow_agent
6992

7093
Run web research agents on each row.

docs/reference/CLASSIFY.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
title: classify
3+
description: API reference for the EveryRow classify tool, which assigns each row of a dataset into one of the provided categories using web research.
4+
---
5+
6+
# Classify
7+
8+
`classify` takes a DataFrame and a list of allowed categories, then assigns each row to exactly one category using web research that scales to the difficulty of the classification. Supports binary (yes/no) and multi-category classification with optional reasoning output.
9+
10+
## Examples
11+
12+
### GICS sector classification
13+
14+
```python
15+
from pandas import DataFrame
16+
from everyrow.ops import classify
17+
18+
companies = DataFrame([
19+
{"company": "Apple"},
20+
{"company": "JPMorgan Chase"},
21+
{"company": "ExxonMobil"},
22+
{"company": "Pfizer"},
23+
{"company": "Procter & Gamble"},
24+
{"company": "Tesla"},
25+
{"company": "AT&T"},
26+
{"company": "Caterpillar"},
27+
{"company": "Duke Energy"},
28+
{"company": "Simon Property Group"},
29+
])
30+
31+
result = await classify(
32+
task="Classify this company by its GICS industry sector",
33+
categories=[
34+
"Energy", "Materials", "Industrials", "Consumer Discretionary",
35+
"Consumer Staples", "Health Care", "Financials",
36+
"Information Technology", "Communication Services",
37+
"Utilities", "Real Estate",
38+
],
39+
input=companies,
40+
)
41+
print(result.data[["company", "classification"]])
42+
```
43+
44+
Output:
45+
46+
| company | classification |
47+
|----------------------|------------------------|
48+
| Apple | Information Technology |
49+
| JPMorgan Chase | Financials |
50+
| ExxonMobil | Energy |
51+
| Pfizer | Health Care |
52+
| Procter & Gamble | Consumer Staples |
53+
| Tesla | Consumer Discretionary |
54+
| AT&T | Communication Services |
55+
| Caterpillar | Industrials |
56+
| Duke Energy | Utilities |
57+
| Simon Property Group | Real Estate |
58+
59+
### Binary classification
60+
61+
For yes/no questions, use two categories:
62+
63+
```python
64+
result = await classify(
65+
task="Is this company founder-led?",
66+
categories=["yes", "no"],
67+
input=companies,
68+
)
69+
```
70+
71+
### Custom output column and reasoning
72+
73+
```python
74+
result = await classify(
75+
task="Classify each company by its primary industry sector",
76+
categories=["Technology", "Finance", "Healthcare", "Energy"],
77+
input=companies,
78+
classification_field="sector",
79+
include_reasoning=True,
80+
)
81+
print(result.data[["company", "sector", "reasoning"]])
82+
```
83+
84+
## Parameters
85+
86+
| Name | Type | Default | Description |
87+
|------|------|---------|-------------|
88+
| `task` | str | required | Natural-language instructions describing how to classify each row |
89+
| `categories` | list[str] | required | Allowed category values (minimum 2). Each row is assigned exactly one. |
90+
| `input` | DataFrame | required | Rows to classify |
91+
| `classification_field` | str | `"classification"` | Name of the output column for the assigned category |
92+
| `include_reasoning` | bool | `False` | If True, adds a `reasoning` column with the agent's justification |
93+
| `session` | Session | Optional, auto-created if omitted | |
94+
95+
## Output
96+
97+
One column is added to each input row (name controlled by `classification_field`):
98+
99+
| Column | Type | Description |
100+
|--------|------|-------------|
101+
| `classification` | str | One of the provided `categories` values |
102+
| `reasoning` | str | Agent's justification (only if `include_reasoning=True`) |
103+
104+
## Via MCP
105+
106+
MCP tool: `everyrow_classify`
107+
108+
| Parameter | Type | Description |
109+
|-----------|------|-------------|
110+
| `task` | string | Classification instructions |
111+
| `categories` | list[string] | Allowed categories (minimum 2) |
112+
| `classification_field` | string | Output column name (default: `"classification"`) |
113+
| `include_reasoning` | boolean | Include reasoning column (default: false) |

everyrow-mcp/README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
MCP (Model Context Protocol) server for [everyrow](https://everyrow.io): agent ops at spreadsheet scale.
44

5-
This server exposes everyrow's 5 core operations as MCP tools, allowing LLM applications to screen, rank, dedupe, merge, and run agents on CSV files.
5+
This server exposes everyrow's core operations as MCP tools, allowing LLM applications to classify, screen, rank, dedupe, merge, forecast, and run agents on CSV files.
66

77
**All tools operate on local CSV files.** Provide absolute file paths as input, and transformed results are written to new CSV files at your specified output path.
88

@@ -116,6 +116,31 @@ Parameters:
116116

117117
Example: Match software products (left, enriched) to parent companies (right, lookup): Photoshop -> Adobe
118118

119+
### everyrow_classify
120+
121+
Classify each row into one of the provided categories.
122+
123+
```
124+
Parameters:
125+
- task: Natural language classification instructions
126+
- categories: Allowed categories (minimum 2)
127+
- classification_field: (optional) Output column name (default: "classification")
128+
- include_reasoning: (optional) Include reasoning column (default: false)
129+
```
130+
131+
Example: Classify companies by GICS sector with categories ["Energy", "Financials", "Information Technology", ...]
132+
133+
### everyrow_forecast
134+
135+
Forecast the probability of binary questions.
136+
137+
```
138+
Parameters:
139+
- context: (optional) Batch-level context for all questions
140+
```
141+
142+
Example: "Will the US Federal Reserve cut rates before July 2027?"
143+
119144
### everyrow_agent
120145

121146
Run web research agents on each row of a CSV.

0 commit comments

Comments
 (0)