Deliberate comparison

Fieldwork and Google LangExtract

Grounded extraction that continues through review, recheck, and proof.

If the job stops at “find structured fields in text,” these projects occupy similar ground, and LangExtract is the more mature tool on it. Fieldwork is for the next question: a person has to sign off on the value, and someone will ask six months from now who signed off and what the source said at the time.

Fieldwork is a free Apache-2.0 command-line app for Node 22 (npm install @kontourai/fieldwork), currently v0.3.1, and it runs without a credential or a network call. LangExtract is a Python library. If you need a Python import, that is a real blocker and this page will not solve it. Every upstream claim below links to public commit 0dff5479; live figures such as the star count were checked on 25 July 2026. This compares documented and demonstrated behavior. It is not a benchmark.

The shared ground

The overlap is real: source-grounded extraction.

Google LangExtract and Fieldwork both make the same deliberate move away from untraceable free-form answers: you describe a structure, the extracted value is tied to the text it came from, and a person can go and look. That much is genuinely equivalent.

What Fieldwork adds is the loop around it — propose the value, inspect the source, record the decision, recheck when the source changes, export the result with its evidence attached. That is a claim about workflow, not a claim that one model or provider is more accurate than another.

Where LangExtract wins

Four reasons to close this tab and use LangExtract.

A comparison page written by one side is worth reading only if it is willing to lose rows. These are the ones we lose.

It is Python, and it is much further along

pip install langextract, five lines of code, and you are extracting. LangExtract is at v1.6.0 with more than 37,800 GitHub stars. Fieldwork is a Node 22 command-line app at v0.3.1. If your work lives in Python, that probably settles it before you read another word.

Pinned quick start ↗

Long documents are tunable there, capped here

Both tools chunk. LangExtract exposes the controls — chunk size, parallel workers, repeat passes for recall — and its pinned README runs all 147,843 characters of Romeo and Juliet through them. Fieldwork chunks too, in fixed 12,000-character windows with 200-character overlap and a single pass, and exposes none of those controls. It also stops after 40 chunks: past roughly 472,000 prepared characters the rest of the document is not extracted and the run still reports success, and a source above 2 MiB is refused outright.

Pinned long-document example ↗

You can try it in a browser right now

A hosted demo runs grounded extraction with nothing installed. Fieldwork needs Node 22 and a terminal before you see anything at all.

LangExtract live demo ↗

More runtimes, published benchmarks, and something to cite

Gemini, Vertex AI, OpenAI, OpenAI-compatible endpoints and local Ollama models, batch modes for large jobs, a provider plugin system with a community registry, a benchmarks directory in the repository, and a Zenodo DOI for papers. Fieldwork has none of that.

Pinned benchmarks directory ↗

If any of those decides it for you, LangExtract is the right answer and nothing further down this page will change that.

What using it looks like

Two fields out of a contract, and an export that refuses.

A three-line synthetic vendor agreement, the example task that ships in the package, and no credential anywhere. The last command is the point of the whole product: nobody has reviewed these values yet, so there is nothing to export.

fieldwork v0.2.5 · vendor-obligations example · real output
# Node 22 · no API key, no network · install output omitted
npm install @kontourai/fieldwork

npx fieldwork run --task task.json --source vendor-agreement.txt --json
{"ok":true,"apiVersion":"fieldwork.kontourai.io/v1","kind":"FieldworkRunResult",
 "runDirectory":"…/.fieldwork/runs/run-bc32a8a21fef4afa",
 "runResource":"fieldwork-run:v1:vendor-obligations:bc32a8a21fef4afa","proposalCount":2}

npx fieldwork inspect .fieldwork/runs/run-bc32a8a21fef4afa --include-excerpts --output inspect.json --json
{"ok":true,"output":"inspect.json"}

jq -c '.spec.candidates[] | {field, excerpt, locator: "chars:\(.start)-\(.end)"}' inspect.json
{"field":"obligation","excerpt":"Obligation: Deliver the monthly security report","locator":"chars:27-74"}
{"field":"deadline","excerpt":"Deadline: 2027-03-31","locator":"chars:75-95"}

npx fieldwork export .fieldwork/runs/run-bc32a8a21fef4afa --output reviewed.json --json
{"ok":false,"error":{"code":"FIELDWORK_ERROR","message":"Export refused: unresolved-review-item, unresolved-review-item"}}

Verbatim output from @kontourai/[email protected] run on 25 July 2026, with two edits for length: the absolute runDirectory path is shortened to , and the first JSON response is wrapped across three lines. Nothing else was changed. Run identifiers are derived from the task and source, so on 0.2.5 the same inputs reproduce run-bc32a8a21fef4afa on your machine too. The bundled example changed in a later release, so a fresh install runs a different document and produces a different identifier — that is the mechanism working, not drift.

Then a person decides.

fieldwork open serves the run on a loopback address. The reviewer sees the proposed value next to the exact sentence it came from and either takes it or does not. The accept is sent to the local server, validated against the record it came from, and stored there — the browser is the interface, not the authority. After that, the export that just refused will succeed and will carry the excerpt, locator and decision with it.

