|
| 1 | +# Agent Guidance for O-QT MCP Server |
| 2 | + |
| 3 | +## Scope |
| 4 | +This file applies to the `o-qt-mcp-server-public` repository (canonical target). |
| 5 | + |
| 6 | +## Critical Controls (Added 2026-04-16) |
| 7 | + |
| 8 | +### 1. Applicability Domain (AD) Gating |
| 9 | +- **Files:** `src/tools/implementations/o_qt_qsar_tools.py`, `src/tools/implementations/toolbox_execution.py`, `src/tools/implementations/workflow_runner.py` |
| 10 | +- **Behavior:** `run_qsar_prediction` and `run_qsar_model` now inspect the domain result from the QSAR Toolbox. If the domain status is `"OutOfDomain"`, the result includes: |
| 11 | + - `"ad_status": "out_of_domain"` |
| 12 | + - `"ad_warning": true` |
| 13 | + - `"ad_recommendation": "..."` |
| 14 | +- **Rule:** Do NOT remove these fields. The workflow runner surfaces AD warnings in the Markdown summary. |
| 15 | + |
| 16 | +### 2. Human Review Checkpoints (OQT-02) |
| 17 | +- **Files:** `src/utils/review.py`, `src/tools/implementations/workflow_runner.py`, `config/tool_permissions.default.json` |
| 18 | +- **Behavior:** When `require_human_review=true` is passed to `run_oqt_multiagent_workflow`, the workflow creates up to three checkpoints: |
| 19 | + 1. `chemical_identity` — after resolving the input identifier to a Toolbox record |
| 20 | + 2. `ad_assessment` — when any QSAR prediction reports `ad_warning=true` |
| 21 | + 3. `final_report` — before generating the PDF artifact |
| 22 | +- If checkpoints are pending, the workflow returns `status: "review_required"` with `workflow_id` and `review_checkpoints`. No PDF is generated. |
| 23 | +- Clients can approve/reject checkpoints via the `approve_workflow_checkpoint` tool, then resume by passing the same `workflow_id` (and optionally `checkpoint_approvals`) to the workflow. |
| 24 | +- **Rule:** Do NOT auto-generate artifacts when `require_human_review=true` and checkpoints are pending. Do NOT skip the `ad_assessment` checkpoint for out-of-domain predictions. |
| 25 | + |
| 26 | +### 3. LLM Prompt-Boundary Sanitization |
| 27 | +- **File:** `src/utils/sanitization.py`, `src/integrations/oqt_assistant.py` |
| 28 | +- **Behavior:** All user-supplied identifiers and context strings are sanitized with `sanitize_for_llm()` before entering the oqt_assistant LLM pipeline. |
| 29 | +- **Rule:** If you add new LLM-facing inputs, pipe them through `sanitize_for_llm()`. |
| 30 | + |
| 31 | +### 4. Privacy-Aware Audit Logging |
| 32 | +- **Files:** `src/utils/privacy.py`, `src/tools/registry.py`, `src/api/server.py`, `src/utils/logging.py` |
| 33 | +- **Behavior:** |
| 34 | + - Audit events hash SMILES, CAS numbers, chemical names, and API keys before logging. |
| 35 | + - The HTTP audit middleware parses query strings into dictionaries so parameter keys remain readable while values are hashed. |
| 36 | + - The `PrivacyLogFilter` scrubs SMILES/CAS patterns from free-text log messages and URL query parameters, and hashes whole-value identifiers in structured log extra fields. |
| 37 | +- **Rule:** Do NOT log raw chemical identifiers or secrets. Use `scrub_dict()` on params before audit emit. |
| 38 | + |
| 39 | +### 5. Fallback PDF Provenance |
| 40 | +- **File:** `src/utils/pdf_generator.py` |
| 41 | +- **Behavior:** The fallback PDF includes: |
| 42 | + - A prominent disclaimer on the first page |
| 43 | + - An "Applicability Domain Warnings" section when out-of-domain predictions are present |
| 44 | + - A "Provenance" section showing model count and AD status |
| 45 | +- **Rule:** Keep the disclaimer visible. Do not remove the AD-warning block. |
| 46 | + |
| 47 | +### 6. Search Defaults |
| 48 | +- **File:** `src/tools/implementations/workflow_runner.py`, `src/tools/implementations/o_qt_qsar_tools.py` |
| 49 | +- **Behavior:** `search_type` default is now `"name"` instead of `"auto"` to reduce silent wrong-chemical resolution. |
| 50 | +- **Rule:** Do not revert the default to `"auto"` without explicit user confirmation logic. |
| 51 | + |
| 52 | +## Testing Expectations |
| 53 | +- Any change to AD logic must pass `test_run_qsar_prediction_ad_warning_out_of_domain`. |
| 54 | +- Any change to privacy logic must pass `tests/utils/test_privacy.py`. |
| 55 | +- Any change to sanitization must pass `tests/utils/test_sanitization.py`. |
| 56 | +- Any change to PDF generation must pass `test_generate_pdf_report_includes_disclaimer_and_ad_warnings`. |
0 commit comments