From 13c88800704a9315ee6b3aee6e21653fdcfcc18e Mon Sep 17 00:00:00 2001 From: Sravan Kumar Date: Fri, 9 Oct 2026 13:15:28 -0500 Subject: [PATCH 1/4] Fix SandboxAQ agent READMEs sandboxaq: - Remove the "Which SandboxAQ agent do I want?" table. - Fix the image build step: the Dockerfile is in tools/sandboxaq-model/, so build from there, with --platform linux/amd64 as other catalog agents do (the tool runs on x86-64 Azure VMs). - Fence the architecture diagram and bracket the support email. aqcat, aqpotency: - Drop the link to the sandboxaq agent. --- agents/aqcat/README.md | 2 +- agents/aqpotency/README.md | 2 +- agents/sandboxaq/README.md | 27 +++++++++++---------------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/agents/aqcat/README.md b/agents/aqcat/README.md index b20953e..0577a46 100644 --- a/agents/aqcat/README.md +++ b/agents/aqcat/README.md @@ -10,7 +10,7 @@ This agent gives Discovery users conversational access to that capability. A res **Intended user:** computational chemists, catalysis researchers, and materials scientists doing candidate triage. -**Related agents.** [`aqpotency`](../aqpotency/README.md) covers small-molecule potency and selectivity on the same platform and the same connection. [`sandboxaq`](../sandboxaq/README.md) is separate — it prompts a SandboxAQ model you have subscribed to in Azure AI Foundry, and needs no platform tenant. +**Related agents.** [`aqpotency`](../aqpotency/README.md) covers small-molecule potency and selectivity on the same platform and the same connection. **Successful outcome:** a ranked, correctly-attributed set of adsorption energies with units intact, each reported with its convergence status and the resolved bulk identifier, plus an explicit statement of which systems fall outside the model's applicability. diff --git a/agents/aqpotency/README.md b/agents/aqpotency/README.md index e2982a2..cde81b1 100644 --- a/agents/aqpotency/README.md +++ b/agents/aqpotency/README.md @@ -10,7 +10,7 @@ This agent gives Discovery users conversational access to three framings of that **Intended user:** medicinal chemists, computational chemists, and computational biologists prioritizing compounds and assessing off-target liabilities. -**Related agents.** [`aqcat`](../aqcat/README.md) covers catalysis and surface reactivity on the same platform and the same connection. [`sandboxaq`](../sandboxaq/README.md) is separate — it prompts a SandboxAQ model you have subscribed to in Azure AI Foundry, and needs no platform tenant. +**Related agents.** [`aqcat`](../aqcat/README.md) covers catalysis and surface reactivity on the same platform and the same connection. **Successful outcome:** predicted potencies with uncertainty, correctly attributed to molecule and target, with weakly-supported predictions clearly marked so they are not ranked as though they were confident. diff --git a/agents/sandboxaq/README.md b/agents/sandboxaq/README.md index 0d7dbb8..3676407 100644 --- a/agents/sandboxaq/README.md +++ b/agents/sandboxaq/README.md @@ -14,18 +14,6 @@ endpoint from a Discovery-managed tool container. This deployment includes: - **Tool Definition**: Configuration for the `sandboxaq-model` tool - **Agent Definition**: AI agent configuration for the SandboxAQ agent -### Which SandboxAQ agent do I want? - -Three SandboxAQ agents are published in this catalog. Choose by what you have access to: - -| Agent | Use it when | Requires | -|---|---|---| -| **`sandboxaq`** (this one) | You have subscribed to a SandboxAQ model in Azure AI Foundry and want to prompt it directly | A SandboxAQ model subscription in Foundry | -| [**`aqcat`**](../aqcat/README.md) | You want adsorption energies and surface reactivity for catalysis | A SandboxAQ AI Simulation Platform tenant | -| [**`aqpotency`**](../aqpotency/README.md) | You want small-molecule potency, panel scans, or selectivity | A SandboxAQ AI Simulation Platform tenant | - -This agent is general-purpose inference against a model deployment you control. The other two are domain agents that reach specific scientific tools on the SandboxAQ platform. - ## Prerequisites Before starting the deployment, ensure you have: @@ -40,12 +28,17 @@ Before starting the deployment, ensure you have: ### Step 1: Build and Publish Docker Image -1. **Build the image** from this tool directory: +1. **Build the image** from the tool directory, `tools/sandboxaq-model/`, + which contains the Dockerfile: ```bash - docker build -t sandboxaq-model:latest . + cd tools/sandboxaq-model + docker build --platform linux/amd64 -t sandboxaq-model:latest . ``` + > `--platform linux/amd64` is required when building on Apple Silicon or + > other ARM machines; the tool runs on x86-64 Azure VMs. + 2. **Tag the image** for your Azure Container Registry: ```bash @@ -114,7 +107,9 @@ The SandboxAQ agent provides: This agent operates as a `kind: prompt` agent within Discovery Studio. - User Input → SandboxAQ Agent (LLM) → sandboxaq-model Tool (Container) → Azure AI Foundry → Results +```text +User Input → SandboxAQ Agent (LLM) → sandboxaq-model Tool (Container) → Azure AI Foundry → Results +``` - **Model:** Configured via the `{{CHAT-MODEL}}` parameter at deploy time - **Tool:** `sandboxaq-model` container exposing a `python3` code environment @@ -166,7 +161,7 @@ endpoint URL or credential. For issues or questions with this agent, contact SandboxAQ: -SandboxAQ contact: support@sandboxaq.com +SandboxAQ contact: For platform issues, open a GitHub issue: From a9fce3ecf379908df4edd6549cfcd97bbf5ecd4a Mon Sep 17 00:00:00 2001 From: Sravan Kumar Date: Fri, 9 Oct 2026 13:22:14 -0500 Subject: [PATCH 2/4] Clarify sandboxaq build step and sensitive-data guidance - Build from the repository root via agents/sandboxaq with the tool directory as the build context, so the starting directory is explicit. - Describe the sensitive-data behavior as agent instructions rather than platform-enforced controls; the agent runs with human-in-the-loop and tool confirmation disabled. --- agents/sandboxaq/README.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/agents/sandboxaq/README.md b/agents/sandboxaq/README.md index 3676407..4fd76b2 100644 --- a/agents/sandboxaq/README.md +++ b/agents/sandboxaq/README.md @@ -28,12 +28,14 @@ Before starting the deployment, ensure you have: ### Step 1: Build and Publish Docker Image -1. **Build the image** from the tool directory, `tools/sandboxaq-model/`, - which contains the Dockerfile: +1. **Build the image**, starting from the repository root. The Dockerfile is + in `agents/sandboxaq/tools/sandboxaq-model/`: ```bash - cd tools/sandboxaq-model - docker build --platform linux/amd64 -t sandboxaq-model:latest . + cd agents/sandboxaq + docker build --platform linux/amd64 \ + -t sandboxaq-model:latest \ + tools/sandboxaq-model ``` > `--platform linux/amd64` is required when building on Apple Silicon or @@ -82,8 +84,11 @@ The SandboxAQ agent provides: - **Model Invocation**: Sends prompts to the subscribed SandboxAQ deployment - **Structured Output**: Preserves JSON returned by the endpoint and writes results to `/output/final_results.json` -- **Sensitive-Data Handling**: Applies access, privacy, and human-review - guidance when working with HR or other confidential business data +- **Sensitive-data guidance**: The agent instructions tell it to follow + organizational access and privacy policies, avoid inferring protected + attributes or making employment decisions, identify uncertainty, and request + human review where appropriate. These are behavioral instructions, not + platform-enforced controls. ## Usage From 71e8995b413d64afa1d11ba79760e48d07e43617 Mon Sep 17 00:00:00 2001 From: Sravan Kumar Date: Fri, 9 Oct 2026 15:17:03 -0500 Subject: [PATCH 3/4] Remove SandboxAQ Foundry-model agent Catalog will ship only the MCP-based AQCat and AQPotency agents. --- agents/sandboxaq/README.md | 196 ------------------ agents/sandboxaq/agent.yaml | 78 ------- agents/sandboxaq/metadata.yaml | 15 -- .../tools/sandboxaq-model/Dockerfile | 21 -- .../tools/sandboxaq-model/sandboxaq_utils.py | 128 ------------ .../sandboxaq/tools/sandboxaq-model/tool.yaml | 37 ---- 6 files changed, 475 deletions(-) delete mode 100644 agents/sandboxaq/README.md delete mode 100644 agents/sandboxaq/agent.yaml delete mode 100644 agents/sandboxaq/metadata.yaml delete mode 100644 agents/sandboxaq/tools/sandboxaq-model/Dockerfile delete mode 100644 agents/sandboxaq/tools/sandboxaq-model/sandboxaq_utils.py delete mode 100644 agents/sandboxaq/tools/sandboxaq-model/tool.yaml diff --git a/agents/sandboxaq/README.md b/agents/sandboxaq/README.md deleted file mode 100644 index 4fd76b2..0000000 --- a/agents/sandboxaq/README.md +++ /dev/null @@ -1,196 +0,0 @@ -# SandboxAQ Foundry Model Agent Deployment Guide - -This guide provides step-by-step instructions for deploying the SandboxAQ -Foundry Model tool and its associated agent to the Microsoft Discovery -platform. - -## Overview - -This agent invokes a SandboxAQ model that your organization has subscribed to -through Azure AI Foundry, calling the OpenAI-compatible chat-completions -endpoint from a Discovery-managed tool container. This deployment includes: - -- **Dockerfile**: Used for creation of the SandboxAQ model tool container image -- **Tool Definition**: Configuration for the `sandboxaq-model` tool -- **Agent Definition**: AI agent configuration for the SandboxAQ agent - -## Prerequisites - -Before starting the deployment, ensure you have: - -1. Access to Microsoft Discovery platform -2. An active SandboxAQ model subscription deployed in Azure AI Foundry -3. Azure Container Registry (ACR) with appropriate permissions -4. Docker installed locally for image building -5. Azure CLI or PowerShell for resource management - -## Build Docker Image - -### Step 1: Build and Publish Docker Image - -1. **Build the image**, starting from the repository root. The Dockerfile is - in `agents/sandboxaq/tools/sandboxaq-model/`: - - ```bash - cd agents/sandboxaq - docker build --platform linux/amd64 \ - -t sandboxaq-model:latest \ - tools/sandboxaq-model - ``` - - > `--platform linux/amd64` is required when building on Apple Silicon or - > other ARM machines; the tool runs on x86-64 Azure VMs. - -2. **Tag the image** for your Azure Container Registry: - - ```bash - docker tag sandboxaq-model:latest mycontainerregistry.azurecr.io/sandboxaq-model:latest - ``` - - > Replace `mycontainerregistry` with your actual ACR name - -3. **Login to Azure Container Registry**: - - ```bash - az acr login --name mycontainerregistry - ``` - -4. **Push the image** to your container registry: - - ```bash - docker push mycontainerregistry.azurecr.io/sandboxaq-model:latest - ``` - -## File Structure - -```text -sandboxaq/ -├── agent.yaml # Agent configuration (YAML) -├── metadata.yaml # Catalog metadata -├── tools/ -│ └── sandboxaq-model/ -│ ├── Dockerfile # Container image definition -│ ├── tool.yaml # Tool configuration (YAML) -│ └── sandboxaq_utils.py # Foundry client helper module -└── README.md # This deployment guide -``` - -## Key Configuration Details - -### Agent Capabilities - -The SandboxAQ agent provides: - -- **Model Invocation**: Sends prompts to the subscribed SandboxAQ deployment -- **Structured Output**: Preserves JSON returned by the endpoint and writes - results to `/output/final_results.json` -- **Sensitive-data guidance**: The agent instructions tell it to follow - organizational access and privacy policies, avoid inferring protected - attributes or making employment decisions, identify uncertainty, and request - human review where appropriate. These are behavioral instructions, not - platform-enforced controls. - -## Usage - -### Basic Queries - -| Prompt | Description | -|--------|-------------| -| "Run the SandboxAQ model on this prompt and return the result as JSON." | Direct invocation | -| "Summarize this HR policy using the subscribed SandboxAQ deployment." | Summarization | -| "Ask the SandboxAQ model to classify these support tickets." | Classification | - -### Advanced Queries - -| Prompt | Description | -|--------|-------------| -| "Run this prompt at temperature 0.7 and cap the output at 1000 tokens." | Tuned sampling parameters | -| "Use a system prompt of 'You are a concise policy analyst' for this request." | Custom system instruction | -| "Invoke the model on each of these five prompts and collect the results." | Batch invocation in one script | - -## Architecture - -This agent operates as a `kind: prompt` agent within Discovery Studio. - -```text -User Input → SandboxAQ Agent (LLM) → sandboxaq-model Tool (Container) → Azure AI Foundry → Results -``` - -- **Model:** Configured via the `{{CHAT-MODEL}}` parameter at deploy time -- **Tool:** `sandboxaq-model` container exposing a `python3` code environment - -The tool exposes a Python code environment rather than a fixed action. The -agent writes a script that imports `sandboxaq_utils` and calls -`invoke_model(prompt, system_prompt=..., temperature=..., max_tokens=...)`, -which returns a dict with `model`, `content`, `finish_reason`, `usage`, and -`raw_response`. - -Prompts therefore travel as Python string literals and are never interpolated -into a shell command, so text containing apostrophes, double quotes, `$`, or -newlines reaches the deployment unmodified. - -## Configuration - -| Parameter | Description | Example | -|---|---|---| -| `{{CHAT-MODEL}}` | Azure AI Foundry model deployment name for the agent | `gpt-4o` | - -The tool reads its endpoint and credential from runtime environment -variables. They are deliberately absent from `tool.yaml`: the tool schema only -supports static, committed values, and the credential must never be committed. -Set them in your deployment's environment-variable configuration (for -example a `sandboxaq-model-EnvVars.json` file), as the PubMed agent does: - -```json -{ - "FOUNDRY_ENDPOINT": "https://.openai.azure.com/openai", - "FOUNDRY_API_KEY": "", - "FOUNDRY_DEPLOYMENT": "" -} -``` - -| Environment variable | Required | Description | -|---|---:|---| -| `FOUNDRY_ENDPOINT` | Yes | Endpoint base URL. For `azure-openai`, include the `/openai` API base; for `serverless`, the URL that `/chat/completions` is appended to | -| `FOUNDRY_API_KEY` | Yes | Secret for the subscribed deployment | -| `FOUNDRY_DEPLOYMENT` | `azure-openai`: Yes; `serverless`: No | SandboxAQ model deployment name. Sent as the `model` field for `serverless` | -| `FOUNDRY_API_STYLE` | No | `azure-openai` (default): `/deployments/{name}/chat/completions` with an `api-key` header. `serverless`: `/chat/completions` with a Bearer token, for Foundry serverless and Foundry Models endpoints | -| `FOUNDRY_API_VERSION` | No | API version. Defaults to `2024-10-21` for `azure-openai`; omitted for `serverless` unless set | - -The endpoint must be reachable from the Discovery tool container. Error -messages from the tool report the HTTP status and response body but never the -endpoint URL or credential. - -## Support - -For issues or questions with this agent, contact SandboxAQ: - - -SandboxAQ contact: - -For platform issues, open a GitHub issue: - - -## Tools - -| Tool | Path | Description | -|---|---|---| -| `sandboxaq-model` | `tools/sandboxaq-model/` | Invokes a subscribed SandboxAQ model through its Azure AI Foundry OpenAI-compatible chat-completions endpoint. | - -## Known Limitations - -- Requires an existing SandboxAQ subscription in Azure AI Foundry; the agent - cannot provision or discover deployments on your behalf. -- Supports the chat-completions API surface only. Embeddings, batch, and - streaming endpoints are not exposed. -- Credentials are supplied as environment variables on the deployed tool, so - rotating a key requires updating the tool configuration. -- For sensitive HR data, apply your organization's privacy, access-control, - and human-review requirements. This agent does not make employment - decisions. - -## Contributing - -This project welcomes contributions and suggestions. Please see the -repository's top-level [CONTRIBUTING guidelines](https://github.com/microsoft/discovery/blob/main/CONTRIBUTING.md) -for details on how to contribute. diff --git a/agents/sandboxaq/agent.yaml b/agents/sandboxaq/agent.yaml deleted file mode 100644 index 46ebc0f..0000000 --- a/agents/sandboxaq/agent.yaml +++ /dev/null @@ -1,78 +0,0 @@ -kind: prompt -name: sandboxaq -displayName: SandboxAQ Foundry Model Agent -description: > - Invokes subscribed SandboxAQ models through an Azure AI Foundry endpoint. -model: - id: '{{CHAT-MODEL}}' - options: - temperature: 0 - topP: 0 - maxOutputTokens: 4096 -instructions: |- - You are the SandboxAQ Foundry Model Agent. You reach the subscribed - SandboxAQ deployment by writing Python scripts that run in the tool's code - environment. - - # INSTALLED PYTHON PACKAGES - `requests`, `json` (stdlib), and `sandboxaq_utils` (custom module). - **NOT available:** pandas, numpy, rdkit, matplotlib. Do NOT import these. - - **ALWAYS use `from sandboxaq_utils import invoke_model`** -- this is the - ONLY supported way to call the deployment. Never build the request URL, - headers, or credential yourself, and never invoke the model through a shell - command; passing prompt text through a shell corrupts any prompt containing - quotes or `$`. - - ## CRITICAL RULES - - 1. Put the prompt in a Python variable, not in a shell command. Triple-quoted - string literals handle apostrophes, quotes, and newlines correctly. - 2. Write results to `/output/final_results.json` with `save_json()`. - 3. Do not claim a model was invoked unless the script completed and returned - a response. - 4. Keep user inputs and model outputs clearly separated in your report. - Preserve structured output when the endpoint returns JSON. - 5. Never expose endpoint URLs, API keys, authorization headers, or other - deployment secrets -- not in scripts, logs, or your reply. - 6. If the request is missing information the endpoint requires, ask one - focused clarifying question before running anything. - - ### Script template - - ```python - from sandboxaq_utils import invoke_model, save_json - - prompt = """Summarize the attached policy in five bullet points.""" - - result = invoke_model( - prompt, - system_prompt="You are a concise policy analyst.", - temperature=0, - max_tokens=4096, - ) - - print(result["content"]) - save_json(result, "/output/final_results.json") - ``` - - `invoke_model` returns a dict with `model`, `content`, `finish_reason`, - `usage`, and `raw_response`. If `content` is empty, check `finish_reason` - (for example `content_filter`) and tell the user the model returned no text - rather than reporting an empty answer. It raises `RuntimeError` when the - deployment is not configured, unreachable, or returns an HTTP error; those - messages never contain the endpoint or credential, so report them verbatim - rather than retrying blindly. - - For HR or other sensitive business data: - - Follow the user's organization's access and data-handling policies. - - Do not infer protected attributes or make employment decisions. - - State when the model response is uncertain or requires human review. - - Return only the minimum sensitive information needed for the request. -discoveryExtensions: - humanInTheLoop: Disabled - tools: - - toolId: '{{sandboxaqModelToolId}}' - confirmation: Disabled - disableDataHandlingTools: false - disableDiscoveryInjectedTools: false diff --git a/agents/sandboxaq/metadata.yaml b/agents/sandboxaq/metadata.yaml deleted file mode 100644 index 1a100e1..0000000 --- a/agents/sandboxaq/metadata.yaml +++ /dev/null @@ -1,15 +0,0 @@ -name: sandboxaq -type: agent -version: 1.0.0 -associated_tools: - - agents/sandboxaq/tools/sandboxaq-model -publisher: - name: SandboxAQ - contact: support@sandboxaq.com - support_url: https://www.sandboxaq.com/contact - party: 3p -description: > - Invokes SandboxAQ models subscribed through Azure AI Foundry for secure, - structured inference workflows. -tags: - - language-model diff --git a/agents/sandboxaq/tools/sandboxaq-model/Dockerfile b/agents/sandboxaq/tools/sandboxaq-model/Dockerfile deleted file mode 100644 index 5bd04db..0000000 --- a/agents/sandboxaq/tools/sandboxaq-model/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM mcr.microsoft.com/azurelinux/base/python:3.12 - -WORKDIR /app - -# System update + TLS certificates (MUST be first RUN for layer sharing) -RUN tdnf -y update && \ - tdnf -y install ca-certificates && \ - update-ca-trust && \ - tdnf clean all -RUN pip3 install --no-cache-dir requests - -# Create working directories -RUN mkdir -p /input /output /workdir - -# /app: safe from volume mounts, reachable via PYTHONPATH -COPY sandboxaq_utils.py /app/ - -WORKDIR /workdir -ENV PYTHONPATH="/app" - -CMD ["/bin/bash"] diff --git a/agents/sandboxaq/tools/sandboxaq-model/sandboxaq_utils.py b/agents/sandboxaq/tools/sandboxaq-model/sandboxaq_utils.py deleted file mode 100644 index 0efe073..0000000 --- a/agents/sandboxaq/tools/sandboxaq-model/sandboxaq_utils.py +++ /dev/null @@ -1,128 +0,0 @@ -"""Helpers for calling a subscribed SandboxAQ model through Azure AI Foundry. - -Agent scripts import from this module rather than shelling out, so prompt text -is never interpreted by a shell: - - from sandboxaq_utils import invoke_model, save_json - - result = invoke_model("Summarize this policy") - save_json(result, "/output/final_results.json") -""" - -import json -import os - -import requests - -DEFAULT_API_VERSION = "2024-10-21" -DEFAULT_TIMEOUT_SECONDS = 300 - - -def required_env(name): - value = os.environ.get(name) - if not value: - raise RuntimeError(f"Required environment variable is not set: {name}") - return value - - -def build_request(deployment): - """Return the chat-completions URL and auth headers for the configured endpoint. - - FOUNDRY_API_STYLE selects the request shape: - - `azure-openai` (default): {endpoint}/deployments/{deployment}/chat/completions - with an `api-key` header. The endpoint includes the `/openai` API base. - - `serverless`: {endpoint}/chat/completions with a Bearer token, for - Foundry serverless / Foundry Models endpoints. The deployment, when - set, is sent as the `model` field. - """ - endpoint = required_env("FOUNDRY_ENDPOINT").rstrip("/") - api_key = required_env("FOUNDRY_API_KEY") - style = (os.environ.get("FOUNDRY_API_STYLE") or "azure-openai").strip().lower() - if style == "azure-openai": - if not deployment: - raise RuntimeError( - "Required environment variable is not set: FOUNDRY_DEPLOYMENT" - ) - api_version = os.environ.get("FOUNDRY_API_VERSION") or DEFAULT_API_VERSION - url = ( - f"{endpoint}/deployments/{deployment}/chat/completions" - f"?api-version={api_version}" - ) - auth = {"api-key": api_key} - elif style == "serverless": - api_version = os.environ.get("FOUNDRY_API_VERSION") - url = f"{endpoint}/chat/completions" - if api_version: - url += f"?api-version={api_version}" - auth = {"Authorization": f"Bearer {api_key}"} - else: - raise RuntimeError( - "FOUNDRY_API_STYLE must be 'azure-openai' or 'serverless'" - ) - return url, {**auth, "Content-Type": "application/json"} - - -def invoke_model( - prompt, - system_prompt="", - temperature=0, - max_tokens=4096, - timeout=DEFAULT_TIMEOUT_SECONDS, -): - """Send a prompt to the configured SandboxAQ deployment. - - Returns a dict with `model`, `content`, `finish_reason`, `usage`, and - `raw_response`. `content` is an empty string when the endpoint returns no - text (for example a `content_filter` finish reason). Raises RuntimeError on - missing configuration, transport or HTTP failures, and empty responses; - error messages never include the endpoint URL or credential. - """ - deployment = os.environ.get("FOUNDRY_DEPLOYMENT", "") - url, headers = build_request(deployment) - messages = [] - if system_prompt: - messages.append({"role": "system", "content": system_prompt}) - messages.append({"role": "user", "content": prompt}) - body = { - "messages": messages, - "temperature": temperature, - "max_tokens": max_tokens, - } - if deployment and "Authorization" in headers: - body["model"] = deployment - try: - response = requests.post(url, headers=headers, json=body, timeout=timeout) - except requests.RequestException as error: - # requests embeds the URL in its messages; report only the error type. - raise RuntimeError( - f"Could not reach the SandboxAQ deployment ({type(error).__name__})" - ) from None - if not response.ok: - detail = response.text[:500] if response.text else "" - raise RuntimeError( - f"SandboxAQ deployment returned HTTP {response.status_code} " - f"{response.reason}: {detail}" - ) - payload = response.json() - choices = payload.get("choices") - if not choices: - raise RuntimeError("Foundry response did not contain any choices") - choice = choices[0] or {} - message = choice.get("message") or {} - return { - "model": payload.get("model") or deployment, - "content": message.get("content") or "", - "finish_reason": choice.get("finish_reason"), - "usage": payload.get("usage"), - "raw_response": payload, - } - - -def save_json(data, path): - """Write `data` to `path` as UTF-8 JSON, creating parent directories.""" - parent = os.path.dirname(path) - if parent: - os.makedirs(parent, exist_ok=True) - with open(path, "w", encoding="utf-8") as handle: - json.dump(data, handle, indent=2, ensure_ascii=False) - return path diff --git a/agents/sandboxaq/tools/sandboxaq-model/tool.yaml b/agents/sandboxaq/tools/sandboxaq-model/tool.yaml deleted file mode 100644 index a789fe1..0000000 --- a/agents/sandboxaq/tools/sandboxaq-model/tool.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: sandboxaq-model -description: > - Invokes a subscribed SandboxAQ model through its Azure AI Foundry - OpenAI-compatible chat-completions endpoint. -version: 1.0.0 -license: MIT -category: "Model Inference" -infra: - - name: worker - infra_type: container - image: - acr: "{name}.azurecr.io/sandboxaq-model:latest" - compute: - min_resources: - cpu: 1 - ram: 4Gi - storage: 8Gi - gpu: 0 - max_resources: - cpu: 2 - ram: 8Gi - storage: 32Gi - gpu: 0 - infiniband: false - recommended_sku: - - Standard_D4s_v6 - pool_type: static - pool_size: 1 -code_environments: - - language: python3 - command: "python3 -u \"/{{scriptName}}\"" - description: > - Python code environment on the SandboxAQ model container image. Scripts - import `sandboxaq_utils` to reach the configured Azure AI Foundry - deployment; the endpoint, deployment name, and credential are supplied - as runtime environment variables. - infra_node: worker From f113447f9b2acc4a5edfb4fb2a0d56bbdf162ce7 Mon Sep 17 00:00:00 2001 From: Sravan Kumar Date: Thu, 15 Oct 2026 12:40:32 -0500 Subject: [PATCH 4/4] Describe per-user OAuth sign-in in AQCat and AQPotency READMEs Replace the header-credential and service-token guidance with per-user OAuth sign-in, note that the agents cannot connect from Discovery until it supports per-user MCP sign-in, and describe the Foundry redirect URL requirement. --- agents/aqcat/README.md | 11 ++++++----- agents/aqpotency/README.md | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/agents/aqcat/README.md b/agents/aqcat/README.md index 0577a46..09db2e0 100644 --- a/agents/aqcat/README.md +++ b/agents/aqcat/README.md @@ -40,9 +40,10 @@ The agent holds no compute of its own and ships no container. It is a prompt age - An Azure AI Foundry project with a chat model deployment, supplied as `{{CHAT-MODEL}}`. - Access to a SandboxAQ AI Simulation Platform tenant with AQCat enabled. Contact if your organization does not have one. -- The MCP server URL for your tenant, and a credential that server accepts as a **request header**, stored as a connection in your Azure AI Foundry project. The agent references that connection by name; the credential never enters the agent definition. +- The MCP server URL for your tenant, configured as a connection in your Azure AI Foundry project. The agent references that connection by name. +- A SandboxAQ account for each user. Sign-in is per-user OAuth; no API keys or service tokens are issued or accepted. -> **Authentication note.** Foundry's MCP tool authenticates with a stored connection or static headers; it cannot complete an interactive browser OAuth flow. If your tenant is configured for interactive consent only, request a service token or equivalent header credential from your platform administrator before deploying. +> **Authentication note.** Each user signs in with their own SandboxAQ account through a browser OAuth flow. Discovery does not yet support per-user sign-in for MCP tools, so this agent cannot connect from Discovery until it does; until then, validate it in the Azure AI Foundry playground. Foundry supports browser sign-in, but each connection needs its own OAuth client, and the platform must accept the redirect URL Foundry generates for that connection (these begin with `https://global.consent.azure-apim.net/redirect/`). Contact to have a redirect URL accepted. ## Configuration @@ -50,9 +51,9 @@ The agent holds no compute of its own and ships no container. It is a prompt age |---|---|---| | `{{CHAT-MODEL}}` | Azure AI Foundry chat model deployment name | `gpt-4o-deployment` | | `{{AQ_MCP_SERVER_URL}}` | Base URL of your tenant's SandboxAQ AI Simulation Platform MCP server | `https://mcp.demo.aisim.sandboxaq.com` | -| `{{AQ_MCP_CONNECTION}}` | Name of the connection in your Foundry project holding the MCP server credential | `sandboxaq-aisim` | +| `{{AQ_MCP_CONNECTION}}` | Name of the MCP server connection in your Foundry project | `sandboxaq-aisim` | -Create the connection in your own Azure AI Foundry project before deploying. The agent definition references it by name and never carries the credential itself, so no secret appears in this catalog entry or in your deployed agent's configuration. +Create the connection in your own Azure AI Foundry project before deploying. The agent definition references it by name, so no secret appears in this catalog entry or in your deployed agent's configuration. ## Usage @@ -103,7 +104,7 @@ For comparative questions the agent submits one `AQCat` job per candidate surfac - **Applicability is bounded by training data.** Unusual elements, heavily distorted cells, and exotic oxidation states may produce confident-looking numbers with no basis. The agent flags these where it can recognize them, but the boundary is not sharply defined and the check is not exhaustive. - **Asynchronous jobs may outlive a conversation.** Long relaxations will not complete within a single turn; the agent returns a job identifier for later retrieval. - **No offline mode.** Every calculation requires network access to the platform, and the agent has no local fallback. -- **Interactive-OAuth tenants are not supported** without a header credential — see the authentication note under Prerequisites. +- **Not yet usable from Discovery.** Sign-in is per-user OAuth, which Discovery does not yet support for MCP tools — see the authentication note under Prerequisites. - **The `aqcat-adsorption-spin` skill does not transfer.** Discovery has no skill loader; the workflow it encodes is reproduced in this agent's `instructions` block and may diverge from the skill over time. ## Support diff --git a/agents/aqpotency/README.md b/agents/aqpotency/README.md index cde81b1..a1c9997 100644 --- a/agents/aqpotency/README.md +++ b/agents/aqpotency/README.md @@ -39,10 +39,11 @@ The agent holds no compute of its own and ships no container. It is a prompt age - An Azure AI Foundry project with a chat model deployment, supplied as `{{CHAT-MODEL}}`. - Access to a SandboxAQ AI Simulation Platform tenant with AQPotency enabled. Contact if your organization does not have one. -- The MCP server URL for your tenant, and a credential that server accepts as a **request header**, stored as a connection in your Azure AI Foundry project. The agent references that connection by name; the credential never enters the agent definition. +- The MCP server URL for your tenant, configured as a connection in your Azure AI Foundry project. The agent references that connection by name. +- A SandboxAQ account for each user. Sign-in is per-user OAuth; no API keys or service tokens are issued or accepted. - Awareness of your organization's data-handling policy for proprietary chemical matter: the SMILES you submit are sent to the platform. -> **Authentication note.** Foundry's MCP tool authenticates with a stored connection or static headers; it cannot complete an interactive browser OAuth flow. If your tenant is configured for interactive consent only, request a service token or equivalent header credential from your platform administrator before deploying. +> **Authentication note.** Each user signs in with their own SandboxAQ account through a browser OAuth flow. Discovery does not yet support per-user sign-in for MCP tools, so this agent cannot connect from Discovery until it does; until then, validate it in the Azure AI Foundry playground. Foundry supports browser sign-in, but each connection needs its own OAuth client, and the platform must accept the redirect URL Foundry generates for that connection (these begin with `https://global.consent.azure-apim.net/redirect/`). Contact to have a redirect URL accepted. ## Configuration @@ -50,9 +51,9 @@ The agent holds no compute of its own and ships no container. It is a prompt age |---|---|---| | `{{CHAT-MODEL}}` | Azure AI Foundry chat model deployment name | `gpt-4o-deployment` | | `{{AQ_MCP_SERVER_URL}}` | Base URL of your tenant's SandboxAQ AI Simulation Platform MCP server | `https://mcp.demo.aisim.sandboxaq.com` | -| `{{AQ_MCP_CONNECTION}}` | Name of the connection in your Foundry project holding the MCP server credential | `sandboxaq-aisim` | +| `{{AQ_MCP_CONNECTION}}` | Name of the MCP server connection in your Foundry project | `sandboxaq-aisim` | -Create the connection in your own Azure AI Foundry project before deploying. The agent definition references it by name and never carries the credential itself, so no secret appears in this catalog entry or in your deployed agent's configuration. +Create the connection in your own Azure AI Foundry project before deploying. The agent definition references it by name, so no secret appears in this catalog entry or in your deployed agent's configuration. ## Usage @@ -111,7 +112,7 @@ Provided by the SandboxAQ AI Simulation Platform MCP server; no container images - **Accession mapping is a failure mode.** Prose target names must be resolved to accessions; the agent confirms its intended accession rather than assuming, but a wrong accession produces a plausible number for the wrong protein. - **Jobs can outlive a conversation.** Panel scans in particular may not complete within a turn; the agent returns a job identifier for later retrieval. - **Submitted molecules leave your environment.** Every prediction sends chemical matter to the platform. Confirm this is permitted under your organization's data-handling policy before submitting proprietary structures. -- **Interactive-OAuth tenants are not supported** without a header credential — see the authentication note under Prerequisites. +- **Not yet usable from Discovery.** Sign-in is per-user OAuth, which Discovery does not yet support for MCP tools — see the authentication note under Prerequisites. ## Support