The review record contract ↗
Fieldwork Grounded Review desktop view: a source inspector showing the renewal brief with each extracted value highlighted, above a Survey review workbench where two values are accepted and a contested renewal date still needs a decision.
Desktop snapshot from a local run of the published package, captured against v0.3.0 on 2026-07-26: source inspection above the review queue, accepted values decided on the local server, one contested date still open.

Capability map

A source-linked comparison, row by row.

Both columns link to the public source behind the claim. The upstream links all point at the same pinned commit, so you can check us rather than take our word for it.

ConcernGoogle LangExtractFieldworkPublic evidence
Core premiseSchema- and example-guided extraction of structured fields from unstructured text, with every value mapped back to its place in the source.The same starting point — a described structure, a proposed value, and the excerpt it came from. The difference is what happens next: the proposal goes into a review queue instead of being returned as the answer.
GroundingAligns each extracted span against the tokenized source itself, exact match first and an optional fuzzy fallback second, and records which of those it was. Anything it cannot place is returned with char_interval = None so you can filter it out.Checks that the excerpt appears verbatim in the prepared text, then derives the locator (chars:27-74) from that verified offset. There is no fuzzy tier: an excerpt that is not found exactly is rejected rather than approximated. LangExtract recovers more; Fieldwork never guesses. Both are defensible; neither is free.
Human reviewGenerates a self-contained interactive HTML file for reading thousands of extractions in their original context.A local review app where a person accepts or rejects each value. The decision is written and validated by the local server against the record it came from, so it outlives the browser tab that made it.
Rechecking a source laterOut of scope by design. LangExtract extracts and visualizes; it is not a monitoring tool and does not claim to be.Content-addressed snapshots make a run exactly replayable, and a later check compares the new proposals against the old ones. Evidence that was added, removed, moved or changed opens a new review round rather than quietly overwriting the old decision.
Reviewed outputWrites results as JSONL for downstream use, alongside the HTML view.Exports only after review is finished, and refuses when the review state is unresolved, stale, malformed, tampered or ungrounded. What comes out carries the excerpt, locator, decision and provenance with it.
Model runtimesGemini, Vertex AI, OpenAI, OpenAI-compatible endpoints and local models via Ollama, plus batch modes for large jobs and a plugin system with a community provider registry.Far fewer runtimes out of the box. What it adds is a capacity ceiling set before the run, ordered fallback between runtimes, and a portable receipt for every call stored with the run. None of that says anything about how good a model is at your task.

Fieldwork is one app you install once. Traverse, Survey and Lookout in the evidence column are libraries it depends on — not separate installs, and not paid add-ons. If you want the map of how those pieces fit together, it lives on the developers page.

What Fieldwork adds

What Fieldwork adds after a value is found.

01 / Review

A decision that outlives the tab

LangExtract’s HTML view is for looking; Fieldwork’s is for deciding. Each accept or reject is sent to the local server, checked against the record it came from, and stored with it.

Review record contract ↗

02 / Change

Sources move; rechecks notice

A recheck compares today’s proposals against the ones you already reviewed, and separates “the source changed” from “someone changed their mind,” so work reopens deliberately instead of silently.

Recheck contract ↗

03 / Export

An export that refuses

The export you saw fail above refuses on unresolved, stale, malformed, tampered or ungrounded review state. What it does emit carries its excerpts, locators and decisions with it.

Export contract ↗

Before you switch

Four things this page cannot tell you.

You cannot swap one for the other

LangExtract is a Python library you import. Fieldwork is a Node command-line app you run. Moving between them is a rewrite, not a config change — and there is no adapter that makes it one.

Nothing here says either one is more accurate

Locators, review records and runtime adapters are mechanics. They do not establish that one model, provider or system extracts better than another, and we have not run a head-to-head that would.

We make no claim about multipass recall

The pinned README describes multiple passes for higher recall. We have not measured that, so we neither confirm nor dispute the gain — we simply have nothing to say about it.

PDFs and scans need an adapter you supply

Fieldwork reviews PDF and OCR output with its page and table-cell context intact, but it ships no parser or OCR engine of its own. Without an adapter the run fails with a typed error, and having one proves nothing about extraction quality.

Everything above is checked against public repositories and frozen test fixtures, so the mechanics are real and you can re-run them. None of it tells you how well a given model will do on your documents. That would take a test set built for your task by someone with no stake in the answer, and neither project has published one for the other.

Choose the workflow you need

So which one?

Pick LangExtract if…

…you work in Python, your documents run past a few hundred thousand characters, you want to pip install and be extracting inside ten minutes, you need a provider it already supports, or you are publishing research and need something citable.

Pick Fieldwork if…

…a person has to sign off before a value becomes real data, and you will be asked later who signed off and what the source said at the time. Vendor renewals, policy tables, public records, grant eligibility — work where “the model said so” is not an acceptable answer.

Plenty of teams should use LangExtract for the extraction and put a review loop like Fieldwork’s downstream of it. These are not mutually exclusive, and we would rather say so than pretend otherwise.