Skip to content

Add SandboxAQ, AQCat, and AQPotency catalog agents - #193

Merged
ryansok merged 16 commits into
microsoft:mainfrom
sravankumarux:add-sandboxaq-agent
Oct 9, 2026
Merged

ryansok merged 16 commits into
microsoft:mainfrom
sravankumarux:add-sandboxaq-agent

Conversation

@sravankumarux

@sravankumarux sravankumarux commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds three third-party (party: 3p) SandboxAQ agents to the catalog. This picks up the work from #134, including the fixes made after that PR closed.

Agent What it does How it connects
sandboxaq Calls SandboxAQ models subscribed through an Azure AI Foundry OpenAI-compatible chat-completions endpoint Container tool sandboxaq-model
aqcat Adsorption/binding energies and surface reactivity for adsorbate–surface systems; ranks binding across candidate surfaces SandboxAQ AI Simulation Platform MCP server
aqpotency Small-molecule binding potency (with uncertainty) against a protein target, plus safety and selectivity panel scans SandboxAQ AI Simulation Platform MCP server

Each agent's README links to the other two.

What's included

  • agents/sandboxaq/: agent.yaml, metadata.yaml, README.md, and tools/sandboxaq-model/ (Dockerfile on mcr.microsoft.com/azurelinux/base/python:3.12, tool.yaml, sandboxaq_utils.py)
  • agents/aqcat/: agent.yaml, metadata.yaml, README.md
  • agents/aqpotency/: agent.yaml, metadata.yaml, README.md

Configuration

No secrets are committed.

sandboxaq: the tool reads these runtime environment variables:

Variable Required Purpose
FOUNDRY_ENDPOINT Yes Foundry endpoint including the /openai API base
FOUNDRY_API_KEY Yes Secret for the subscribed deployment
FOUNDRY_DEPLOYMENT Yes SandboxAQ model deployment name
FOUNDRY_API_VERSION No Defaults to 2024-10-21

aqcat / aqpotency: these use a Foundry-native kind: mcp tool with a remote connection (authenticationMode: apiKey) and two deploy-time placeholders:

  • {{AQ_MCP_SERVER_URL}}: the tenant's SandboxAQ MCP server URL (tenant-specific, so it can't be fixed in the catalog)
  • {{AQ_MCP_CONNECTION}}: the name of the connection in the deploying customer's Foundry project that holds the header credential. The credential never appears in the catalog.

Reviewer notes

  • MCP tool shape follows the existing synthesize-bio agent: serverName, serverDescription, a remote connection, approvalMode: never, and a tool-level allowedTools list scoping each agent to its own tools on the shared platform server.
  • aqcat and aqpotency have not been deployed end to end yet. We don't have a Microsoft Discovery preview workspace to deploy into. deploy-discovery-agent.ps1 aqcat -WhatIfPlan succeeds. Note that the deployer only substitutes {{CHAT-MODEL}} and tool IDs. The two AQ_MCP_* placeholders have to be filled in manually at deploy time.
  • The sandboxaq agent's instructions forbid exposing endpoint URLs, API keys, or authorization headers. They also include data-handling guidance: no inference of protected attributes, no employment decisions, and flag responses that need human review.

Two defects in the initial SandboxAQ agent:

1. The toolId placeholder was `{{SANDBOAQ_MODEL_TOOL_ID}}` -- misspelled and
   not in the catalog's `{{<toolName>ToolId}}` camelCase convention, so it
   would not resolve at provisioning time. Now `{{sandboxaqModelToolId}}`.

2. The tool declared an `actions:` entry whose command interpolated the
   user's prompt into a shell string (`--prompt '{{prompt}}'`). Because the
   runtime substitutes textually, any prompt containing an apostrophe was
   mangled -- and no quoting style fixes this in general: single quotes break
   on `'`, double quotes break on `"` and expand `$(...)`.

Switch the tool to the `code_environments` pattern used by the majority of
the catalog. The agent now writes a Python script that imports
`sandboxaq_utils` and calls `invoke_model(...)`, so prompt text travels as a
Python string literal and never reaches a shell.

- run_action.py -> sandboxaq_utils.py, an importable module exposing
  `invoke_model()` and `save_json()` instead of an argparse entrypoint.
- Dockerfile ships the module to /app on PYTHONPATH, creates /input /output
  /workdir, and drops the ENTRYPOINT in favour of the code environment.
- tool.yaml replaces `actions:` with a `python3` code environment.
- agent.yaml instructions document the script template and the installed
  package set.
