AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
Foundry IQ provides a structured framework for creating, diagnosing, and connecting knowledge bases to AI agents. It supports making local or Blob-based documents searchable, managing multi-source knowledge configurations, and retrieving information with citations. The skill emphasizes strict adherence to defined procedures for service discovery, resource creation, and troubleshooting to ensure reliable agent-knowledge integration.
What it does
- Creates searchable knowledge bases from local or Azure Blob storage documents.
- Connects existing knowledge bases to AI agents.
- Diagnoses issues with knowledge base configurations or unsupported connectors.
- Retrieves information from knowledge bases with source citations.
- Manages the lifecycle of search services and knowledge sources.
- Routes requests based on specific operational needs rather than source counts.
When to use it
- When you need to make local or cloud-stored documents searchable by an AI agent.
- When connecting an existing knowledge base to a new or current agent.
- When troubleshooting or diagnosing a knowledge base configuration.
- When you need to create a new search service or knowledge source.
- When performing retrieval tasks that require citations from a knowledge base.
Advantages
- Provides a clear, procedural approach to knowledge base management.
- Ensures consistent handling of multi-source knowledge configurations.
- Includes built-in diagnostic paths for troubleshooting.
- Supports secure, citation-backed retrieval for agent responses.
- Prevents unauthorized or unsupported configuration changes.
Usage examples
- “Create a new knowledge base from my Azure Blob container.”
- The agent will initiate the knowledge base creation procedure, validating the source and setting up the necessary search indexing.
- “Connect my existing knowledge base to the current agent.”
- The agent will follow the connection workflow to link the specified knowledge base to the agent's retrieval pipeline.
- “Why is my multi-source knowledge base failing to index?”
- The agent will trigger the diagnostic procedure to identify configuration drifts or unsupported connector issues.
- “Retrieve information about project timelines from the knowledge base.”
- The agent will query the knowledge base and provide an answer with citations from the source documents.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/microsoft/foundry-iq/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip foundry-iq.zip -d .agents/skills
Documentation by Microsoft
Foundry IQ
Read one procedure before questions/actions; invocation is not a read.
Read the owning procedure before blocked/unsupported responses too.
Before mutation plans/approval, successfully read its required pre-action references, selected
branches only. Do not reload successful reads. On failure, try only permitted
bounded exact-path reads with any supported reader; never bypass restrictions
or search broadly. If still unavailable: blocked: reference-unavailable, name
missing references and inability to plan. Never invent requirements/plans.
Failures first.
Cleanup and receipt-backed execution go directly to their lifecycle/producer owner; do not reopen Search intake, provisioning or hardening.
Before expensive service discovery, reuse supplied resource/intent; otherwise ask one early USE EXISTING / FIND CANDIDATES / CREATE NEW choice. Only FIND enumerates; supplied identity uses exact/minimum scoped resolution. CREATE checks its proposed name, not existing-service inventories. Preserve these answers across source/KB/CU/model handoffs; selection is not write approval.
Searchable docs: KB + validated retrieval. Confirm intent once; KS-only must be explicit. Child success is not KB completion. Unclear/compound/mode/completion: read.
Route by requested operation, not existing KB source count. Connecting an existing KB with two or more sources, without changing the KB, uses Connect. Read-only operations use their owning procedure and actual helper constraints; this does not add retrieval modes or supported source kinds. Explicit unsupported provisioning or multi-source KB creation/reconfiguration uses Diagnose and stops before discovery, even when connecting an agent is also requested. This routing takes precedence over classic-search terms (e.g. hybrid search) in compound requests. Never end in a plain refusal: Diagnose gives the boundary, docs pointer and agent handoff; writes still need an approved concrete plan. Do not silently execute only the supported part of a compound request. If existing-KB connection versus KB creation/reconfiguration is unclear, read intent-routing and clarify that scope before Azure discovery. Never infer KB mutation.
| Outcome | Read |
|---|---|
| Cleanup | Plan cleanup |
| Failure/drift | Diagnose |
| Unsupported connector provisioning / multi-source KB creation or reconfiguration | Diagnose |
| Connect | Connect |
| Read KB | Query |
| Search only | Search |
| File KS only | File |
| Blob/ADLS KS only | Blob |
| Searchable/KB | KB |
Generic agents: microsoft-foundry.
Reads: no approval; approve unchanged plans before writes.
Hide hashes. No Search/Storage keys, scope widening, guessed identity/boundaries,
drift repair or joint cleanup/creation approval. Acceptance != success.
Files
- ATTRIBUTION.mdAdded by AutoGineer977 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md3.7 KiB
- agents/connect-hosted-toolbox.md7.8 KiB
- agents/connect-hosted.md7.8 KiB
- agents/connect-prompt-sdk-fallback.md7.8 KiB
- agents/connect.md7.8 KiB
- agents/create-missing-agent.md7.8 KiB
- helpers/_blob_observation.pyScript4.4 KiB
- helpers/_blob_source_read.pyScript39.5 KiB
- helpers/_bootstrap_io.pyScript30.1 KiB
- helpers/_cleanup_dependencies.pyScript27.5 KiB
- helpers/_cleanup_receipts.pyScript13.5 KiB
- helpers/_common.pyScript36.2 KiB
- helpers/_document_adapters.pyScript15.0 KiB
- helpers/_document_limits.pyScript3.9 KiB
- helpers/_embedding.pyScript7.0 KiB
- helpers/_file_inventory.pyScript24.4 KiB
- helpers/_file_source_config.pyScript15.6 KiB
- helpers/_indexer_observation.pyScript7.1 KiB
- helpers/_initial_prompt.pyScript12.5 KiB
- helpers/_private_json.pyScript2.4 KiB
- helpers/_progress.pyScript12.1 KiB
- helpers/_prompt_read.pyScript17.7 KiB
- helpers/_search_read.pyScript6.0 KiB
- helpers/_source_readback.pyScript1.6 KiB
- helpers/blob-contracts.md7.8 KiB
- helpers/blob-cu-contracts.md7.8 KiB
- helpers/blob_inventory.pyScript17.1 KiB
- helpers/blob_recheck.pyScript64.6 KiB
- helpers/blob_source.pyScript35.8 KiB
- helpers/bootstrap-contracts.md7.8 KiB
- helpers/bootstrap_azure.pyScript41.5 KiB
- helpers/cleanup_plan.pyScript41.4 KiB
- helpers/contracts.md7.8 KiB
- helpers/cu_ingestion_auth.pyScript12.5 KiB
- helpers/document-assessment.md7.8 KiB
- helpers/document_assess.pyScript14.0 KiB
- helpers/file-upload-recovery.md7.8 KiB
- helpers/file_cu_canary.pyScript32.7 KiB
- helpers/file_cu_mi.pyScript9.6 KiB
- helpers/file_ingest.pyScript15.4 KiB
- helpers/file_source.pyScript31.7 KiB
- helpers/file_upload.pyScript53.7 KiB
- helpers/hosted_connect.pyScript30.8 KiB
- helpers/kb-contracts.md7.8 KiB
- helpers/knowledge_base_retrieve.pyScript7.7 KiB
- helpers/model-discovery-contracts.md7.8 KiB
- helpers/model-discovery-scopes.md7.8 KiB
- helpers/model_discovery.pyScript23.7 KiB
- helpers/private-artifacts.md7.2 KiB
- helpers/private_artifacts.pyScript4.8 KiB
- helpers/prompt_cleanup.pyScript22.0 KiB
- helpers/prompt_connect.pyScript62.3 KiB
- helpers/requirements-assessment.txt103 B
- helpers/retrieval-verification-contracts.md7.8 KiB
- helpers/retrieval_verify.pyScript19.6 KiB
- helpers/search-intake-contracts.md7.6 KiB
- helpers/search_intake.pyScript18.4 KiB
- helpers/search_reconcile.pyScript59.7 KiB
- helpers/source_vector.pyScript33.2 KiB
- helpers/throttle-recovery.md5.0 KiB
- helpers/vector-contracts.md7.8 KiB
- knowledge-bases/create.md8.1 KiB
- knowledge-bases/retrieve.md7.8 KiB
- knowledge-sources/create-azure-blob.md7.8 KiB
- knowledge-sources/create-file.md7.8 KiB
- lifecycle/cleanup.md7.8 KiB
- references/abstention.md1.0 KiB
- references/blob-binding-evidence.md7.8 KiB
- references/blob-indexer-observation.md7.7 KiB
- references/blob-ingestion-progress.md6.5 KiB
- references/blob-readiness-recheck.md7.8 KiB
- references/blob-vector-readiness.md2.6 KiB
- references/bootstrap-azure.md7.8 KiB
- references/content-fit.md7.8 KiB
- references/cu-ingestion.md7.8 KiB
- references/file-cu-canary.md7.8 KiB
- references/intent-routing.md7.7 KiB
- references/owner.md2.1 KiB
- references/platform-contracts.md7.7 KiB
- references/platform-interfaces.md7.8 KiB
- references/resource-intake.md7.8 KiB
- references/search-substrate.md7.8 KiB
- references/standard-cu.md7.8 KiB
- search-services/create.md7.8 KiB
- troubleshooting/diagnose.md8.7 KiB
helpers/_prompt_read.py
"""Read-only, resource-specific prerequisites for Prompt connection planning/apply."""
from __future__ import annotations
import copy
import json
import re
from importlib.metadata import PackageNotFoundError, version
from typing import Any
from urllib.parse import parse_qs, quote, unquote, urlencode, urlsplit
try:
from ._bootstrap_io import run_cli
from ._common import MANAGEMENT_AUDIENCE, SEARCH_AUDIENCE, HelperFailure, digest, require_allowed_fields
except ImportError:
from _bootstrap_io import run_cli
from _common import MANAGEMENT_AUDIENCE, SEARCH_AUDIENCE, HelperFailure, digest, require_allowed_fields
PROJECT_API = "2025-10-01-preview"
SEARCH_API = "2025-05-01"
ROLE_API = "2022-04-01"
READER_ROLE = "1407120a-92aa-4202-b7e9-c0e197c71c8f"
NAME = re.compile(r"[A-Za-z0-9][A-Za-z0-9_.-]{0,127}")
GUID = re.compile(r"[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}")
SEARCH_ID = re.compile(
r"/subscriptions/[^/?#\s]+/resourceGroups/[^/?#\s]+/"
r"providers/Microsoft\.Search/searchServices/(?P<name>[a-z0-9-]{2,60})",
re.IGNORECASE,
)
def fail(code: str, message: str, response=None, *, status=None, request_id=None) -> HelperFailure:
return HelperFailure(
code, message, blocked_at="reconciliation",
status=response.status if response is not None else status,
request_id=response.request_id if response is not None else request_id,
)
def binding(plan: dict[str, Any]) -> tuple[str, str, str]:
scope = plan["rbac_verified"].get("scope")
match = SEARCH_ID.fullmatch(scope) if isinstance(scope, str) else None
target = urlsplit(plan["connection"]["target"])
parts = target.path.split("/")
if (
match is None or target.hostname != match["name"].lower() + ".search.windows.net"
or len(parts) != 4 or parts[1] != "knowledgebases" or parts[3] != "mcp"
or parse_qs(target.query) != {"api-version": ["2026-08-01-preview"]}
or not NAME.fullmatch(unquote(parts[2]))
):
raise fail("kb-binding-invalid", "Bind an exact Search service ID and preview KB MCP name, not a generated index.")
assignment = plan["rbac_verified"].get("assignment_id")
prefix = scope + "/providers/Microsoft.Authorization/roleAssignments/"
if (
not isinstance(assignment, str) or not assignment.casefold().startswith(prefix.casefold())
or not GUID.fullmatch(assignment[len(prefix):])
):
raise fail("rbac-scope-invalid", "Select one exact Search-service-scoped role assignment resource ID.")
return scope, "https://" + target.hostname, unquote(parts[2])
def get_object(url, token, transport, *, absent=False, label="resource"):
try:
result = transport(
"GET", url, token, follow_redirects=False, max_response_bytes=1024 * 1024,
)
except HelperFailure as error:
if absent and error.http_status == 404 and not error.partial:
return None, [error.request_id] if error.request_id else []
raise
if result.status == 404 and absent:
return None, [result.request_id] if result.request_id else []
if result.status != 200:
raise fail(label + "-unavailable", "Exact " + label + " read failed; no fallback or inferred absence.", result)
if not isinstance(result.body, dict) or not result.body:
raise fail(label + "-readback-invalid", "Exact " + label + " readback must be a nonempty object.", result)
return result.body, [result.request_id] if result.request_id else []
def cli_context(project_id, *, cli=run_cli):
rc, out, _ = cli(["account", "show"], 60)
if rc:
raise fail("cli-context-unavailable", "The selected signed-in Azure CLI context could not be read.")
try:
value = json.loads(out)
except (UnicodeError, ValueError) as error:
raise fail("cli-context-invalid", "Azure CLI context is malformed.") from error
user = value.get("user") if isinstance(value, dict) else None
if (
not isinstance(user, dict) or user.get("type") not in {"user", "servicePrincipal"}
or not isinstance(user.get("name"), str) or not 1 <= len(user["name"]) <= 256
or value.get("environmentName") != "AzureCloud"
or str(value.get("state", "")).casefold() != "enabled"
or str(value.get("id", "")).casefold() != project_id.split("/")[2].casefold()
or not isinstance(value.get("tenantId"), str) or not GUID.fullmatch(value["tenantId"])
):
raise fail("cli-context-conflict", "Select the project's enabled subscription and tenant without changing identity.")
return {"subscription_id": value["id"].lower(), "tenant_id": value["tenantId"].lower(),
"principal": user["name"], "principal_type": user["type"]}
def kb_state(value, name):
if value.get("name") != name:
raise fail("kb-identity-mismatch", "The exact knowledgebases API returned another KB identity.")
sources, models = value.get("knowledgeSources"), value.get("models", [])
if models is None:
models = []
effort = value.get("retrievalReasoningEffort")
mode = value.get("outputMode")
if (
not isinstance(sources, list) or not 1 <= len(sources) <= 200
or any(not isinstance(item, dict) or not isinstance(item.get("name"), str)
or not NAME.fullmatch(item["name"]) for item in sources)
or len({item["name"] for item in sources}) != len(sources)
or not isinstance(models, list) or any(
not isinstance(item, dict) or not isinstance(item.get("@odata.type"), str)
or not item["@odata.type"].strip()
for item in models
)
or not isinstance(effort, dict) or effort.get("kind") not in {"minimal", "low", "medium"}
or mode not in {"extractiveData", "answerSynthesis"}
):
raise fail("kb-configuration-unresolved", "Read complete KB sources, model configuration, reasoning and output; never infer them from generated indexes.")
if not models and (effort["kind"] != "minimal" or mode != "extractiveData"):
raise fail("kb-model-required", "This existing KB configuration requires a KB chat model; connection planning never changes its mode or models.")
material = copy.deepcopy(value)
for field in ("@odata.etag", "description", "tags"):
material.pop(field, None)
return {"name": name, "definition_digest": digest(material)}, {
"source_count": len(sources), "model_configured": bool(models),
"reasoning": effort["kind"], "output": mode,
}
def read_dependencies(plan, *, token_provider, transport, cli=run_cli, capture_context=False):
scope, endpoint, kb_name = binding(plan)
project_id = plan["project_resource_id"]
context = cli_context(project_id, cli=cli) if capture_context else None
token = token_provider(MANAGEMENT_AUDIENCE)
request_ids = []
project, ids = get_object(MANAGEMENT_AUDIENCE + project_id + "?api-version=" + PROJECT_API,
token, transport, label="project")
request_ids.extend(ids)
identity, props = project.get("identity"), project.get("properties")
endpoints = props.get("endpoints") if isinstance(props, dict) else None
identity_types = identity.get("type") if isinstance(identity, dict) else None
identity_types = {item.strip() for item in identity_types.split(",")} if isinstance(identity_types, str) else set()
if (
str(project.get("id", "")).casefold() != project_id.casefold()
or not isinstance(identity, dict) or identity_types not in ({"SystemAssigned"}, {"SystemAssigned", "UserAssigned"})
or not isinstance(identity.get("principalId"), str) or not GUID.fullmatch(identity["principalId"])
or not isinstance(identity.get("tenantId"), str) or not GUID.fullmatch(identity["tenantId"])
or not isinstance(props, dict) or str(props.get("provisioningState", "")).casefold() != "succeeded"
or not isinstance(endpoints, dict) or plan["project_endpoint"].rstrip("/") not in {
value.rstrip("/") for value in endpoints.values() if isinstance(value, str)
}
):
raise fail("project-identity-unverified", "Require the selected ready Foundry PROJECT endpoint and its system-assigned principalId/tenantId.",
request_id=ids[-1] if ids else None)
if context is not None and context["tenant_id"] != identity["tenantId"].lower():
raise fail("cli-context-conflict", "CLI tenant differs from the observed project identity tenant.")
project_state = {"id": project_id, "endpoint": plan["project_endpoint"].rstrip("/"),
"principal_id": identity["principalId"].lower(), "tenant_id": identity["tenantId"].lower()}
search, ids = get_object(MANAGEMENT_AUDIENCE + scope + "?api-version=" + SEARCH_API,
token, transport, label="search")
request_ids.extend(ids)
props = search.get("properties")
if str(search.get("id", "")).casefold() != scope.casefold() or not isinstance(props, dict):
raise fail("search-identity-unverified", "The selected Search resource identity is unresolved.", request_id=ids[-1] if ids else None)
status, provisioning = str(props.get("status", "")).lower(), str(props.get("provisioningState", "")).lower()
if status not in {"running", "provisioning", "degraded"} or provisioning not in {"succeeded", "provisioning"}:
raise fail("search-operation-blocked", "Search is failed, disabled, deleting or unresolved; no connection write is allowed.",
request_id=ids[-1] if ids else None)
warnings = [] if status == "running" and provisioning == "succeeded" else [
"Search is provisioning/degraded; healthy KB GET permits connection configuration only, not readiness or retrieval proof."
]
search_state = {"id": scope, "endpoint": endpoint, "access_digest": digest({
key: props.get(key) for key in ("disableLocalAuth", "authOptions", "publicNetworkAccess", "networkRuleSet", "privateEndpointConnections")
})}
assignment_id = plan["rbac_verified"]["assignment_id"]
assignment, ids = get_object(MANAGEMENT_AUDIENCE + assignment_id + "?api-version=" + ROLE_API,
token, transport, label="role-assignment")
request_ids.extend(ids)
role = assignment.get("properties")
if (
str(assignment.get("id", "")).casefold() != assignment_id.casefold()
or not isinstance(role, dict)
or str(role.get("principalId", "")).casefold() != project_state["principal_id"]
or str(role.get("scope", "")).casefold() != scope.casefold()
or str(role.get("roleDefinitionId", "")).casefold() not in {
"/providers/microsoft.authorization/roledefinitions/" + READER_ROLE,
"/subscriptions/" + scope.split("/")[2].lower() + "/providers/microsoft.authorization/roledefinitions/" + READER_ROLE,
}
or role.get("principalType", "ServicePrincipal") != "ServicePrincipal"
or role.get("condition") not in (None, "")
):
raise fail("project-reader-role-unverified", "Search Index Data Reader must be an unconditional exact-scope grant to the observed PROJECT principal, not the agent identity.",
request_id=ids[-1] if ids else None)
rbac = {"assignment_id": assignment_id, "principal_id": project_state["principal_id"],
"scope": scope, "role_definition_id": READER_ROLE}
url = endpoint + "/knowledgebases('" + quote(kb_name.replace("'", "''"), safe="") + "')?api-version=2026-08-01-preview"
kb, ids = get_object(url, token_provider(SEARCH_AUDIENCE), transport, absent=True, label="knowledge-base")
request_ids.extend(ids)
if kb is None:
raise fail("knowledge-base-absent", "The exact KB is absent; a generated index is not a knowledge base.",
status=404, request_id=ids[-1] if ids else None)
try:
knowledge_base, profile = kb_state(kb, kb_name)
except HelperFailure as error:
error.request_id = ids[-1] if ids else None
raise
state = {"project": project_state, "search": search_state, "rbac": rbac, "knowledge_base": knowledge_base}
if context is not None:
state["cli_context"] = context
expected = plan.get("verified_dependencies")
if expected is not None:
require_allowed_fields(expected, set(state), label="Verified Prompt dependencies")
if expected != state:
raise fail("connection-prerequisite-drift", "Project principal, CLI context, KB binding or exact role changed since planning; refresh before approval.")
elif plan["rbac_verified"].get("verified") is True and (
str(plan["rbac_verified"]["principal_id"]).lower() != project_state["principal_id"]
):
raise fail("project-reader-role-unverified", "The approved principal is not the observed Foundry PROJECT identity.")
return state, profile, warnings, request_ids
ARM_API_VERSION = "2025-10-01-preview"
SDK_MAJOR = "2"
PROJECT_ID = re.compile(
r"^/subscriptions/[^/]+/resourceGroups/[^/]+/providers/"
r"Microsoft\.CognitiveServices/accounts/(?P<account>[^/]+)/projects/"
r"(?P<project>[^/]+)$",
re.IGNORECASE,
)
PROJECT_PATH = re.compile(r"^/api/projects/(?P<project>[^/]+)/?$")
def _project_endpoint(value: Any) -> str:
if not isinstance(value, str):
raise HelperFailure(
"project-endpoint-invalid",
"Project endpoint must be a string.",
blocked_at="input-resolution",
)
try:
parsed = urlsplit(value)
port = parsed.port
except ValueError as error:
raise HelperFailure(
"project-endpoint-invalid", "Project endpoint is malformed.",
blocked_at="input-resolution",
) from error
if (
parsed.scheme != "https"
or not parsed.hostname
or not parsed.hostname.endswith(".services.ai.azure.com")
or PROJECT_PATH.fullmatch(parsed.path) is None
or parsed.query
or parsed.fragment
or parsed.username
or parsed.password
or port not in {None, 443}
):
raise HelperFailure(
"project-endpoint-invalid",
"Project endpoint must be an HTTPS services.ai.azure.com project URL.",
blocked_at="input-resolution",
)
return value.rstrip("/")
def _project_identity(plan: dict[str, Any]) -> tuple[str, str]:
project_id = plan.get("project_resource_id")
match = PROJECT_ID.fullmatch(project_id) if isinstance(project_id, str) else None
if match is None:
raise HelperFailure(
"project-resource-id-invalid",
"project_resource_id must identify one Microsoft Foundry project.",
blocked_at="input-resolution",
)
endpoint = _project_endpoint(plan.get("project_endpoint"))
parsed = urlsplit(endpoint)
endpoint_account = parsed.hostname.removesuffix(".services.ai.azure.com")
endpoint_match = PROJECT_PATH.fullmatch(parsed.path)
if (
endpoint_match is None
or endpoint_account.casefold() != match.group("account").casefold()
or unquote(endpoint_match.group("project")).casefold()
!= match.group("project").casefold()
):
raise HelperFailure(
"project-identity-mismatch",
"project_endpoint and project_resource_id must identify the same Foundry project.",
blocked_at="reconciliation",
)
return project_id, endpoint
def _connection_url(plan: dict[str, Any]) -> str:
project_id = plan.get("project_resource_id")
if not isinstance(project_id, str) or PROJECT_ID.fullmatch(project_id) is None:
raise HelperFailure(
"project-resource-id-invalid",
"project_resource_id must identify one Microsoft Foundry project.",
blocked_at="input-resolution",
)
connection = plan.get("connection")
if not isinstance(connection, dict):
raise HelperFailure(
"connection-invalid",
"connection must be an object.",
blocked_at="input-resolution",
)
name = connection.get("name")
if not isinstance(name, str) or not name:
raise HelperFailure(
"connection-invalid",
"connection.name is required.",
blocked_at="input-resolution",
)
return (
"https://management.azure.com"
f"{project_id}/connections/{quote(name, safe='')}?"
+ urlencode({"api-version": ARM_API_VERSION})
)
def _load_sdk() -> tuple[Any, Any, Any, Any, Any]:
try:
if version("azure-ai-projects").split(".", 1)[0] != SDK_MAJOR:
raise HelperFailure(
"sdk-version-invalid",
"azure-ai-projects 2.x is required.",
blocked_at="execution",
)
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import (
MCPTool,
PromptAgentDefinition,
StructuredInputDefinition,
)
from azure.core.exceptions import AzureError
from azure.identity import AzureCliCredential
except PackageNotFoundError as exc:
raise HelperFailure(
"sdk-unavailable",
"azure-ai-projects 2.x is not installed.",
blocked_at="execution",
) from exc
except ImportError as exc:
raise HelperFailure(
"sdk-unavailable",
"azure-ai-projects, azure-identity, and azure-core are required.",
blocked_at="execution",
) from exc
return (
AIProjectClient,
MCPTool,
PromptAgentDefinition,
StructuredInputDefinition,
(AzureCliCredential, AzureError),
)
def _load_connection_sdk() -> tuple[Any, Any, Any, Any, Any]:
sdk = _load_sdk()
installed = re.match(r"^2\.(\d+)\.", version("azure-ai-projects"))
if installed is None or int(installed[1]) < 4:
raise fail("sdk-version-invalid", "Complete Prompt version reads require azure-ai-projects>=2.4.0,<3, including drafts.")
return sdk
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Python
The author says: Azure
Security
What our scanner noticed· Medium risk
- References to credential files
- Instructions that use the network
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Microsoft
- Publisher
- Microsoft (Official)
- Source
- microsoft/skills · .github/plugins/foundry-iq-skills/skills/foundry-iq · commit 0696600
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from .github/plugins/foundry-iq-skills/LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Microsoft or Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download foundry-iq.zip