Browse
Core Concepts
Reasoning
Memory & Retrieval
Agent Types
Design Patterns
Training & Alignment
Frameworks
Tools
Safety
Meta
Browse
Core Concepts
Reasoning
Memory & Retrieval
Agent Types
Design Patterns
Training & Alignment
Frameworks
Tools
Safety
Meta
ChemCrow is an LLM-powered chemistry agent introduced by Bran et al. (2023) that augments GPT-4 with 18 expert-designed chemistry tools to autonomously perform tasks in organic synthesis, drug discovery, and materials design1). With 795 citations, it demonstrates that domain-specific tool augmentation enables LLMs to bridge the gap between computational and experimental chemistry, including executing synthesis on robotic platforms.
ChemCrow integrates tools across four categories:
ChemCrow employs the ReAct framework for iterative reasoning2). At each step $t$, the agent generates:
$$a_t = \text{LLM}(\text{Thought}_t, \text{Action}_t, \text{Input}_t \mid h_{<t})$$
where $h_{<t}$ is the history of previous thought-action-observation triples. The agent selects from the 18 tools based on the current reasoning state and observation feedback.
# Simplified ChemCrow agent with tool selection TOOLS = { "Name2SMILES": lambda name: pubchem_lookup(name, "smiles"), "RXNPredict": lambda rxn: rxn4chemistry_predict(rxn), "RXNPlanner": lambda target: rxn4chemistry_plan(target), "ChemicalWeaponCheck": lambda cas: check_cw_database(cas), "ExplosiveCheck": lambda smiles: check_explosive(smiles), "Similarity": lambda pair: tanimoto_similarity(*pair), "FuncGroups": lambda smiles: identify_groups(smiles), } def chemcrow_run(query, llm, max_steps=15): history = [] for step in range(max_steps): thought, action, action_input = llm.reason(query, history) # Safety gate: always check before synthesis if action in ("RXNPlanner", "RXNPredict"): smiles = TOOLS["Name2SMILES"](action_input) if not TOOLS["ChemicalWeaponCheck"](smiles): return "Halted: safety violation detected" if not TOOLS["ExplosiveCheck"](smiles): return "Halted: explosive compound detected" observation = TOOLSaction(action_input) history.append((thought, action, observation)) if is_final_answer(thought): return compile_answer(history)