Materials Decoded Lab · Artifact 02
Screen a battery cathode the way a materials scientist would
Give it a plain-language target, "a Li-ion cathode above 3.5V that doesn't use cobalt", and it searches Materials Project's real, DFT-computed electrode data, proposes new candidates by isovalent substitution when nothing existing fits, screens those proposals with a local ML interatomic potential, checks arXiv for whether anyone has actually studied them, and loops back for another round if the results are too thin. Answering from a database with no judgment about whether the answer is actually good is exactly what this is built to avoid.
5
real fields verified before use
checked against the installed mp-api client, not assumed from docs
2
real bugs a live run caught
a substitution-chemistry bug and an arXiv precision bug, see below
16
passing tests
including real integration tests against the live MLIP and arXiv
1
hard iteration cap
a deterministic guardrail the critic LLM can never override
Why this problem, why this architecture
The dominant pattern in AI-driven materials discovery right now, GNoME, A-Lab, the current wave of universal ML potentials, is generate → screen → validate → refine, not a single lookup. That loop is why this reaches for LangGraph instead of a simpler linear pipeline: a graph can route back to an earlier step based on what a later one decided, which is what an actual refine loop needs and a straight pipeline cannot express.
How it's wired
Two real conditional edges, not one straight line. After the database search: if Materials Project alone already has enough DFT-verified candidates, the substitution and relaxation steps never run at all, there is no reason to spend a relaxation on a composition that already has real ground-truth data. After the critic step: the actual cycle. An LLM judges whether the candidate set is good enough; if not, and a retry budget remains, the graph loops back with the previously tried elements excluded, so a retry explores new chemistry instead of regenerating the same rejected candidates. A hard, deterministic iteration cap always wins over the LLM's preference, so a model that keeps asking for "one more round" can never turn this into an unbounded loop.
| Step | Kind | Job |
|---|---|---|
intake | LLM | Plain language → structured constraints (working ion, element excludes, voltage/capacity bounds) |
db_search | tool | Queries Materials Project's real electrode data directly |
candidate_proposer | rule-based | Isovalent element substitution, deliberately not generative, every proposal traces to one explainable rule |
mlip_screener | tool | Relaxes proposed structures with a local universal ML potential |
literature_grounder | tool | Searches arXiv, scoped to materials-science categories |
critic | LLM | Judges whether the candidate set actually answers the request |
report_writer | LLM | Turns the structured data into a ranked, evidenced report, never inventing an input |
A real run, not a mockup
Asked to find a Li-ion cathode above 3.5V with no cobalt, the agent returned five real, Materials Project-verified candidates and ranked them honestly rather than just listing them:
Two of the other four candidates were marked not recommended in the same run, LiP4WO12 and LiMn2(PO4)2, both real, DFT-verified, and both rejected outright for impractically low capacity (52.9 and 29.1 mAh/g). A system that only ever says yes is not screening anything, and the honest "no" is the part worth showing.
What was actually verified before being written, and two real bugs it caught
Every tool here was run against something real before the graph was built around it, not written from documentation and assumed to work.
- Materials Project's electrode fields were confirmed real by introspecting the installed client's own schema, not assumed from docs. One field the schema advertises,
battery_id, turned out not to actually be populated; the tool was written to build its own id from a field confirmed present instead of trusting one that couldn't be verified. - A real chemistry bug: the first substitution rule used "same periodic group" for every element, correct for main-group elements but wrong for transition metals, it missed the textbook Fe → Mn → Ni olivine cathode family entirely, since those sit in the same period, not the same group. Fixed to branch on block, and locked in by a regression test.
- A real API precision bug: arXiv's plain keyword search for "cathode" returns hollow-cathode plasma-physics papers ahead of battery materials papers, an entirely different subfield. Fixed by scoping every query to the materials-science category by default.
- MACE, the state-of-the-art universal potential this was originally scoped around, failed to install (a C-compiler dependency broke on the build machine). Rather than fake the result, it was swapped for
matgl's M3GNet, pure PyTorch, and confirmed relaxing a real structure end to end before the swap was accepted.
What this is not
- The substitution rule covers a deliberately scoped, explainable element pool, not a general materials generative model.
- The ML potential estimates relative stability fast; it is not a substitute for full DFT.
- Literature grounding is coverage, not proof: a formula with strong arXiv hits is better evidenced, not automatically better chemistry.
The live demo needs your own Anthropic or OpenAI key. It runs on a shared free server, so a shared LLM key would mean one visitor's queries bill another's account, the same reason the Trust Benchmark's live audit above asks for your own Materials Project key rather than reusing mine. Nothing is stored: your key is used for one run and forgotten. Get an Anthropic key (recommended) atconsole.anthropic.com, or an OpenAI key atplatform.openai.com.