agentrun
★ 423▲ 13Parcha-ai/agentrun
A workflow DSL for agents with a Jev package for the steps that are decisions rather than generation.
Local decision cache keyed on (model, schema, state), with redaction and canonicalisation before hashing, for cheaper repeats and deterministic replay in CI. No license file at the time of writing.
View on GitHub →Hands-on review
A local cache for Jev decisions, shipped as a binary with no source and no licence. It drops user_id before hashing, so two users share one answer.
Good for
Watch out for
Tested Sep 20, 2026 at v0.1.0 binar · debian:13-slim in Docker with --network none, against the built-in mock backend
How we reviewed this: we ran the published v0.1.0 Linux binary in debian:13-slim with --network none, against its own JEVCACHE_BACKEND=mock, and checked its SHA-256 against the published .sha256. We made no Jev calls. There is no source to read.
Treat a Jev decision as a pure function of (model, schema, state) and cache it locally, so the second identical decision costs nothing. That is a good idea, and the right one for a model priced per input token where the same question gets asked thousands of times.
Before hashing, the state is canonicalised: PII patterns are masked and “volatile” fields are dropped, so cosmetically different states that mean the same thing land on one key. Dropping created_at and timestamp is exactly right.
We built a one-question schema and two states that differ in a single field:
$ echo '{"user_id":"alice","amount":100}' > alice.json
$ echo '{"user_id":"bob","amount":100}' > bob.json
--- decide alice ---
{"answers":{"risky":{"value":true,…}},"cached":false,"fingerprint":"4e2c6b3363ac…"}
--- decide bob ---
{"answers":{"risky":{"value":true,…}},"cached":true, "fingerprint":"4e2c6b3363ac…"}
Identical fingerprints. Bob’s decision was never computed — "cached":true means it came from Alice’s row. Changing amount instead produces a different fingerprint, so the canonicaliser is working as designed; user_id is simply on the list of things it throws away.
We probed the list. Against a fixed base state, adding each field and watching the fingerprint:
| field added | fingerprint |
|---|---|
| (base) | 21dca6618083 |
user_id, id, uuid |
21dca6618083 |
session_id, request_id, trace_id |
21dca6618083 |
order_id |
21dca6618083 |
created_at, timestamp, updated_at |
21dca6618083 |
idempotency_key |
c80feff6a382 |
name |
8a2bd81a1ca2 |
amount |
8ad234e13558 |
email |
d84b9680fb4c |
Ten fields vanish. Three of them — user_id, order_id, session_id — are not volatile metadata; they are frequently the subject of the decision. “Is this user allowed to do this” and “should this order be held” are the questions people cache.
The project advertises the behaviour. jevcache demo:
ticket T-1001 decide() -> "billing" (0.90) routed to the model
ticket T-2087 decide() -> "billing" (0.90) cache HIT · 0ms · $0
a different ticket id, but the same decision — the volatile id was redacted before hashing.
For that example it is defensible: two tickets with the same text should route the same way, and the ticket number is noise. The trouble is that one rule covers user_id too, and there the identifier is the signal. Nothing warns you, nothing lets you pin a field, and the answer arrives flagged as a hit.
The README’s claim is narrower than it reads. “PII … and volatile fields (ids, timestamps) never enter the key” is true and is about the key. It is not a statement about what gets sent or stored, and it is easy to read as one.
~/.jevcache/ledger.log records every decision with a state_preview holding the raw state. We passed a state with four planted values and then grepped the ledger:
| planted value | in the ledger |
|---|---|
email: a@b.com |
masked |
ssn: 555-12-3456 |
masked |
authorization: Bearer SUPERSECRET |
present, plaintext |
password: hunter2hunter2 |
present, plaintext |
The masker is pattern-based — emails, phone numbers, long digit runs — so it catches the shapes it knows and passes everything else through. A bearer token and a password have no distinctive shape, so they land in the file intact. The file is mode 644, readable by every account on the machine.
This is the reading of the README that matters. “PII … never enter the key” is a claim about the key, and it is true. It is not a claim about the ledger, and the ledger is where your state actually comes to rest.
README.md:122 has a ## License heading, under which it says jevcache is “free to use”. The repository contains no LICENSE file and GitHub’s API reports license: null.
“Free to use” is a sentiment, not a grant. With no licence, default copyright applies and nobody has permission to redistribute the binary or ship it in a product. For a tool whose whole pitch is dropping into someone’s production decision path, that is the first thing to fix, and it costs one file.
Three commits. README.md and og.png. The product is a prebuilt binary distributed through GitHub Releases — the SHA-256 matches the published checksum, which is good practice, and we verified it. But nothing here can be read, audited, forked or patched, and everything above we had to establish by black-box probing.
--help also lists a subsystem the README does not mention:
jevcache market | usage | earnings | wallet [deposit <micros>]
The README’s roadmap says “Next: … per-recall pricing so publishers can charge”. It has shipped.
hit is backwards. A miss returns "cached":false,"hit":true; a hit returns "cached":true,"hit":false. cached is the field to trust.
jevcache add merges a cache file or URL with no signature and no provenance check, and the README’s only defence is “A bundle is plain JSON — inspect it before you add it”. Because identifiers are stripped, fingerprints are predictable, which makes a bundle that asserts a chosen answer for a chosen state easier to construct than it should be.
One thing the project gets right and deserves credit for: publish really does export fingerprints and answers only. We checked the bundle — no state, no previews. Whatever leaks locally stays local.
48 stars, three commits, no source, no licence, no tests, no CI, one open issue. The idea deserves a real implementation; this is a landing page with a binary attached.
We’ve reported the licence and the identifier stripping, and asked whether the source is coming. If you want decision caching today, the pattern is a dozen lines around your own client, and you get to decide yourself which fields identify the subject. Compare jevcal, which caches with its source in the open.
See how it compares with other tools in Best Jev tools, tested hands-on.
Review updated Sep 20, 2026. Numbers quoted from the project are its author's own; we don't publish our own measurements of Jev.
Parcha-ai/agentrun
A workflow DSL for agents with a Jev package for the steps that are decisions rather than generation.
osolmaz/switch
TypeScript framework for decision-model harnesses: your program offers a short list of next steps and the model picks one at a time until it can answer, with chess, wikirace and rubric-judge examples run on Jev.
disler/ten-levels-of-jev
Thirty worked uses arranged in ten levels, from one if statement to an agent that reaches for Jev itself, with a video walkthrough.
New Jev releases, pricing changes, and the best new projects, once a week. No spam; unsubscribe anytime.
Powered by Buttondown. See our privacy policy.