Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Build persistent agents on Azure AI Foundry using the Microsoft Agent Framework Python SDK.
.claude/skills/agent-framework-azure-ai-py/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-10 | ✗→✓ | ▲ Improved | — | — |
| case-11 | ✗→✓ | ▲ Improved | — | — |
| case-21 | ✗→✓ | ▲ Improved | — | — |
| case-20 | ✗→✓ | ▲ Improved | — | — |
| case-12 | ✗→✓ | ▲ Improved | — | — |
Build persistent agents on Azure AI Foundry using the Microsoft Agent Framework Python SDK.
User Query → AzureAIAgentsProvider → Azure AI Agent Service (Persistent)
↓
Agent.run() / Agent.run_stream()
↓
Tools: Functions | Hosted (Code/Search/Web) | MCP
↓
AgentThread (conversation persistence)bash# Full framework (recommended) pip install agent-framework --pre # Or Azure-specific package only pip install agent-framework-azure-ai --pre
bashexport AZURE_AI_PROJECT_ENDPOINT="https://<project>.services.ai.azure.com/api/projects/<project-id>" export AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" export BING_CONNECTION_ID="your-bing-connection-id" # For web search
pythonfrom azure.identity.aio import AzureCliCredential, DefaultAzureCredential # Development credential = AzureCliCredential() # Production credential = DefaultAzureCredential()
pythonimport asyncio from agent_framework.azure import AzureAIAgentsProvider from azure.identity.aio import AzureCliCredential async def main(): async with ( AzureCliCredential() as credential, AzureAIAgentsProvider(credential=credential) as provider, ): agent = await provider.create_agent( name="MyAgent", instructions="You are a helpful assistant.", ) result = await agent.run("Hello!") print(result.text) asyncio.run(main())
pythonfrom typing import Annotated from pydantic import Field from agent_framework.azure import AzureAIAgentsProvider from azure.identity.aio import AzureCliCredential def get_weather( location: Annotated[str, Field(description="City name to get weather for")], ) -> str: """Get the current weather for a location.""" return f"Weather in {location}: 72°F, sunny" def get_current_time() -> str: """Get the current UTC time.""" from datetime import datetime, timezone return datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC") async def main(): async with ( AzureCliCredential() as credential, AzureAIAgentsProvider(credential=credential) as provider, ): agent = await provider.create_agent( name="WeatherAgent", instructions="You help with weather and time queries.", tools=[get_weather, get_current_time], # Pass functions directly ) result = await agent.run("What's the weather in Seattle?") print(result.text)
pythonfrom agent_framework import ( HostedCodeInterpreterTool, HostedFileSearchTool, HostedWebSearchTool, ) from agent_framework.azure import AzureAIAgentsProvider from azure.identity.aio import AzureCliCredential async def main(): async with ( AzureCliCredential() as credential, AzureAIAgentsProvider(credential=credential) as provider, ): agent = await provider.create_agent( name="MultiToolAgent", instructions="You can execute code, search files, and search the web.", tools=[ HostedCodeInterpreterTool(), HostedWebSearchTool(name="Bing"), ], ) result = await agent.run("Calculate the factorial of 20 in Python") print(result.text)
pythonasync def main(): async with ( AzureCliCredential() as credential, AzureAIAgentsProvider(credential=credential) as provider, ): agent = await provider.create_agent( name="StreamingAgent", instructions="You are a helpful assistant.", ) print("Agent: ", end="", flush=True) async for chunk in agent.run_stream("Tell me a short story"): if chunk.text: print(chunk.text, end="", flush=True) print()
pythonfrom agent_framework.azure import AzureAIAgentsProvider from azure.identity.aio import AzureCliCredential async def main(): async with ( AzureCliCredential() as credential, AzureAIAgentsProvider(credential=credential) as provider, ): agent = await provider.create_agent( name="ChatAgent", instructions="You are a helpful assistant.", tools=[get_weather], ) # Create thread for conversation persistence thread = agent.get_new_thread() # First turn result1 = await agent.run("What's the weather in Seattle?", thread=thread) print(f"Agent: {result1.text}") # Second turn - context is maintained result2 = await agent.run("What about Portland?", thread=thread) print(f"Agent: {result2.text}") # Save thread ID for later resumption print(f"Conversation ID: {thread.conversation_id}")
pythonfrom pydantic import BaseModel, ConfigDict from agent_framework.azure import AzureAIAgentsProvider from azure.identity.aio import AzureCliCredential class WeatherResponse(BaseModel): model_config = ConfigDict(extra="forbid") location: str temperature: float unit: str conditions: str async def main(): async with ( AzureCliCredential() as credential, AzureAIAgentsProvider(credential=credential) as provider, ): agent = await provider.create_agent( name="StructuredAgent", instructions="Provide weather information in structured format.", response_format=WeatherResponse, ) result = await agent.run("Weather in Seattle?") weather = WeatherResponse.model_validate_json(result.text) print(f"{weather.location}: {weather.temperature}°{weather.unit}")
| Method | Description | |--------|-------------| | create_agent() | Create new agent on Azure AI service | | get_agent(agent_id) | Retrieve existing agent by ID | | as_agent(sdk_agent) | Wrap SDK Agent object (no HTTP call) |
| Tool | Import | Purpose | |------|--------|---------| | HostedCodeInterpreterTool | from agent_framework import HostedCodeInterpreterTool | Execute Python code | | HostedFileSearchTool | from agent_framework import HostedFileSearchTool | Search vector stores | | HostedWebSearchTool | from agent_framework import HostedWebSearchTool | Bing web search | | HostedMCPTool | from agent_framework import HostedMCPTool | Service-managed MCP | | MCPStreamableHTTPTool | from agent_framework import MCPStreamableHTTPTool | Client-managed MCP |
pythonimport asyncio from typing import Annotated from pydantic import BaseModel, Field from agent_framework import ( HostedCodeInterpreterTool, HostedWebSearchTool, MCPStreamableHTTPTool, ) from agent_framework.azure import AzureAIAgentsProvider from azure.identity.aio import AzureCliCredential def get_weather( location: Annotated[str, Field(description="City name")], ) -> str: """Get weather for a location.""" return f"Weather in {location}: 72°F, sunny" class AnalysisResult(BaseModel): summary: str key_findings: list[str] confidence: float async def main(): async with ( AzureCliCredential() as credential, MCPStreamableHTTPTool( name="Docs MCP", url="https://learn.microsoft.com/api/mcp", ) as mcp_tool, AzureAIAgentsProvider(credential=credential) as provider, ): agent = await provider.create_agent( name="ResearchAssistant", instructions="You are a research assistant with multiple capabilities.", tools=[ get_weather, HostedCodeInterpreterTool(), HostedWebSearchTool(name="Bing"), mcp_tool, ], ) thread = agent.get_new_thread() # Non-streaming result = await agent.run( "Search for Python best practices and summarize", thread=thread, ) print(f"Response: {result.text}") # Streaming print("\nStreaming: ", end="") async for chunk in agent.run_stream("Continue with examples", thread=thread): if chunk.text: print(chunk.text, end="", flush=True) print() # Structured output result = await agent.run( "Analyze findings", thread=thread, response_format=AnalysisResult, ) analysis = AnalysisResult.model_validate_json(result.text) print(f"\nConfidence: {analysis.confidence}") if __name__ == "__main__": asyncio.run(main())
async with provider:tools= parameter (auto-converted to AIFunction)Annotated[type, Field(description=...)] for function parametersget_new_thread() for multi-turn conversationsHostedMCPTool for service-managed MCP, MCPStreamableHTTPTool for client-managedThis skill is applicable to execute the workflow or actions described in the overview.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-10 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-23 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +70 percentage points is the difference between those two pass rates over the 23 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.