- Normalize language to `python3` (required for Foundry agent binding).

Verified: prompts containing apostrophes, double quotes, `$(whoami)`, and
newlines now reach the endpoint byte-identically; the documented script
template executes as written; the image builds and the module imports from
PYTHONPATH inside the container.
Addresses all 7 findings from the pr-review bot (SCH-037, DOC-003,
DOC-004, DOC-005, DOC-102, DOC-104, DOC-105) plus conformance gaps found
by comparing against the other 46 catalog agents.

tool.yaml:
- infra[].image.acr uses the deployer placeholder form
  `{name}.azurecr.io/sandboxaq-model:latest`. The bare `{name}/...` form
  renders without a registry domain (SCH-037); 39/44 catalog tools use
  the .azurecr.io form, and the 4 exceptions are all `actions:`-based
  EDA tools.
- Add `recommended_sku: Standard_D4s_v6` -- this was the only tool of 44
  without one.
- Match the compute profile shared by all 11 API-calling peer tools
  (chembl, pubchem, zinc, pubmed, clinical-trials, ...): ram 4Gi->8Gi and
  storage 8Gi->32Gi, plus `infiniband: false`.

agent.yaml:
- Add `topP: 0` to model.options; 35/47 agents set it and the deploy path
  reads model.options.topP.

README.md:
- Restructure to the section layout shared by 46/47 agents: Overview,
  Prerequisites, Build Docker Image, File Structure, Key Configuration
  Details, Usage, Architecture, Configuration, Support, Tools, Known
  Limitations, Contributing. It was previously the shortest README in the
  catalog and was missing six required sections.

Verified with .github/scripts/validate_pr.py (the script CI runs) against
the current schemas: all checks pass. Confirmed the validator is live via
a negative control (an invalid publisher.party is correctly rejected).
Both agents reach the SandboxAQ AI Simulation Platform MCP server as a
Foundry-native tool (kind: mcp), scoped with allowed_tools so each agent
sees only its own product's tools plus the shared job-management tools.
No container images or tool definitions are contributed; all computation
runs on SandboxAQ infrastructure.

Credentials are supplied through a connection reference resolved in the
deploying customer's Foundry project, so no secret-bearing value appears
in the published catalog metadata. The server URL remains a deploy-time
parameter.

Instructions are grounded in observed platform behaviour: submissions are
asynchronous jobs reporting pending until completion, so both agents
submit, poll, and fetch rather than expecting inline results. AQCat
reports convergence with the residual force against its threshold, the
resolved bulk identifier, the spin treatment, and every placement tried,
and declines to name a unique binding site when placements are
near-degenerate. AQPotency reports one-sigma uncertainty and ligand
similarity alongside every value, treating a wide sigma band with low
similarity as an absence of information rather than weak activity.

Jobs consume metered capacity, so humanInTheLoop is enabled and both
agents state the resolved plan and estimated cost for approval before
submitting.

Deployment against Foundry is not yet verified; the MCP tool option and
connection shapes need a live deploy to confirm.
Readers browsing the catalog see sandboxaq, aqcat, and aqpotency side by
side with no guidance on which applies to them. Each README now points at
the other two and states what access each one requires: a Foundry model
subscription for sandboxaq, an AI Simulation Platform tenant for the other
two.
@github-actions github-actions Bot added update-branch PR branch is behind base — please update needs-human-review Awaiting human approval 3p-contribution Authored by a third-party partner (party='3p' in metadata) contains-code PR includes source-code changes contains-dockerfile PR adds, modifies, renames, or removes a Dockerfile pr-validation-failed The pr-review workflow's validator failed; see inline comments. labels Sep 29, 2026
Comment thread agents/sandboxaq/tools/sandboxaq-model/Dockerfile
Comment thread agents/aqcat/README.md
Comment thread agents/aqcat/agent.yaml
Comment thread agents/aqcat/metadata.yaml
Comment thread agents/aqpotency/README.md
Comment thread agents/sandboxaq/agent.yaml
Comment thread agents/sandboxaq/metadata.yaml
Comment thread agents/sandboxaq/tools/sandboxaq-model/Dockerfile
Comment thread agents/sandboxaq/tools/sandboxaq-model/sandboxaq_utils.py
Comment thread agents/sandboxaq/tools/sandboxaq-model/tool.yaml
@github-actions

Copy link
Copy Markdown

❌ Automated Check Results — 18 issue(s) found

