Emission Factors in LangChain Agents
An AI agent asked for an emission factor will usually answer. Whether it answers correctly is a different question, and we measured it: across 467 questions, five frontier models were right about 46% of the time, and in up to 59% of answers they named the correct publisher while giving the wrong number. Given a lookup tool, the same models reached 99–100%. langchain-greencalculus is that lookup tool. It installs in one line, works before you sign up for anything, and every value it returns carries the exact place in the publisher’s own document it came from.
pip install langchain-greencalculus gives your agent three tools: search the corpus in plain English, look up a factor by key, and calculate emissions with an audit trail. No API key is needed for search and lookup — the corpus is open to read.
Install and first call
pip install langchain-greencalculus
No signup, no key, no configuration:
from langchain_greencalculus import EmissionFactorLookup
print(EmissionFactorLookup().invoke({"key": "grid.gbr.electricity.location_based"}))
0.13096 kg CO2e per kWh
key: grid.gbr.electricity.location_based
citation: UK grid electricity — location-based (generation). UK Government GHG
Conversion Factors 2026 — Department for Energy Security and Net Zero (DESNZ),
cell 'UK electricity'!E25, retrieved 2026-06-18. via GreenCalculus data version
2026.189. https://verify.greencalculus.com/grid.gbr.electricity.location_based@2026.189
The cell reference is the point. 'UK electricity'!E25 is a row in a government workbook, and the proof link opens without an account. A number your agent produces can be traced to a primary document rather than to something it read once.
The package is listed in LangChain’s own integration documentation: as GreenCalculusToolkit in the Python tools directory, and as a provider.
The three tools
| Tool | Needs a key | What it does |
|---|---|---|
EmissionFactorSearch | No | Plain-English search. Returns candidate keys with values and publishers. |
EmissionFactorLookup | No | One factor by exact key, with its citation. as_of version pinning needs a key. |
EmissionsCalculator | Optional | Quantity × factor. With a key you get a server-side audit trail; without one it multiplies locally and says so. |
Search and lookup work with no credentials at all, because the corpus browse route is open. The package’s CI runs with no API key configured for exactly this reason: a green build proves the no-key path works for someone who has never heard of us, rather than mocking it into looking like it does.
A working agent
from langchain.agents import create_agent
from langchain_greencalculus import (
EmissionFactorLookup, EmissionFactorSearch, EmissionsCalculator,
)
tools = [EmissionFactorSearch(), EmissionFactorLookup(), EmissionsCalculator()]
agent = create_agent("anthropic:claude-sonnet-5", tools=tools)
agent.invoke({"messages": [{"role": "user", "content":
"We used 12,000 kWh of UK grid electricity. What are the emissions, and cite the source."}]})
With a key set, the calculator returns the working as well as the answer:
1571.52 kg CO2e
working: 12000 kWh × 0.13096 (kg CO2e per kWh) = 1571.52 kg CO2e
scope: scope2
citation: UK grid electricity — location-based (generation). Source: UK Government
GHG Conversion Factors 2026 (DESNZ), cell 'UK electricity'!E25. Licence: Open
Government Licence v3.0.
note: UK publishes a single location-based factor. No separate market-based
residual mix in DESNZ.
data version: 2026.189 receipt: gcr_17ae9bd290d7…
proof: https://verify.greencalculus.com/grid.gbr.electricity.location_based@2026.189
The receipt is a hash over the response. Recompute it from the same inputs at the same data version and you get the same id, which is what makes a filed number defensible a year later.
Why the tool descriptions matter
For an agent tool, the description is the interface. It is the text the model reads to decide when to call the tool and what to pass. Wrapping an HTTP endpoint is easy; the descriptions are where the domain knowledge has to live.
Here is the problem they exist to prevent. Ask for “UK grid electricity” and there are three defensible answers:
| Key | Value | What it is |
|---|---|---|
grid.gbr.electricity.location_based | 0.13096 | Generation, location-based — the default for Scope 2 |
grid.gbr.electricity.lifecycle_intensity | 0.21741 | Lifecycle intensity, including upstream |
grid.gbr.electricity.residual_mix | 0.28064 | Residual mix, for market-based reporting |
Pick the wrong one and nothing looks broken. The number is plausible, the units are right, and the answer is wrong by more than a factor of two. So the search tool’s description names the distinctions explicitly — location-based versus market-based, well-to-tank versus combustion — and tells the model to ask rather than choose silently when the user has not said which they need.
The package has tests that assert the descriptions still tell the model to prefer the tool over recall, to repeat the citation, and to warn about the basis trap. A future edit cannot quietly strip the expertise out without turning the build red.
What an API key adds
A free key is 1,000 calls a month with no card. It adds three things:
- Version pinning.
as_ofserves a factor as it stood at an archived data version, so a figure in a filed report reproduces exactly later. - Traced calculations. The server returns the working, the GHG Protocol scope mapping, and a reproducibility receipt.
- Higher limits.
Set GREENCALCULUS_API_KEY in the environment and the tools pick it up, or pass api_key= explicitly.
The measurement behind this
The claim that a lookup tool is worth adding is ours, so we measured it rather than asserting it, and published the parts that reflect badly on us.
Unaided accuracy ran from 41.9% to 65.2% depending on the model. The more useful figure is the failure mode: in 31.6% to 58.8% of answers the model named the correct publisher and still gave the wrong number. A wrong value with no source gets caught in review. A wrong value wearing DEFRA’s name does not.
In a paired run on the same questions, connecting a sourced lookup took Claude Opus 5 from 37.1% to 98.7% and GPT-5.5 from 50.0% to 100.0%, at one to two tool calls per question.
Everything is reproducible: the questions, the verbatim text of every model answer and the scoring code are published on GitHub and HuggingFace, and archived with a DOI (10.5281/zenodo.22692277). The scorer’s own six bugs are logged too — four of them were understating the result.
Read the full study: how accurate is AI on emission factors, and where it is reliable, category by category.
Frequently asked questions
Not for search or lookup. The corpus browse route is open, so pip install langchain-greencalculus and a first call work with no signup. A free key adds version pinning, server-side traced calculations and higher limits.
Because it is wrong about half the time, and wrong in the way hardest to catch. Across 467 questions, five frontier models were within 10% of the published value 41.9%–65.2% of the time, and in up to 59% of answers they cited the correct publisher beside an incorrect number. Given a lookup tool the same models reached 99–100%.
Yes. The tools are standard BaseTool subclasses, so they work anywhere LangChain tools do, including LangGraph. Async is implemented properly — the synchronous HTTP call is offloaded to a thread rather than blocking the event loop, so one lookup does not stall the rest of an agent.
The tool descriptions already warn it. “UK grid electricity” has three defensible answers — 0.13096 location-based, 0.21741 lifecycle, 0.28064 residual mix — and the search tool tells the model to ask which basis you need rather than choose silently. If you know the basis, pass the exact key to EmissionFactorLookup and skip the ambiguity.
With a key, yes. Pass as_of with a data version and the factor is served as it stood then, from the reproducibility archive. Calculations return a receipt hash which recomputes from the same inputs at the same version. Without a key you get the current value, which moves when publishers update.
It runs LangChain’s own conformance suite — ToolsUnitTests and ToolsIntegrationTests from langchain-tests — across all three tools, sync and async, on Python 3.9 to 3.13. A weekly job also tests against the latest langchain-core, so an upstream change that would break the package surfaces before a user hits it. Source: github.com/greencalculus/langchain-greencalculus. It is also listed in LangChain’s own integration documentation, in the Python tools directory and as a provider.