> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aisim.sandboxaq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AQPotency

> AQPotency is an ultrafast proteochemometric model (PCM) for relative ranking of protein–ligand potency — no crystal structure required, CPU-friendly, MCP-accessible, with built-in uncertainty and applicability tooling.

**AQPotency** predicts protein–ligand potency on the pIC₅₀ scale without requiring an experimentally resolved 3D structure, returning a ranking signal together with uncertainty and applicability-domain context on every prediction. It runs on standard CPUs for about \$1 per thousand pairs scored, so a team can rank a large compound library before committing wet-lab resources to the candidates most likely to matter.

<a id="overview" />

## Overview

**AQPotency** is SandboxAQ's ultrafast **potency ranking model** — a Large Quantitative Model for small-molecule drug discovery. It takes a protein UniProt accession and a ligand SMILES string and returns a predicted potency (`potency_mean`, on the pIC₅₀ scale), an uncertainty estimate (`potency_sigma`), and applicability signals (`ligand_similarity`, `protein_in_training`) via an async job — no GPU, no per-target training, no docked pose or crystal structure required.

AQPotency is purpose built for **relative ranking** : virtual screening, selectivity profiling, off-target and safety-panel scans, and reverse screening, not absolute potency prediction. It is the fast triage layer that runs **before** slower and more accurate physics-based methods such as docking, FEP, or experimental screening.

AQPotency is available via the **SandboxAQ MCP Server** — SandboxAQ's fully managed server, optimized for LLM and agentic integration with Anthropic and others LLM platforms.

<a id="what-is" />

Through the SandboxAQ MCP Server, users can:

* Score a single protein–ligand pair from a UniProt ID and a SMILES string via `AqpotencyPotency` (async — jobs typically finish in seconds).
* Screen a SMILES library of **up to 10,000 compounds** against a single target with `AqpotencyScreen`, using an upload-session flow (`upload_files` / `upload_local_files` with `purpose='aqpotency_screen'`).
* Run a single ligand against curated panels — `human_kinome`, `bowes_safety_panel`, or `proteome` — via `AqpotencyScan` for off-target and toxicity triage.
* Compute selectivity ratios with `AqpotencySelectivity` against one on-target and a list of off-targets, without standing up custom infrastructure.

<Note>
  **Positioning — ranking, not absolute prediction:** AQPotency typically delivers **useful Spearman rank correlations** but limited R² on absolute potency. Treat predictions as a fast ranking signal with uncertainty (`potency_sigma`), and rely on the always-on applicability signals — `ligand_similarity` and `protein_in_training` — to gate confidence.
</Note>

<a id="how-it-works" />

## How It Works

AQPotency's respective tool calls automatically orchestrates:

1. **Protein ID Lookup:** The UniProt accession is resolved to a precomputed ESM2 protein-language-model embedding, so no protein-language model runs at inference time. Lookup is effectively free, which is what makes whole-panel reverse screening practical.
2. **Ligand Features:** Ligand SMILES strings are converted to fast small-molecule fingerprints on the fly.
3. **Potency Prediction:** Our potency prediction model head fuses the protein embedding and the ligand fingerprint to predict `potency_mean` (on the pIC₅₀ scale) plus a per-pair `potency_sigma` (model standard deviation).
4. **Applicability Domain (AD) Scoring:** Two applicability-domain signals are computed automatically and returned with every prediction — `ligand_similarity` (max Tanimoto vs. the training set, 0–1) and `protein_in_training` (boolean). AD is always on; there is no opt-in flag and no separately callable AD tool.
5. **Result Delivery:** All four tools are **asynchronous**. Each call returns a `job_id` in 1–2 seconds; results are retrieved by polling `check_job_status` and then calling `get_job_results`.

With the protein side reduced to an embedding lookup, throughput stays high on ordinary hardware: AQPotency scores roughly **2,000 protein–ligand pairs in about 15 seconds** on standard CPUs, and asynchronous execution is what lets large library and panel workflows finish inside LLM timeout windows.`AqpotencyPotency` jobs typically finish in seconds. `AqpotencyScreen` accepts up to **10,000 SMILES** per request (with a 16 MB upload-file cap) and returns results as a JSON `predictions` list sorted by `potency_mean` descending.

