OptionalResearchVersion 1.0.0

Drug Discovery with Hermes Agent: ChEMBL, Drug-Likeness, and Safety

Drug discovery: ChEMBL search, drug-likeness, interactions.

Written by Neura Market from the official Hermes Agent documentation for Drug Discovery. Commands, paths, and version numbers are reproduced from the source unchanged.

Read the official documentation

This skill turns Hermes Agent into a pharmaceutical research assistant. It queries public chemistry and pharmacology databases to find bioactive compounds, assess drug-likeness, check drug interactions, and explore gene-disease associations. Reach for it when you need quick, reproducible answers about a compound's properties or a target's known ligands, without setting up a local cheminformatics stack.

What it does

The skill bundles five command-line workflows that hit free, public APIs. You get a ChEMBL search for targets and bioactivity data, a Lipinski and Veber rule checker powered by PubChem, an OpenFDA lookup for drug interactions and adverse events, a PubChem compound resolver, and an OpenTargets query for gene-disease links. Each workflow is a shell script that takes a query argument, calls the API with curl, and pipes the JSON through Python for a readable summary. No API keys, no authentication, no local database. The output is designed for a scientist who wants raw numbers and rule-based verdicts, not a web page.

Before you start

  • The skill is optional and installed on demand. Its path is optional-skills/research/drug-discovery, version 1.0.0, authored by bennytimz, MIT licensed.
  • It runs on Linux, macOS, and Windows, so it is portable across typical development machines.
  • You need curl and python available on the command line. The Python calls use only the standard library (urllib.parse, json, sys), so no extra packages are required.
  • All APIs are free and public, requiring no authentication. That means you can start using the skill immediately after installation.
  • Be aware of ChEMBL rate limits: the source advises adding sleep 1 between batch requests to avoid throttling.

1. Bioactive Compound Search (ChEMBL)

ChEMBL is the world's largest open bioactivity database. This workflow finds targets by name, retrieves bioactivity data for a target, and looks up a specific molecule's properties.

Find a target by name

Pass a target name like "EGFR", "COX-2", or "ACE" as the first argument. The script URL-encodes it, queries ChEMBL's target search endpoint, and prints the top five matches with their ChEMBL IDs, preferred names, and target types.

# Search compounds by target name (e.g. "EGFR", "COX-2", "ACE")
TARGET="$1"
ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$TARGET")
curl -s "https://www.ebi.ac.uk/chembl/api/data/target/search?q=${ENCODED}&format=json" \
  | python -c "