All issues are listed below. Please address all of them before requesting human review.

Rule ID Location Details
CFG-002 .github/policy/source-allowlist.yaml:1 source-allowlist.yaml is required but is missing. This policy is a security control; a missing file must not silently disable the checks it backs.

How to fix: Correct the issue described above, then push the fix to rerun validation.
CFG-002 .github/policy/base-images.yaml:1 base-images.yaml is required but is missing. This policy is a security control; a missing file must not silently disable the checks it backs.

How to fix: Correct the issue described above, then push the fix to rerun validation.
CFG-002 .github/policy/tag-taxonomy.yaml:1 tag-taxonomy.yaml is required but is missing. This policy is a security control; a missing file must not silently disable the checks it backs.

How to fix: Correct the issue described above, then push the fix to rerun validation.
CFG-003 docs/schemas/common-schema.json:1 docs/schemas/common-schema.json could not be loaded as a JSON object. External schema references would not resolve. A schema is a validation control; a missing or corrupt schema must not silently disable the checks it backs.

How to fix: Correct the issue described above, then push the fix to rerun validation.
POL-014 agents/sandboxaq/tools/sandboxaq-model/Dockerfile:1 Base image 'mcr.microsoft.com/azurelinux/base/python:3.12' comes from 'mcr.microsoft.com/azurelinux', which is not an approved source. Use a Docker Official Image (for example 'python:3.12-slim', 'ubuntu:24.04', 'debian:12-slim'), an mcr.microsoft.com image, or one of the publisher namespaces listed in '.github/policy/base-images.yaml'. If this publisher is genuinely required, propose it in a separate PR against that file explaining why no official equivalent exists.

How to fix: Switch the FROM line to a Docker Official Image, an mcr.microsoft.com image, or an approved publisher namespace from .github/policy/base-images.yaml.

Guidance: Open the authoring guide
POL-015 agents/aqcat/README.md:1 'README.md' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/aqcat/agent.yaml:1 'agent.yaml' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/aqcat/metadata.yaml:1 'metadata.yaml' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/aqpotency/README.md:1 'README.md' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/aqpotency/agent.yaml:1 'agent.yaml' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/aqpotency/metadata.yaml:1 'metadata.yaml' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/sandboxaq/README.md:1 'README.md' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/sandboxaq/agent.yaml:1 'agent.yaml' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/sandboxaq/metadata.yaml:1 'metadata.yaml' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/sandboxaq/tools/sandboxaq-model/Dockerfile:1 'Dockerfile' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/sandboxaq/tools/sandboxaq-model/sandboxaq_utils.py:1 'sandboxaq_utils.py' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-015 agents/sandboxaq/tools/sandboxaq-model/tool.yaml:1 'tool.yaml' is not an approved file type for the catalog. Permitted extensions and filenames are listed in '.github/policy/source-allowlist.yaml'. If this file type is legitimately needed, open a PR adding it to the allowlist (CODEOWNERS-gated) and explain the use case.

How to fix: Rename the file to an approved type, remove it, or extend .github/policy/source-allowlist.yaml in a separate CODEOWNERS-reviewed PR.

Guidance: Open the authoring guide
POL-019 .github/policy/contact-network.json:1 Contact network policy could not be loaded: [Errno 2] No such file or directory: '/home/runner/work/discovery/discovery/pr/.github/policy/contact-network.json'

How to fix: Use an address whose fully qualified domain publishes a non-null MX record, or an A/AAAA record permitted by implicit-MX fallback. This check validates the domain only; it does not prove mailbox ownership.

Guidance: Open the authoring guide

Once all issues are resolved, push a new commit to re-trigger this check.
When the pr-review validator passes, the pr-validation-passed label will be applied and the maintainers will be auto-requested for review. Note: other status checks (unit-tests, schema regression, etc.) report separately — see the full status rollup at the bottom of this PR.

See the authoring guides for end-to-end walkthroughs.

@github-actions github-actions Bot removed update-branch PR branch is behind base — please update 3p-contribution Authored by a third-party partner (party='3p' in metadata) pr-validation-failed The pr-review workflow's validator failed; see inline comments. contains-dockerfile PR adds, modifies, renames, or removes a Dockerfile contains-code PR includes source-code changes labels Sep 29, 2026
@github-actions

Copy link
Copy Markdown

✅ Automated Check Results — All checks passed

All structural, schema, content, documentation, and secret scan checks passed.

This PR is ready for human review. The maintainers have been automatically requested.

