
Tooluniverse Drug Synergy
- 78 installs
- 1.6k repo stars
- Updated August 4, 2026
- mims-harvard/tooluniverse
Helps with ai & agent building tasks.
About
tooluniverse-drug-synergy is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- tooluniverse-drug-synergy
- AI & Agent Building
- AI-coding skill
Tooluniverse Drug Synergy by the numbers
- 78 all-time installs (skills.sh)
- +5 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #5,339 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mims-harvard/tooluniverse --skill tooluniverse-drug-synergyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 78 |
|---|---|
| repo stars | ★ 1.6k |
| Last updated | August 4, 2026 |
| Repository | mims-harvard/tooluniverse ↗ |
What it does
Helps with ai & agent building tasks.
Files
Drug-Combination Synergy Analysis
Decide whether a two-drug combination does more than expected (synergy), exactly as expected (additivity), or less (antagonism) — and pick the right reference model for the data you have.
"Synergy" only means something relative to a null model of additivity, and the models define additivity differently — so the first decision is which model, driven by what data you measured.
Step 0 — Pick the model by the data you have
| You measured… | Use model | Tool | Input |
|---|---|---|---|
| Single effects of A, B, and A+B at one dose pair | Bliss | DrugSynergy_calculate_bliss | effect_a, effect_b, effect_combination (each a fraction 0–1) |
| Effects of A, B, A+B across several dose points | HSA | DrugSynergy_calculate_hsa | effects_a, effects_b, effects_combo (arrays) |
| Single-agent dose-response curves + one combination point | Loewe | DrugSynergy_calculate_loewe | doses_a_single/effects_a_single, doses_b_single/effects_b_single, dose_a_combo, dose_b_combo, effect_combo |
| Single-agent dose-response + combo point, want Chou-Talalay CI | Combination Index | DrugSynergy_calculate_ci | same as Loewe + assumption |
| A full dose × dose viability matrix | ZIP | DrugSynergy_calculate_zip | doses_a, doses_b, viability_matrix (% , 0–100) |
Effects must be on a consistent inhibition scale. Bliss/HSA/Loewe expect fractional inhibition0–1(0 = no effect, 1 = complete kill). If your data is % viability, convert:inhibition = 1 − viability/100. ZIP takes the viability matrix in % directly. Mixing scales is the most common error.
Step 1 — What each model's "additivity" means
| Model | Null (additive) expectation | Best when |
|---|---|---|
| Bliss independence | drugs act independently: E_exp = E_a + E_b − E_a·E_b | different mechanisms; quick single-point screen |
| HSA (highest single agent) | combo should beat the better single agent: E_exp = max(E_a, E_b) | conservative "does it beat monotherapy?" question |
| Loewe additivity | a drug combined with itself = additive (dose equivalence) | same/similar mechanism; needs dose-response |
| ZIP | combines Bliss + Loewe; potency shift of one drug's curve by the other | dose-matrix screens (the SynergyFinder default) |
| Chou-Talalay CI | CI<1 synergy, =1 additive, >1 antagonism (median-effect) | classic isobologram-style analysis with dose-response |
There is no single "correct" model — state which one you used. Bliss and Loewe genuinely disagree for some combinations (that's expected, not an error); reporting two models (e.g. Bliss + HSA, or Loewe + ZIP) is good practice.
Step 2 — Run it
# Bliss (single dose pair, fractional inhibition)
tu run DrugSynergy_calculate_bliss '{"operation":"calculate_bliss",
"effect_a":0.4,"effect_b":0.3,"effect_combination":0.7}'
# -> expected 0.58, bliss_synergy_score 0.12, "Strong synergy"scripts/synergy_reference.py computes the Bliss, HSA, and Loewe-style expected combination effects side-by-side from one dose pair, so you can see at a glance whether the models agree before running the full tools.
Step 3 — Interpret the score
For Bliss/HSA/Loewe/ZIP, the synergy score is (observed − expected) (often ×100):
| Score (fractional, ×100 scale) | Call |
|---|---|
| > +10 | synergy |
| −10 to +10 | additive (no meaningful interaction) |
| < −10 | antagonism |
For Combination Index (Chou-Talalay): CI < 1 = synergy, CI = 1 additive, CI > 1 antagonism (note the opposite direction — lower is more synergistic).
- A positive Bliss/HSA score means the combination exceeds the additive expectation at that point.
- Synergy is often dose-dependent — a combination can be synergistic at one ratio and antagonistic at another; for a matrix, report the synergistic region, not one number.
Step 4 — Gotchas (state these)
- Scale mismatch (% viability vs fractional inhibition) — convert first (Step 0).
- Effects near 0 or 1 (ceiling). If both single agents already kill ~everything, the combo can't show synergy (no headroom) — Bliss/HSA saturate; interpret with care.
- ZIP/Loewe/CI need real dose-response with ≥3 non-zero, measurable-effect dose points per drug, or the Hill fit fails (the tools say so).
- Model disagreement is normal — don't shop for the model that gives "synergy"; pre-specify the model and report it.
- A synergy score is not efficacy — a strongly synergistic combination can still be weak overall; report the absolute combination effect too.
Honest limitations
- These are reference-model synergy scores, not statistical tests — for confidence, replicate and report variability across the dose matrix.
- Synergy in vitro does not guarantee clinical benefit (PK/PD, toxicity, scheduling all matter).
Related skills
tooluniverse-dose-response— fit the single-agent IC50/EC50 curves that Loewe/CI/ZIP need.tooluniverse-cell-line-profiling— look up pre-computed combination synergy (SYNERGxDB).tooluniverse-drug-repurposing/tooluniverse-network-pharmacology— rationale for combinations.
#!/usr/bin/env python3
"""Side-by-side synergy reference expectations for the
tooluniverse-drug-synergy skill.
Given the single-agent and combination fractional inhibition at one dose pair,
prints the Bliss, HSA, and simple-additive expected combination effects and the
corresponding synergy scores, so you can see at a glance whether the reference
models agree before running the full DrugSynergy_* tools (which also handle
dose-response models Loewe / CI / ZIP).
Inputs are FRACTIONAL inhibition (0-1). For % viability, convert first:
inhibition = 1 - viability/100.
Usage:
python synergy_reference.py --ea 0.4 --eb 0.3 --ecombo 0.7
"""
import argparse
def _call(score):
if score > 0.10:
return "synergy"
if score < -0.10:
return "antagonism"
return "additive"
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--ea", type=float, required=True, help="fractional inhibition of drug A (0-1)")
ap.add_argument("--eb", type=float, required=True, help="fractional inhibition of drug B (0-1)")
ap.add_argument("--ecombo", type=float, required=True, help="fractional inhibition of A+B (0-1)")
args = ap.parse_args()
ea, eb, ec = args.ea, args.eb, args.ecombo
for v, name in ((ea, "ea"), (eb, "eb"), (ec, "ecombo")):
if not 0 <= v <= 1:
raise SystemExit(f"{name}={v} is not a fraction in [0,1]; convert % viability to 1-viability/100.")
bliss_exp = ea + eb - ea * eb
hsa_exp = max(ea, eb)
additive_exp = min(1.0, ea + eb)
print(f"\nObserved combination effect: {ec:.3f} (single agents: A={ea:.3f}, B={eb:.3f})\n")
print(f"{'Model':<26}{'expected':>10}{'score':>10} call")
for name, exp in (
("Bliss independence", bliss_exp),
("HSA (highest single)", hsa_exp),
("Simple additive (capped)", additive_exp),
):
score = ec - exp
print(f"{name:<26}{exp:>10.3f}{score:>10.3f} {_call(score)}")
if ec >= 0.95 and min(ea, eb) >= 0.9:
print("\n ! both single agents near-complete inhibition — ceiling effect; little headroom to detect synergy.")
print("\nFor Loewe / Combination Index / ZIP (dose-response or matrix models) use the DrugSynergy_* tools.")
if __name__ == "__main__":
main()
"""Tests for the drug-synergy skill helper script."""
import pathlib
import subprocess
import sys
import pytest
SCRIPT = pathlib.Path(__file__).parent / "scripts" / "synergy_reference.py"
sys.path.insert(0, str(SCRIPT.parent))
import synergy_reference as sr # noqa: E402
pytestmark = pytest.mark.unit
def test_call_thresholds():
assert sr._call(0.2) == "synergy"
assert sr._call(0.0) == "additive"
assert sr._call(-0.2) == "antagonism"
# boundary: just inside +/-0.10 is additive
assert sr._call(0.10) == "additive"
assert sr._call(0.11) == "synergy"
def test_bliss_expected_matches_tool():
# Bliss: E_exp = ea + eb - ea*eb; for 0.4,0.3 -> 0.58, score (0.7-0.58)=0.12
out = subprocess.run(
[sys.executable, str(SCRIPT), "--ea", "0.4", "--eb", "0.3", "--ecombo", "0.7"],
capture_output=True,
text=True,
check=True,
).stdout
assert "0.580" in out # Bliss expected
assert "0.120" in out # Bliss synergy score (matches DrugSynergy_calculate_bliss)
assert "synergy" in out
def test_rejects_out_of_range_fraction():
r = subprocess.run(
[sys.executable, str(SCRIPT), "--ea", "40", "--eb", "0.3", "--ecombo", "0.7"],
capture_output=True,
text=True,
)
assert r.returncode != 0
assert "fraction" in (r.stderr + r.stdout).lower()