import json,sys
data=json.load(sys.stdin)
targets=data.get('targets',[])[:5]
for t in targets:
    print(f\"ChEMBL ID : {t.get('target_chembl_id')}\")
    print(f\"Name      : {t.get('pref_name')}\")
    print(f\"Type      : {t.get('target_type')}\")
    print()
"

You will see a list of up to five targets. The ChEMBL ID is what you need for the next step.

Get bioactivity data for a target

Use the ChEMBL ID from the previous step, for example CHEMBL203. The script fetches activities with a pChEMBL value of 6 or higher, limited to 10 results, and prints the molecule ID, standard type, value, units, and pChEMBL.

# Get bioactivity data for a ChEMBL target ID
TARGET_ID="$1"   # e.g. CHEMBL203
curl -s "https://www.ebi.ac.uk/chembl/api/data/activity?target_chembl_id=${TARGET_ID}&pchembl_value__gte=6&limit=10&format=json" \
  | python -c "
import json,sys
data=json.load(sys.stdin)
acts=data.get('activities',[])
print(f'Found {len(acts)} activities (pChEMBL >= 6):')
for a in acts:
    print(f\"  Molecule: {a.get('molecule_chembl_id')}  |  {a.get('standard_type')}: {a.get('standard_value')} {a.get('standard_units')}  |  pChEMBL: {a.get('pchembl_value')}\")
"

This gives you a quick read on which molecules are active against your target and how potent they are.

Look up a specific molecule

If you already have a ChEMBL molecule ID, for example CHEMBL25 (aspirin), this script prints the name, canonical SMILES, molecular weight, LogP, hydrogen bond donors and acceptors, TPSA, Lipinski violations, and QED score.

# Look up a specific molecule by ChEMBL ID
MOL_ID="$1"   # e.g. CHEMBL25 (aspirin)
curl -s "https://www.ebi.ac.uk/chembl/api/data/molecule/${MOL_ID}?format=json" \
  | python -c "
import json,sys
m=json.load(sys.stdin)
props=m.get('molecule_properties',{}) or {}
print(f\"Name       : {m.get('pref_name','N/A')}\")
print(f\"SMILES     : {m.get('molecule_structures',{}).get('canonical_smiles','N/A') if m.get('molecule_structures') else 'N/A'}\")
print(f\"MW         : {props.get('full_mwt','N/A')} Da\")
print(f\"LogP       : {props.get('alogp','N/A')}\")
print(f\"HBD        : {props.get('hbd','N/A')}\")
print(f\"HBA        : {props.get('hba','N/A')}\")
print(f\"TPSA       : {props.get('psa','N/A')} Ų\")
print(f\"Ro5 violations: {props.get('num_ro5_violations','N/A')}\")
print(f\"QED        : {props.get('qed_weighted','N/A')}\")
"

This is a fast way to get the key physicochemical properties for a known compound.

2. Drug-Likeness Calculation (Lipinski Ro5 + Veber)

This workflow assesses any molecule against established oral bioavailability rules using PubChem's free property API. No RDKit installation is needed. Pass a compound name as the first argument, and the script fetches molecular weight, XLogP, hydrogen bond donors and acceptors, rotatable bond count, TPSA, and InChIKey, then evaluates Lipinski's Rule of Five and Veber's rules.

COMPOUND="$1"
ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$COMPOUND")
curl -s "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/${ENCODED}/property/MolecularWeight,XLogP,HBondDonorCount,HBondAcceptorCount,RotatableBondCount,TPSA,InChIKey/JSON" \
  | python -c "
import json,sys
data=json.load(sys.stdin)
props=data['PropertyTable']['Properties'][0]
mw   = float(props.get('MolecularWeight', 0))
logp = float(props.get('XLogP', 0))
hbd  = int(props.get('HBondDonorCount', 0))
hba  = int(props.get('HBondAcceptorCount', 0))
rot  = int(props.get('RotatableBondCount', 0))
tpsa = float(props.get('TPSA', 0))
print('=== Lipinski Rule of Five (Ro5) ===')
print(f'  MW   {mw:.1f} Da    {\"✓\" if mw<=500 else \"✗ VIOLATION (>500)\"}')
print(f'  LogP {logp:.2f}       {\"✓\" if logp<=5 else \"✗ VIOLATION (>5)\"}')
print(f'  HBD  {hbd}           {\"✓\" if hbd<=5 else \"✗ VIOLATION (>5)\"}')
print(f'  HBA  {hba}           {\"✓\" if hba<=10 else \"✗ VIOLATION (>10)\"}')
viol = sum([mw>500, logp>5, hbd>5, hba>10])
print(f'  Violations: {viol}/4  {\"→ Likely orally bioavailable\" if viol<=1 else \"→ Poor oral bioavailability predicted\"}')
print()
print('=== Veber Oral Bioavailability Rules ===')
print(f'  TPSA         {tpsa:.1f} Ų   {\"✓\" if tpsa<=140 else \"✗ VIOLATION (>140)\"}')
print(f'  Rot. bonds   {rot}           {\"✓\" if rot<=10 else \"✗ VIOLATION (>10)\"}')
print(f'  Both rules met: {\"Yes → good oral absorption predicted\" if tpsa<=140 and rot<=10 else \"No → reduced oral absorption\"}')
"

The output shows a clear pass/fail for each criterion, a violation count, and a verdict on oral bioavailability. This is useful for triaging compound libraries or checking a single hit from a ChEMBL search.

3. Drug Interaction & Safety Lookup (OpenFDA)

The OpenFDA API provides access to FDA drug labels and adverse event reports. This workflow checks for drug interactions and lists top reported adverse events.

Drug interactions from FDA labels

Pass a drug name as the first argument. The script searches FDA labels for interaction data and prints the brand name, generic name, and the first 800 characters of the interaction section for up to two results.

DRUG="$1"
ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$DRUG")
curl -s "https://api.fda.gov/drug/label.json?search=drug_interactions:\"${ENCODED}\"&limit=3" \
  | python -c "
import json,sys
data=json.load(sys.stdin)
results=data.get('results',[])
if not results:
    print('No interaction data found in FDA labels.')
    sys.exit()
for r in results[:2]:
    brand=r.get('openfda',{}).get('brand_name',['Unknown'])[0]
    generic=r.get('openfda',{}).get('generic_name',['Unknown'])[0]
    interactions=r.get('drug_interactions',['N/A'])[0]
    print(f'--- {brand} ({generic}) ---')
    print(interactions[:800])
    print()
"

If no interaction data is found, the script prints a message and exits. Otherwise you get the relevant label text, truncated to 800 characters for readability.

Adverse event reports

This script queries the FDA adverse event reporting system for a drug and counts the top 10 reported reactions by MedDRA term.

DRUG="$1"
ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$DRUG")
curl -s "https://api.fda.gov/drug/event.json?search=patient.drug.medicinalproduct:\"${ENCODED}\"&count=patient.reaction.reactionmeddrapt.exact&limit=10" \
  | python -c "
import json,sys
data=json.load(sys.stdin)
results=data.get('results',[])
if not results:
    print('No adverse event data found.')
    sys.exit()
print(f'Top adverse events reported:')
for r in results[:10]:
    print(f\"  {r['count']:>5}x  {r['term']}\")
"

The output is a simple frequency count, which gives you a quick sense of the most common reported issues. Remember that these are reports, not proven causation.

4. PubChem Compound Search

This workflow resolves a compound name to a PubChem CID and then fetches its isomeric SMILES, InChIKey, and IUPAC name.

COMPOUND="$1"
ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$COMPOUND")
CID=$(curl -s "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/${ENCODED}/cids/TXT" | head -1 | tr -d '[:space:]')
echo "PubChem CID: $CID"
curl -s "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/${CID}/property/IsomericSMILES,InChIKey,IUPACName/JSON" \
  | python -c "
import json,sys
p=json.load(sys.stdin)['PropertyTable']['Properties'][0]
print(f\"IUPAC Name : {p.get('IUPACName','N/A')}\")
print(f\"SMILES     : {p.get('IsomericSMILES','N/A')}\")
print(f\"InChIKey   : {p.get('InChIKey','N/A')}\")
"

This is handy when you have a common name and need a canonical structure representation for downstream tools or for cross-referencing with ChEMBL.

5. Target & Disease Literature (OpenTargets)

OpenTargets links genes to diseases. This workflow takes a gene symbol, queries the OpenTargets GraphQL API, and prints the approved symbol, approved name, and the top associated diseases with their association scores.

GENE="$1"
curl -s -X POST "https://api.platform.opentargets.org/api/v4/graphql" \
  -H "Content-Type: application/json" \
  -d "{\"query\":\"{ search(queryString: \\\"${GENE}\\\", entityNames: [\\\"target\\\"], page: {index: 0, size: 1}) { hits { id score object { ... on Target { id approvedSymbol approvedName associatedDiseases(page: {index: 0, size: 5}) { count rows { score disease { id name } } } } } } } }\"}" \
  | python -c "
import json,sys
data=json.load(sys.stdin)
hits=data.get('data',{}).get('search',{}).get('hits',[])
if not hits:
    print('Target not found.')
    sys.exit()
obj=hits[0]['object']
print(f\"Target: {obj.get('approvedSymbol')} — {obj.get('approvedName')}\")
assoc=obj.get('associatedDiseases',{})
print(f\"Associated with {assoc.get('count',0)} diseases. Top associations:\")
for row in assoc.get('rows',[]):
    print(f\"  Score {row['score']:.3f}  |  {row['disease']['name']}\")
"

This is useful for prioritizing targets based on disease association strength, or for quickly surveying the disease landscape around a gene of interest.

Reasoning Guidelines

When analysing drug-likeness or molecular properties, the skill's instructions ask you to follow a structured approach:

  1. State raw values first - MW, LogP, HBD, HBA, TPSA, RotBonds
  2. Apply rule sets - Ro5 (Lipinski), Veber, Ghose filter where relevant
  3. Flag liabilities - metabolic hotspots, hERG risk, high TPSA for CNS penetration
  4. Suggest optimizations - bioisosteric replacements, prodrug strategies, ring truncation
  5. Cite the source API - ChEMBL, PubChem, OpenFDA, or OpenTargets

For ADMET questions, reason through Absorption, Distribution, Metabolism, Excretion, Toxicity systematically. The source points to references/ADMET_REFERENCE.md for detailed guidance, which should be available in the skill's directory.

When not to use it

This skill is not a substitute for clinical judgment. The source explicitly warns that FDA data reflects reported adverse events, not necessarily causation, and that you should always recommend consulting a licensed pharmacist or physician for clinical decisions. It is also not designed for high-throughput screening of thousands of compounds; the ChEMBL rate limits and the sequential nature of the scripts make that impractical. For large-scale virtual screening, you would want a local cheminformatics toolkit like RDKit.

Limits and gotchas

  • All APIs are free and public, but they have rate limits. The source specifically mentions ChEMBL: add sleep 1 between batch requests.
  • The scripts assume the APIs return the expected JSON structure. If an API changes its schema or a compound is not found, the Python parsing may fail with a traceback rather than a friendly message.
  • The OpenFDA interaction search uses a quoted query string; if the drug name contains special characters, the URL encoding handles it, but the search may still return no results if the label does not explicitly mention interactions.
  • The adverse event counts are raw report counts, not normalized by patient population or time, so they are only a rough signal.
  • The OpenTargets GraphQL query is fixed to return one target and five associated diseases; you cannot adjust these parameters without editing the script.

What pairs with this

The source page does not list related skills, but the skill itself references references/ADMET_REFERENCE.md for deeper ADMET guidance. In a broader research workflow, this skill complements other research skills in the Hermes Agent optional skills collection, such as literature search or data analysis skills, by providing structured chemical and pharmacological data that can feed into a larger report or decision process.

More Research skills