Reminder: 1 approval from a CODEOWNERS reviewer is required before this PR can be merged.

sandboxaq-model tool:
- Add FOUNDRY_API_STYLE (azure-openai default, or serverless with Bearer
  auth and /chat/completions) and fall back to the default api-version
  when FOUNDRY_API_VERSION is empty.
- Raise RuntimeError without the endpoint URL on HTTP and transport
  errors, so reporting errors verbatim cannot leak the endpoint.
- Tolerate null message/content and return finish_reason.
- Document supplying credentials as deploy-time environment variables,
  matching the PubMed agent.

aqcat:
- Use the platform's `aqcat` tool; drop aqcat_compare and run one job
  per surface with identical settings for comparisons.
- State the 5-placement cap and the 1 RU per bulk-facet-adsorbate cost.

aqpotency:
- Describe the real upload flow (upload_files session, user upload,
  check_upload_session, upload_session_id) and drop upload tools the
  agent cannot use.
- Resolve the conflicting value/similarity reporting order.

Both MCP agents check job status once per user request instead of
polling with waits they cannot perform, and the READMEs state that
pre-submission approval is enforced by instructions, not the platform.
@sravankumarux
sravankumarux requested a review from a team as a code owner October 6, 2026 18:04
@github-actions github-actions Bot added 3p-contribution Authored by a third-party partner (party='3p' in metadata) contains-code PR includes source-code changes contains-dockerfile PR adds, modifies, renames, or removes a Dockerfile pr-validation-passed The pr-review workflow's validator passed. Other status checks report separately. and removed 3p-contribution Authored by a third-party partner (party='3p' in metadata) pr-validation-passed The pr-review workflow's validator passed. Other status checks report separately. contains-dockerfile PR adds, modifies, renames, or removes a Dockerfile contains-code PR includes source-code changes labels Oct 6, 2026
Verified against the SandboxAQ AI Simulation Platform MCP server's tool
schemas.

aqcat:
- Restore AQCat and aqcat_compare; the lowercase name is only a
  list_jobs filter value.
- Describe the real comparison flow: one AQCat job per surface, then
  aqcat_compare on the completed job IDs (no compute, optional baseline).
- Propose the 1,1,1 facet as a stated assumption when none is given.
- Drop spin treatment from the plan; AQCat takes no spin input.

aqpotency:
- Remove AqpotencyScreen and the upload tools. upload_files needs an
  interactive iframe and upload_local_files needs a shell, so a Foundry
  agent cannot upload a library. Document running screens from Claude
  Desktop or claude.ai and retrieving results here.
- Name the three AqpotencyScan panels and require choosing one.
- Update catalog description and tags to match.

Allow get_credit_balance in both agents.
@github-actions github-actions Bot added 3p-contribution Authored by a third-party partner (party='3p' in metadata) contains-code PR includes source-code changes contains-dockerfile PR adds, modifies, renames, or removes a Dockerfile pr-validation-passed The pr-review workflow's validator passed. Other status checks report separately. and removed 3p-contribution Authored by a third-party partner (party='3p' in metadata) pr-validation-passed The pr-review workflow's validator passed. Other status checks report separately. contains-dockerfile PR adds, modifies, renames, or removes a Dockerfile contains-code PR includes source-code changes labels Oct 6, 2026
Live AqpotencyPotency results return structured fields (potency_mean,
potency_sigma, ligand_similarity, ic50_display and range, sigma_band,
confidence_tier), not a prose summary. Quote the IC50 and range from
those fields instead of recomputing them.

A test prediction returned confidence_tier "high" with sigma_band "wide",
so require the tier to be reported alongside the uncertainty and judge
reliability by uncertainty and ligand similarity when they disagree.
@github-actions github-actions Bot removed 3p-contribution Authored by a third-party partner (party='3p' in metadata) pr-validation-passed The pr-review workflow's validator passed. Other status checks report separately. contains-dockerfile PR adds, modifies, renames, or removes a Dockerfile labels Oct 6, 2026
A live run of six concurrent AQCat jobs took about 4.8 minutes each,
so tell users to expect a few minutes, longer when several jobs run
together, instead of a minute or two.

@ryansok ryansok left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3p-contribution Authored by a third-party partner (party='3p' in metadata) contains-code PR includes source-code changes contains-dockerfile PR adds, modifies, renames, or removes a Dockerfile needs-human-review Awaiting human approval pr-validation-passed The pr-review workflow's validator passed. Other status checks report separately.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants