Open source npm package, v0.1
Your API already knows how to search. JevFilter lets users ask.
Natural language in, validated filters out. JevFilter turns a user's sentence into a typed filter object for the API you already own. It doesn't generate SQL, and your query layer and authorization stay in charge.
npm install jevfilter @typesafe-ai/sdk
Real outputs from the library. Dates anchored to Wed 23 Sep 2026. Only ready carries executable filters.
readyneeds_clarificationunsupportedblockedunavailable
01 how it works
AI interprets. Your code queries.
The model never writes a query. It picks from options built from your schema, and your code decides what runs.
-
input · the user
A sentence
"urgent billing tickets from last week" -
code · deterministic
Code finds dates & numbers
"last week"→2026-09-14…2026-09-21 -
model · closed options only
Jev chooses from closed options
Which field? Which allowed value? Which phrase?
-
code · deterministic
JevFilter validates every answer
Against the schema you defined.
-
your code · your auth
Your existing API executes it
With your auth, inside the user's tenant.
02 boundaries
What JevFilter won't do
JevFilter doesn't claim to make AI safe. Its guarantee is narrower: the model never gets direct authority over your database.
Generate SQL, ORM code, or any other executable text.
Execute anything the model returns.
Expand the caller's permissions. Scope comes from your session, never from the filters.
Send the model your database credentials or your records.
Guess which record you meant when a name matches several.
03 compare
What you get back
Each approach returns something different. JevFilter returns a filter object that your existing API can already run.
| Approach | What you get back |
|---|---|
| Text-to-SQL | A query string you have to trust |
| AI search engine | A new index to keep all your data in |
| RAG | A generated answer |
| Agent tools | A model that decides which tools to call |
| JevFilter | A bounded, typed filter object for the API you already own |
04 why jev
Why Jev instead of a hosted AI search service
Hosted AI search services generally ask you to copy or index your records into their system. They run the search on their side and return their results or a generated answer. That usually means keeping a second copy of your data in sync and re-creating your permission rules there.
JevFilter with Jev keeps your data where it is. Jev receives the user's search text and your filter schema: field names, descriptions, and allowed values. It never sees your records, your credentials, your query code, or the customer names your resolver finds. Your existing API and its authorization run the query.
A hosted AI search service, usually
- your records
- Copied or indexed into their system
- leaves your server
- Your records, kept in sync
- runs the search
- The service, on its side
- permission rules
- Re-created in the service
- comes back
- Their results or a generated answer
JevFilter with Jev
- your records
- Stay in your database
- leaves your server
- The search text and your filter schema
- runs the search
- Your existing API
- permission rules
- Your authorization, unchanged
- comes back
- A typed filter object from your schema
-
bounded decisions
Jev picks from your options
Jev is built for bounded decisions. It picks from options you define and returns a probability for each, instead of generating free text. The probabilities are why JevFilter can say "I'm not sure, which one?", and an answer outside the options is rejected.
-
cost
About $0.0001 per search
TypeSafe lists Jev at $0.042 per million input tokens and doesn't charge for output tokens. A demo search uses about 2.3k input tokens, so we estimate each search costs roughly $0.0001.
-
speed
About 300 to 520 ms
In the live demo, searches took about 300 to 520 ms end to end, measured locally against the live API.
-
no lock-in
Swap the provider, keep the schema
Jev is the launch provider. The
FilterProviderinterface lets you swap providers without changing your schema or your API.
05 quick start
Three steps to a search box
It runs server-side on Node.js 20+ and ships as ESM. The core has no runtime dependencies; @typesafe-ai/sdk is only needed for the Jev provider.
-
Describe the filters your API already supports
import { defineSearch, enumField, booleanField, numberField, dateField, entityField } from "jevfilter"; const tickets = defineSearch({ resource: "tickets", fields: { status: enumField({ open: "still open, active", pending: null, closed: "resolved, done" }), priority: enumField({ low: null, medium: null, high: "urgent, critical, P1" }), category: enumField(["billing", "sales", "support"]), escalated: booleanField({ description: "escalated to a manager" }), amount: numberField({ unit: "USD" }), createdAt: dateField({ label: "created" }), customer: entityField({ resolve: (name, session) => findCustomers(name, session) }), }, });"Urgent" maps to
highonly because the description says so. JevFilter takes business meaning from your schema and adds none of its own. -
Connect your existing API
import { createNaturalFilter } from "jevfilter"; import { jev } from "jevfilter/jev"; const search = createNaturalFilter({ schema: tickets, provider: jev(), // reads TYPESAFE_API_KEY authorize: (session) => session.canSearchTickets, // runs before any model call executor: (filters, session) => searchTickets(filters, session), // your code, your scope timeZone: "Asia/Kolkata", }); -
Prepare, show, execute
const result = await search.prepare(userText, { context: session }); // never runs a search if (result.status === "ready") { // show result.interpretation as chips, then: const page = await search.execute(result.filters, { context: session }); }The filters are typed from your schema, so
statusis"open" | "pending" | "closed" | { not: … }.
06 keys
Bring your own Jev key
JevFilter never ships a key or proxies requests. Keys never appear in logs, results, or errors.
Powered by Jev from TypeSafe AI, the launch provider. Providers are pluggable.
jev() // TYPESAFE_API_KEY from the environment
jev({ apiKey: process.env.JEV_API_KEY }) // one key for your app
jev({ apiKey: (session) => session.workspace.jevKey }) // each customer brings their own key
07 tested against real Jev
- live eval cases pass on
jev-1.13.0 - 23/23
- cross-tenant leaks
- 0
- input tokens for the whole suite
- ~41k
- unit tests, including a hostile provider that returns random and malicious answers
- 60
The confidence thresholds come from this one small suite, so run npm run eval against your own schema before relying on them. See the eval cases
08 faq
Questions developers ask
Is this text-to-SQL?
No. JevFilter returns filter objects built from your schema. Your code runs the query.
Can the model see my data?
Jev receives the search text and your configured filter schema (field names, descriptions, and allowed values). Records, credentials, and query code never are, so if your category names are sensitive, treat them like the search text. Candidate names aren't sent either, and entity candidate names aren't sent either: the model picks a phrase from the request, and your resolver looks it up within the user's scope.
What if the model is wrong?
Chips show users how their request was read, so they can check it and edit it. Ambiguity returns needs_clarification. If the model fails, times out, or answers outside the options it was given, you get unavailable, and nothing falls back to searching everything.
Can a prompt escape tenant scope?
Scope comes from your session, and the filters can't change it. execute() validates the filters again on every call and reruns authorize(context), and your executor applies tenant and user scope as an outer AND.
Do I need Jev?
Jev is the launch provider. The FilterProvider interface lets you plug in any model that can answer closed multiple-choice questions, and the offline keywordProvider works for tests and demos.
What does it cost?
Each search makes one Jev call. A demo search uses about 2.3k input tokens. TypeSafe lists Jev at $0.042 per million input tokens and doesn't charge for output tokens, so we estimate a search costs about $0.0001.
Which languages and limits?
v0.1 is English only, with one entity field per search. There's no OR across fields and no "open or pending" on a single field. Requests are capped at 500 characters.
What's the license?
MIT.
>_ try it
Type a sentence and watch it become a filter.
The store demo searches 640 made-up products and fills in its filter sidebar from your sentence. The helpdesk demo shows every step on the server, and you can try to break it.