jev_rows
Qualify a table's rows with Jev ON THE SERVER: rows are read, judged and written back here, and no row data passes through you. Write the rubric; review the sample.
Each row's state_fields are sent with the same questions; each answer is written
to its output column, its confidence to <column>_p (choice and score), and the
model snapshot to model_column. A noul writes its probability; a score writes
the expected level (e.g. 3.34). A row Jev can never answer as is (state too large,
or refused upstream as too long) or whose answer the table refuses to store gets
jev_error: <reason> in model_column. A row whose state fields are all empty is
counted in empty_state and left undecided: fill it, then re-run.
Missing output, <column>_p and model_column columns are created, typed from
the questions (choice → enum of its criteria); existing ones are never changed.
The key and the rubric are checked before anything is created or written.
Only undecided rows are taken (model_column empty) unless overwrite=true, so a
re-run resumes and never pays twice. Rows leased by another run are skipped, and a
row changed since it was read is never overwritten.
A whole table: background=true (after a dry run). The call returns a job_id
at once and the server judges every matching row itself — no cursor loop, and a
dropped connection doesn't stop it. Follow it with jev_job(op='status'), stop
it with jev_job(op='cancel'). The key, the write right and the quota are
checked again before every slice: a revoked key or a spent quota stops the job,
and what was already judged stays written and billed. One active job per table
and model_column. A job keeps _run_id and bills its slices under it.
Without background, one call judges what fits in its time window (~100 rows):
loop on next_cursor until done, then finish with one pass WITHOUT cursor to
pick up skipped rows. Nothing reserves rows between two calls: do not run two at
once on the same rows.
Any other upstream refusal (key, credits, a malformed request) stops the batch: what was already judged stays written and billed, and the error says how much.
Run dry_run=true on known cases before a full run. Jev sees only the state and the
questions: put client context (ICP, offer) in the criteria or the state. Rows with a
thin state score low for lack of evidence (thin_state counts them). No bucketing
here: thresholds belong to you.
Validate fit against known outcomes before trusting it; combine Jev's answers with
structured fields in plain code.
⚠️ Each state goes to a third party (OpenRouter, then TypeSafe). Billed on real cost, about 50 µ$ per row for 3 questions and a 500-character description.
Returns — {decided, jev_errors, empty_state, skipped_leased, skipped_changed, errors, error_count, low_confidence, thin_state, created_columns, next_cursor, remaining, done, cost, model, sample}. errors and sample name rows by _id
with codes and what was written — never a value read from the table. dry_run
returns rows (each judged row's _id and answers) and would_create_columns,
and writes nothing. background returns {job_id, status, remaining, created_columns}.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"datastore": "<datastore>",
"questions": "<questions>",
"state_fields": "<state_fields>",
"output": "<output>",
"model_column": "<model_column>"
},
"name": "jev_rows"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| _org | No | Org (id) de CET APPEL. `oto_list_orgs()`. | |
| limit | No | max rows judged in this call (default and max 500; dry run max 20). Ignored with `background`: the job takes every matching row. | |
| model | No | another model id (default: the pinned dated snapshot). | |
| _group | No | Équipe (id) de CET APPEL, sous son org parente. | |
| cursor | No | `next_cursor` from the previous call (not with `background`). | |
| filter | No | `data_rows` filter grammar. | |
| output | Yes | `{question: column}`; choice → text/enum, score and noul → number. Missing columns are created. | |
| _run_id | No | OBLIGATOIRE à chaque appel dès `run_start` ou `data_claim_next` : sans lui, l'écriture sur une ligne réservée est refusée. Hérité seulement si le serveur tient un run actif — n'y compte pas. | |
| dry_run | No | judge and return, write nothing (still billed). | |
| filters | No | `data_rows` multi-column clauses. | |
| _project | No | Projet (id) de CET APPEL — jeton PRIMAIRE. `oto_project(op='list')`. | |
| parallel | No | rows in flight (default 25, max 50). | |
| _instance | No | Instance de connecteur PRÉCISE (un credential exact). `oto_instance(op='list')`. | |
| datastore | Yes | the table number (ns_id) or `slot:<name>`. | |
| overwrite | No | also re-judge rows that already have an answer. | |
| questions | Yes | the rubric, same shape and rules as `jev_ask`; `criteria` required. | |
| background | No | run the whole table as a server job; returns a `job_id`. | |
| model_column | Yes | text column for the model snapshot or `jev_error`; required (created if missing). | |
| state_fields | Yes | columns to send, each a name or `{name: max_chars}`. |