<Warning>
  **Ranking signal, not absolute truth.** Treat predictions as a fast ordering signal, not a quantitative affinity. Always inspect `ligand_similarity`, `protein_in_training`, and `potency_sigma` before acting — out-of-domain proteins or ligands yield lower rank correlation and often negative R².
</Warning>

<Note>
  **Trust signals are always included.** `ligand_similarity` and `protein_in_training` ride along with every prediction at no extra cost — no opt-in, no separate trust-stack tool to call.
</Note>

<a id="using" />

## Using AQPotency

<Warning>
  **LLM tool invocation is non-deterministic.** Your client may occasionally answer an AQPotency-shaped question from its own knowledge rather than calling `AqpotencyPotency`, `AqpotencyScreen`, `AqpotencyScan`, or `AqpotencySelectivity`. Follow the setup and prompt-phrasing guidance below — and see [Improving tool-invocation reliability](/mcp-server/mcp-server#improving-tool-invocation-reliability) for the full write-up (including how to disable lazy loading in Claude Desktop, which is the single biggest reliability win).
</Warning>

### Typical Workflow

A typical AQPotency session through an MCP client follows the same four-step shape regardless of which tool you reach for:

1. **Pick the screening mode.** Single-target ranking, library screening, reverse / panel screening, or selectivity.
2. **Provide the inputs the mode needs.** A UniProt accession and SMILES for `AqpotencyPotency`; an `upload_session_id` (from `upload_files` / `upload_local_files` with `purpose='aqpotency_screen'`) plus a UniProt accession for `AqpotencyScreen`; a SMILES and a `panel` enum for `AqpotencyScan`; a SMILES plus an on-target accession and an off-target list for `AqpotencySelectivity`.
3. **Invoke the matching tool.** `AqpotencyPotency`, `AqpotencyScreen`, `AqpotencyScan`, or `AqpotencySelectivity` — each returns a `job_id` in 1–2 seconds.
4. **Review the result with its trust signals.** Read `potency_mean` alongside `potency_sigma`, `ligand_similarity`, and `protein_in_training` before committing to a downstream docking, med-chem, or experimental decision.

### Setup

AQPotency is reached through the SandboxAQ MCP Server, so there is nothing AQPotency-specific to install. Connect the server once and all four AQPotency tools appear in your client alongside `aqcat`.

<Steps>
  <Step title="Connect the SandboxAQ MCP Server">
    Sign up at [platform.aisim.sandboxaq.com/signin](https://platform.aisim.sandboxaq.com/signin), then follow the [Quickstart](/getting-started/quickstart) for your client — or [Connect your MCP client](/getting-started/connect-client) for the full walkthrough with screenshots and troubleshooting.
  </Step>

  <Step title="Turn off lazy loading">
    In **Settings → Connectors → SandboxAQ MCP Server**, set **Lazy load tools** to **off** so all four AQPotency schemas stay loaded and your client picks the right one. In Claude Code, set `ENABLE_TOOL_SEARCH=true` instead. See [Improving tool-invocation reliability](/mcp-server/mcp-server#improving-tool-invocation-reliability).
  </Step>

  <Step title="Verify">
    Ask your client: *"What tools do you have available from SandboxAQ?"* — it should list `AqpotencyPotency`, `AqpotencyScreen`, `AqpotencyScan`, and `AqpotencySelectivity` with their parameter descriptions.
  </Step>

  <Step title="Run your first query">
    Try: \_"\_Predict the binding potency of `CC1=CC=C(C=C1)S(=O)(=O)N` against protein P00533." Your client will submit an `AqpotencyPotency` job, poll `check_job_status`, and return `potency_mean` alongside `ligand_similarity`, `protein_in_training`, and `potency_sigma`.
  </Step>
</Steps>

<Note>
  The SandboxAQ MCP Server is a **remote connector**, added through **Settings → Connectors** — not an entry in `claude_desktop_config.json`. Claude Code is the exception: it registers the server with `claude mcp add` or a `.mcp.json` entry. Both flows are covered in [Connect your MCP client](/getting-started/connect-client).
</Note>

### Improving Tool-Invocation Reliability

Two failure modes are common when asking your client about AQPotency-shaped problems: (1) it answers from prior knowledge instead of calling the right AQPotency tool, and (2) it picks the wrong tool (e.g. `AqpotencyScreen` for a single-pair question, or `AqpotencyPotency` for a batch screen). Both are addressed by client configuration plus prompt hygiene.

* **Disable lazy loading in Claude Desktop** — the single most impactful fix. See [MCP → Improving tool-invocation reliability](/mcp-server/mcp-server#improving-tool-invocation-reliability) for the exact toggle.
* **Name the specific tool** in your prompt: *"Use AqpotencyPotency to…"*, *"Call AqpotencyScreen with…"*, *"Run AqpotencyScan against panel …"*, or *"Use AqpotencySelectivity with target …"*.
* **Match the tool to the workload shape.** One pair = `AqpotencyPotency`. Many SMILES vs. one target = `AqpotencyScreen`. One SMILES vs. many targets = `AqpotencyScan`. One SMILES vs. a target + explicit off-targets = `AqpotencySelectivity`.
* **Provide the UniProt ID (or panel name)** explicitly rather than a gene symbol — *"P00533"* or *"panel='proteome'"* trigger the tool more reliably than *"EGFR"* or *"the whole proteome"*.
* **Include the SMILES inline or reference the uploaded file** so the model doesn't have to infer where the ligand is coming from.
* **If your client still answers without calling the tool, explicitly ask it to.** *"Please call AqpotencyScreen with the parameters above"* is a valid recovery prompt.

### Example Use Cases

Realistic prompts you can issue after SandboxAQ MCP Server is connected. The worked examples name the target AQPotency tool explicitly and surface the parameters (UniProt ID, panel name, off-targets) that make the call converge on the same tool selection every time. In each case your client submits the job, polls `check_job_status`, and returns the result alongside its applicability signals.

**Quick prompts.** Three single-call shapes, copy-paste ready — collected with the AQCat equivalents on [Example Prompts](/getting-started/example-prompts).

**Single protein–ligand pair — `AqpotencyPotency`**

> Predict the binding potency of `CC1=CC=C(C=C1)S(=O)(=O)N` against protein P00533.

**Panel scan — `AqpotencyScan`**

> Scan `CC1=CC=C(C=C1)S(=O)(=O)N` against the `human_kinome`.

**Selectivity against named off-targets — `AqpotencySelectivity`**

> Assess the selectivity of `CC1=CC=C(C=C1)S(=O)(=O)N` against target Q15078 vs. off-targets Q6J9G0, Q13546, Q15768.

The three worked examples below cover the heavier workflows, each with the tool call LLM makes and the shape of the result.

<AccordionGroup>
  <Accordion title="1. Rank a focused EGFR library for downstream docking">
    **User prompt**

    > I have a focused library of \~1,000 compounds. Upload the file, then use the `AqpotencyScreen` tool to rank the top 25 compounds by predicted potency against UniProt P00533 (EGFR) so I can shortlist them for docking. Include `ligand_similarity` and `protein_in_training` on each row.

    Example file: [`focused_library.csv`](https://drive.google.com/file/d/1STkQn20XKfwDy6WYmBKiF2ZNDl8ltBUU/view?usp=sharing)

    **What your client does**

    Calls `upload_local_files` with `purpose='aqpotency_screen'` to push the library to a new `upload_session_id`, then invokes `AqpotencyScreen` with that session ID and `uniprot_id='P00533'`. Polls `check_job_status` to completion, then `get_job_results` with `limit=25`.

    **Expected output**

    ```text theme={null}
    **Top 25 compounds against EGFR (P00533), sorted by `potency_mean` descending.** Each row reports `potency_mean`, `potency_sigma`, `ligand_similarity`, and `protein_in_training`. The top three sit in the high-similarity regime (`ligand_similarity` ≥ 0.85) and are recommended for downstream docking; the next ten carry elevated `potency_sigma` and may merit re-ranking after docking.
    ```
  </Accordion>

  <Accordion title="2. Identify likely targets of a phenotypic hit">
    **User prompt**

    > Here's a SMILES from a phenotypic screen: `CN(C)CC[C@@H](c1ccc(Br)cc1)c1ccccn1`. Use the `AqpotencyScan` tool with `panel='proteome'` to score it against every protein in the panel, then return the top 10 most likely targets ranked by predicted potency, and flag any that are out-of-domain (`protein_in_training=false`).

    **What your client does**

    Calls `AqpotencyScan` with the supplied `smiles` and `panel='proteome'`. Polls to completion, then `get_job_results` to read the top targets ranked by `potency_mean`.

    **Expected output**

    ```text theme={null}
    **Top targets ranked by predicted potency.** Three accessions land in the high-confidence regime (`ligand_similarity` ≥ 0.8 and `protein_in_training=true`); two more are flagged as out-of-domain (`protein_in_training=false`) and should be discounted before deciding which hits to validate experimentally.
    ```
  </Accordion>

  <Accordion title="3. Screen for CDK7-selective inhibitors">
    **User prompt**

    > For the SMILES below, use the `AqpotencySelectivity` tool with `target_uniprot_id='P50613'` (CDK7) and `off_target_uniprot_ids=['P06493','P24941','P11802','Q00534','P50750']` (CDK1, CDK2, CDK4, CDK6, CDK9). Return per-off-target fold selectivity and the strongest-off-target summary, and flag any panel entry that's out-of-domain.

    ```text theme={null}
    CN(C)CCN(Cc1ccccc1)c1ccccn1
    CN(C)CCN(Cc1cccs1)c1ccccn1
    CN(C)CCN1C(=O)c2ccccc2N(C)c2ccccc21
    CN(C)CCOC(=O)C(c1ccccc1)C1(O)CCCC1
    CN(C)CCOC(C)(c1ccccc1)c1ccc(Cl)cc1
    CN(C)CCOC(C)(c1ccccc1)c1ccccn1
    CN(C)CCOC(c1ccc(Cl)cc1)c1ccccn1
    CN(C)CCOC(c1ccccc1)c1ccc(Br)cc1
    CN(C)CCOC(c1ccccc1)c1ccccc1
    CN(C)CCOc1ccc(/C(=C(/CCCl)c2ccccc2)c2ccccc2)cc1
    CN(C)CC[C@@H](c1ccc(Br)cc1)c1ccccn1
    CN(C)CC[C@@H](c1ccc(Cl)cc1)c1ccccn1
    ```

    **What your client does**

    Calls `AqpotencySelectivity` with the supplied `smiles`, `target_uniprot_id='P50613'` (CDK7), and `off_target_uniprot_ids=['P06493','P24941','P11802','Q00534','P50750']`. Returns per-off-target `fold_selectivity` plus a `fold_selectivity_against_strongest_off_target` summary.

    **Expected output**

    ```text theme={null}
    **Per-off-target `fold_selectivity` plus a strongest-off-target summary.** Compounds with `fold_selectivity_against_strongest_off_target` ≥ 5 and `protein_in_training=true` across every CDK in the panel are surfaced as solid CDK7-selective candidates; entries with one or more off-targets out of domain are flagged with a caveat.
    ```
  </Accordion>
</AccordionGroup>

<a id="tools" />

## Tool Catalog

AQPotency exposes **four MCP tools**. All four are **asynchronous and job-backed** — every call returns a `job_id` in 1–2 seconds, and results are retrieved by polling `check_job_status` and then calling `get_job_results`. Applicability-domain signals (`ligand_similarity` and `protein_in_training`) are always computed and returned automatically on every prediction at no extra cost — there is no separately callable AD tool surface.

| Tool                   | Purpose                                                                                                                                                 | Execution                    |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| `AqpotencyPotency`     | Predict pIC₅₀ for a **single** protein–ligand pair.                                                                                                     | Async (job ID, poll + fetch) |
| `AqpotencyScreen`      | Score an uploaded SMILES library (up to **10,000** SMILES) against a single target for virtual screening.                                               | Async (job ID, poll + fetch) |
| `AqpotencyScan`        | Screen one ligand against a **curated target panel** (`human_kinome`, `bowes_safety_panel`, or `proteome`) for reverse screening and off-target triage. | Async (job ID, poll + fetch) |
| `AqpotencySelectivity` | Compute on-target vs. off-target potency and `fold_selectivity` for one ligand against one on-target and a list of off-targets.                         | Async (job ID, poll + fetch) |

### `AqpotencyPotency` — single protein–ligand prediction

Predict potency for one ligand against one UniProt target. **Bulk submission is not supported in this tool** — issue separate calls for multiple molecules. The job submission returns a `job_id`; the eventual result contains `potency_mean`, `potency_sigma`, `ligand_similarity`, and `protein_in_training`.

| Parameter    | Required | Type   | Description                                                                   |
| ------------ | -------- | ------ | ----------------------------------------------------------------------------- |
| `smiles`     | yes      | string | A single SMILES string for the query ligand                                   |
| `uniprot_id` | yes      | string | UniProt accession for the target. Raw protein sequences are **not** accepted. |

### `AqpotencyScreen` — library vs. single target

Score an uploaded SMILES library against one target. The library must be uploaded **first** via `upload_files` or `upload_local_files` with `purpose='aqpotency_screen'`; the returned `upload_session_id` is then passed to `AqpotencyScreen`.

| Parameter           | Required | Type   | Description                                                                                                                                               |
| ------------------- | -------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `upload_session_id` | yes      | string | Session ID returned by the upload step. The uploaded file must be `.smi` or `.csv`; if `.csv`, it must contain a `SMILES` column (case-sensitive header). |
| `uniprot_id`        | yes      | string | UniProt accession for the target                                                                                                                          |

<Note>
  **Hard limits.** A `screen` request accepts at most **10,000 SMILES** per call, and the uploaded file must be ≤ **16 MB**. Requests over these caps are rejected with a `ToolError`. Results are returned as a JSON `predictions` list sorted by `potency_mean` descending; pass an optional `limit` (the tool docstrings suggest `limit=25`) when fetching results.
</Note>

### `AqpotencyScan` — reverse screening vs. curated panels

Screen a single ligand against a predefined target panel and return ranked potential targets. Panels are bundled in the container image — no external API calls at runtime.

| Parameter | Required | Type   | Description                                                 |
| --------- | -------- | ------ | ----------------------------------------------------------- |
| `smiles`  | yes      | string | The query ligand (single SMILES string)                     |
| `panel`   | yes      | enum   | One of `bowes_safety_panel`, `human_kinome`, or `proteome`. |

### `AqpotencySelectivity` — on-target vs. off-target ratios

Compute selectivity for a single ligand against a single on-target and a list of off-targets. Returns per-off-target `fold_selectivity` plus a `fold_selectivity_against_strongest_off_target` summary. The `off_targets` list in the response is ordered **lexicographically by UniProt accession**, not by submission order.

| Parameter                | Required | Type   | Description                                                                                                                 |
| ------------------------ | -------- | ------ | --------------------------------------------------------------------------------------------------------------------------- |
| `smiles`                 | yes      | string | The query ligand (single SMILES string)                                                                                     |
| `target_uniprot_id`      | yes      | string | UniProt accession of the on-target                                                                                          |
| `off_target_uniprot_ids` | yes      | array  | List of off-target UniProt accessions. Must contain ≥1 entry, all entries distinct, and none may equal `target_uniprot_id`. |

<a id="schemas" />

## Request & Response Schemas

Every AQPotency tool follows the same **three-step job lifecycle** over MCP: (1) call the tool to submit a job and receive a `job_id`; (2) poll `check_job_status` until `is_terminal` is `true`; (3) fetch the result with `get_job_results`.

### `AqpotencyPotency` request

AQPotency tools are invoked as standard MCP tool calls with named arguments — there is no `client_context_id` / `tool_name` / `parameters` wrapper.

```json theme={null}
{
  "name": "AqpotencyPotency",
  "arguments": {
    "smiles": "Cc1ccc(NC(=O)c2ccc(CN3CCN(C)CC3)cc2)cc1Nc1nccc(-c2cccnc2)n1",
    "uniprot_id": "P50613"
  }
}
```

### Submission ack (every AQPotency tool)

Every AQPotency tool returns the same lightweight acknowledgement on submission. The `job_id` is the handle for the subsequent polling and result-fetch calls.

```json theme={null}
{
  "job_id": "0c5b1f3e-9b2c-4f4a-9a4e-2bfa1c4e1101",
  "status": "pending",
  "message": "Job submitted. Use check_job_status to poll for completion, then get_job_results to fetch the result."
}
```

### Polling with `check_job_status`

While the job is running, `check_job_status` returns `is_terminal: false` and a recommended `poll_after_seconds` interval. On completion it returns `is_terminal: true`; elapsed time is included in the `progress_message` string (there is no separate `elapsed_seconds` field).

```json theme={null}
{
  "job_id": "0c5b1f3e-9b2c-4f4a-9a4e-2bfa1c4e1101",
  "status": "completed",
  "is_terminal": true,
  "progress_message": "Job complete (4s elapsed)."
}
```

### `AqpotencyPotency` result (via `get_job_results`)

`get_job_results` returns a `predictions` list. Each entry includes the identifying `smiles` and `uniprot_id` plus the real output fields — `potency_mean`, `potency_sigma`, `ligand_similarity`, and `protein_in_training`. Applicability fields are only present when computable.

```json theme={null}
{
  "predictions": [
    {
      "smiles": "Cc1ccc(NC(=O)c2ccc(CN3CCN(C)CC3)cc2)cc1Nc1nccc(-c2cccnc2)n1",
      "uniprot_id": "P50613",
      "potency_mean": 7.82,
      "potency_sigma": 0.41,
      "ligand_similarity": 0.87,
      "protein_in_training": true
    }
  ]
}
```

### `AqpotencyScreen` request

The compound library must be uploaded ahead of the screen call via `upload_files` or `upload_local_files` with `purpose='aqpotency_screen'`. Pass the returned `upload_session_id` and the target's UniProt accession:

```json theme={null}
{
  "name": "AqpotencyScreen",
  "arguments": {
    "upload_session_id": "us_2f8e1c4a9b7d4e10",
    "uniprot_id": "P50613"
  }
}
```

### `AqpotencyScreen` result (via `get_job_results`)

Results are returned as a JSON `predictions` list **sorted by `potency_mean` descending**. Pass an optional `limit` (the tool docstrings suggest `limit=25`) to cap the number of rows returned. Each entry mirrors the potency shape but uses `target_uniprot_id` for the target accession.

```json theme={null}
{
  "predictions": [
    {
      "smiles": "Cc1ccc(NC(=O)c2ccc(CN3CCN(C)CC3)cc2)cc1Nc1nccc(-c2cccnc2)n1",
      "target_uniprot_id": "P50613",
      "potency_mean": 7.50,
      "potency_sigma": 0.40,
      "ligand_similarity": 0.90,
      "protein_in_training": true
    }
  ]
}
```

### Output Field Reference

| Field                                           | Type        | Description                                                                                                                   |
| ----------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `job_id`                                        | string      | Unique identifier returned on submission; pass to `check_job_status` and `get_job_results`.                                   |
| `status`                                        | string      | `pending`, `running`, `completed`, or `failed`.                                                                               |
| `is_terminal`                                   | bool        | `true` once the job has reached a terminal state and results can be fetched.                                                  |
| `progress_message`                              | string      | Human-readable progress; includes elapsed-time text on completion.                                                            |
| `smiles`                                        | string      | Ligand SMILES echoed on each prediction.                                                                                      |
| `uniprot_id` / `target_uniprot_id`              | string      | Target accession. `AqpotencyPotency` uses `uniprot_id`; `AqpotencyScreen` and `AqpotencySelectivity` use `target_uniprot_id`. |
| `potency_mean`                                  | float       | Predicted potency on the pIC₅₀ scale (higher = more potent). Use for **ranking**, not absolute affinity.                      |
| `potency_sigma`                                 | float       | Per-pair standard deviation from the Gaussian-mixture head, in pIC₅₀ units. Larger σ = lower confidence.                      |
| `ligand_similarity`                             | float (0–1) | Maximum Tanimoto similarity of the query ligand to the training set.                                                          |
| `protein_in_training`                           | bool        | Whether the target was represented in the training set. `false` means the prediction is extrapolating to an unseen protein.   |
| `fold_selectivity`                              | float       | **`AqpotencySelectivity` only.** Per-off-target potency ratio vs. the on-target.                                              |
| `fold_selectivity_against_strongest_off_target` | float       | **`AqpotencySelectivity` only.** Convenience summary against the most-potent off-target.                                      |
| `off_targets`                                   | array       | **`AqpotencySelectivity` only.** Per-off-target predictions, ordered **lexicographically** by UniProt accession.              |

<a id="interpreting-results" />

## Interpreting Results

### Use AQPotency for Ranking, Not Absolute Potency

AQPotency is designed and validated as a **rank-correlation** model. Spearman correlation is typically meaningful; R² is often poor and can be negative for out-of-domain targets or ligands. Use predictions to **order compounds** (top-N for downstream docking/FEP, bottom-N to discard), not to report headline binding constants.

<Warning>
  **Do not quote `potency_mean` as an absolute affinity.** A `potency_mean` of 7.8 should be read as *"this compound ranks near the top of the library for this target"*, not *"this compound has Ki ≈ 16 nM."* Combine with docking, FEP, or experimental follow-up before committing to a number.
</Warning>

### Applicability Domain & Uncertainty

Every prediction ships with three confidence signals. Applicability domain is **always on** and surfaces as **two distinct fields** (not a single fused score); there is no separate `applicability_domain` tool to call.

| Signal                | Type                | Interpretation                                                                                                                                                                                                                              |
| --------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ligand_similarity`   | float (0–1)         | Maximum Tanimoto similarity of the query ligand to the training set. **Higher = more reliable**; a low value means the ligand is unlike anything the model has seen and the prediction should be treated as a noisy ranking signal at best. |
| `protein_in_training` | bool                | Whether the target was represented in training. `false` means the model is extrapolating to an unseen protein — discount the prediction accordingly.                                                                                        |
| `potency_sigma`       | float (pIC₅₀ units) | Per-pair standard deviation from the Gaussian-mixture head. A large σ alongside a high `potency_mean` is a flag to re-rank with AD-aware filters or to fall back to docking/FEP.                                                            |

<Note>
  **LLM behaviour:** The MCP tool descriptions instruct the assistant to **caveat predictions with low `ligand_similarity` or high `potency_sigma`**, rather than presenting a single number with false confidence. There is no `applicability_domain` or `eda` follow-up tool to call — applicability signals are already returned automatically with every prediction.
</Note>

### Selectivity & Off-Target Reasoning

Selectivity ratios (e.g., CDK7 vs. other CDKs) are most reliable when **every target in the comparison sits inside the applicability domain**. A high apparent selectivity driven by an out-of-domain off-target prediction is a common failure mode — filter the off-target set on `ligand_similarity` and `protein_in_training` before acting on the ratios. Selectivity outputs are most useful for narrowing a large candidate set to a smaller shortlist for downstream docking, medicinal-chemistry review, or experimental follow-up — not as a standalone go/no-go signal.

### Scientific Benchmarks

**Virtual Screening Benchmark: LIT-PCBA Early Enrichment (N=15)**

| **Enrichment Factor** <br />**@ 5%** | **Full Set** | **Filter Training** | **Filter Training & PDB Selection** | **Extrapolate (Global Similarity \< 0.7) & Filter PDB Selection** |
| :----------------------------------- | :----------- | :------------------ | :---------------------------------- | :---------------------------------------------------------------- |
| **Docking (Vinardo Score)**          | 1.5          | 1.5                 | 1.3                                 | 2.2                                                               |
| **AQ Potency**                       | 2.2          | 2.1                 | 2.1                                 | 2.2                                                               |
| **Improvement Over Docking**         | 47%          | 37%                 | 67%                                 | None                                                              |
| **Wilcoxon Signed Rank Test**        | 0.27         | 0.27                | 0.21                                | 0.54                                                              |

*AQPotency is statistically equivalent to docking, with a significant speed advantage. LIT-PCBA target sets were standardized, deduplicated, and filtered (PAINS, BRENK), docked with GNINA 1.3 (no CNN), and evaluated with AQPotency. After controlling for data leakage and training similarity, the average maximum training-ligand similarity was 0.31 (Filter Training & PDB Selection). Differences from docking are not statistically significant (Wilcoxon signed-rank p = 0.21–0.54, N=15).*

<a id="pricing" />

## Pricing

AQPotency is priced **per protein–ligand pair evaluated**, on a shared two-tier schedule that applies uniformly to all four tools (`AqpotencyPotency`, `AqpotencyScreen`, `AqpotencyScan`, `AqpotencySelectivity`). The first **10 pairs of every call** are billed at **\$0.01 / pair**; every pair beyond that in the same call is billed at **\$0.001 / pair**.

A pair is one protein–ligand combination scored by the model. Each tool defines its own per-call workload envelope (see [Limits & Quotas](#limits)). Applicability-domain signals (`ligand_similarity`, `protein_in_training`) and the `potency_sigma` uncertainty estimate are returned with every prediction at no additional cost — there is no premium trust-stack add-on.

**What counts as a pair (per tool):**

| Tool                   | What counts as a pair                               |
| ---------------------- | --------------------------------------------------- |
| `AqpotencyPotency`     | 1 protein–ligand pair (the call itself is the pair) |
| `AqpotencyScreen`      | Each SMILES in the library × the target             |
| `AqpotencyScan`        | Each panel protein × the ligand                     |
| `AqpotencySelectivity` | Each (on-target or off-target) × the ligand         |

<Note>
  **Each call starts a fresh tier.** A screen of 10,000 SMILES pays tier-1 pricing on its first 10 pairs; a screen that splits across two 5,000-SMILES calls pays tier-1 pricing **on each call** (an extra \$0.09 vs. a single batched call). Batch aggressively where possible.
</Note>

Per-call workload caps live in [Limits & Quotas](#limits) — they're an envelope, not a billing unit. The 10,000-pair per-call cap applies to `AqpotencyScreen` only; `AqpotencyScan` runs against curated server-side panels and is not subject to that cap.

The full rate card, thirteen worked example costs, and the Individual vs. Enterprise tier comparison are on the [Pricing page → AQPotency](/getting-started/pricing#aqpotency) section. Enterprise customers can negotiate volume-based pricing, custom SLAs, customer-tenant deployment, and marketplace or procurement arrangements — contact [mcp-prod@sandboxaq.com](mailto:mcp-prod@sandboxaq.com).

<a id="limits" />

## Limits & Quotas

AQPotency is designed for high-throughput ranking. The following limits are enforced server-side to keep responses inside LLM timeout windows and to protect shared hosted infrastructure.

| Limit                                      | Individual                                         | Enterprise                                         |
| ------------------------------------------ | -------------------------------------------------- | -------------------------------------------------- |
| SMILES per `AqpotencyScreen` request       | 10,000 (hard cap)                                  | 10,000 (hard cap)                                  |
| Max upload file size for `AqpotencyScreen` | 16 MB                                              | 16 MB                                              |
| Job-ID return (all four tools)             | \<1–2s; processing async (poll `check_job_status`) | \<1–2s; processing async (poll `check_job_status`) |
| Curated panels available (`AqpotencyScan`) | `bowes_safety_panel`, `human_kinome`, `proteome`   | `bowes_safety_panel`, `human_kinome`, `proteome`   |
| Rate limit                                 | 10 RPM                                             | 100 RPM                                            |
| Minimum container resources                | ≥8 vCPU, ≥16–32 GB RAM (AD-on)                     | ≥8 vCPU, ≥16–32 GB RAM (AD-on)                     |

<Note>
  **All four AQPotency tools are asynchronous.** Every call returns a `job_id` in 1–2 seconds; results are fetched by polling `check_job_status` and then calling `get_job_results`. `AqpotencyScreen` requests that exceed the 10,000-SMILES or 16 MB caps are rejected with a `ToolError`.
</Note>

<a id="security" />

## Security & IP Protection

* **Telemetry:** Per-call usage metadata (counts, identifiers, wall-clock time) is logged for billing reconciliation and capacity planning.
* **Privacy:** See the [SandboxAQ Privacy Policy](/support-legal/privacy) for complete details on data handling and retention.
* **Organizational isolation:** Usage, billing, and data are isolated per organization. Cross-organization access is not possible.
