| name | agentic-ai |
| description | Helps build AI agents using Azure AI Foundry with tool calling capabilities. Use this skill when creating agents, configuring tool definitions, implementing the agent loop, or integrating agents with Azure Functions and MCP servers. |
Agentic AI Development Skill
Overview
This skill helps you build AI agents that can reason, plan, and execute actions using tools. We focus on the single-agent pattern using Azure AI Foundry.
Agent Architecture
┌─────────────────────────────────────────────────────────────────┐
│ AI Agent Loop │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌──────────────┐ ┌─────────────────────┐ │
│ │ User │────▶│ AI Model │────▶│ Tool Execution │ │
│ │ Query │ │ (Reasoning) │ │ (Azure Functions) │ │
│ └─────────┘ └──────────────┘ └─────────────────────┘ │
│ ▲ │ │ │
│ │ ▼ ▼ │
│ │ ┌──────────────┐ ┌─────────────────────┐ │
│ └─────────│ Response │◀────│ Tool Results │ │
│ │ Generation │ │ │ │
│ └──────────────┘ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Tool Definition Schema
Tools tell the AI what actions it can take:
tools = [
{
"type": "function",
"function": {
"name": "analyze_data",
"description": "Analyze a list of numbers and return statistics including count, sum, mean, min, and max.",
"parameters": {
"type": "object",
"properties": {
"values": {
"type": "array",
"items": {"type": "number"},
"description": "List of numbers to analyze"
}
},
"required": ["values"]
}
}
}
]
Agent Implementation with Azure AI Foundry
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
client = AIProjectClient(
credential=DefaultAzureCredential(),
subscription_id="your-subscription",
resource_group_name="your-rg",
project_name="your-project"
)
agent = client.agents.create_agent(
model="gpt-4o",
name="data-analyst",
instructions="You are a data analysis assistant. Use your tools to analyze data when asked.",
tools=tools
)
thread = client.agents.create_thread()
message = client.agents.create_message(
thread_id=thread.id,
role="user",
content="Analyze these sales figures: [100, 250, 175, 300, 225]"
)
run = client.agents.create_and_process_run(
thread_id=thread.id,
assistant_id=agent.id
)
Tool Execution Pattern
When the AI decides to call a tool:
def process_tool_calls(run, client, thread_id):
"""Process tool calls from the agent."""
if run.status == "requires_action":
tool_calls = run.required_action.submit_tool_outputs.tool_calls
tool_outputs = []
for call in tool_calls:
function_name = call.function.name
arguments = json.loads(call.function.arguments)
if function_name == "analyze_data":
result = analyze_data(arguments["values"])
elif function_name == "search_database":
result = search_database(arguments["query"])
else:
result = {"error": f"Unknown function: {function_name}"}
tool_outputs.append({
"tool_call_id": call.id,
"output": json.dumps(result)
})
run = client.agents.submit_tool_outputs(
thread_id=thread_id,
run_id=run.id,
tool_outputs=tool_outputs
)
return run
Writing Good Tool Descriptions
The AI uses descriptions to decide when to use a tool. Be specific:
Good ✅
"description": "Search the product database for items matching the query. Returns product name, price, and availability. Use when the user asks about products, inventory, or wants to find specific items."
Bad ❌
"description": "Searches things"
Single Agent vs Multi-Agent
| Aspect | Single Agent | Multi-Agent |
|---|
| Complexity | Lower | Higher |
| Use Case | One brain + many tools | Specialized roles |
| Coordination | None needed | Requires orchestration |
| Debugging | Easier | More complex |
| When to Use | Most tasks | Parallel work, debate, specialization |
Start with single agent. Graduate to multi-agent only when needed.
Agent Loop Best Practices
- Clear Instructions: Tell the agent its role and constraints
- Descriptive Tools: Help the AI understand when to use each tool
- Error Handling: Tools should return error info, not throw exceptions
- Iteration Limits: Set max iterations to prevent infinite loops
- Logging: Log tool calls and results for debugging
Connecting to External Tools
Via HTTP (Azure Functions)
def call_azure_function(function_url: str, data: dict) -> dict:
"""Call an Azure Function as a tool."""
response = requests.post(
function_url,
json=data,
headers={"x-functions-key": os.environ["FUNCTION_KEY"]}
)
return response.json()
Via MCP (Model Context Protocol)
Debugging Agents
- Print tool calls: Log what the AI is trying to do
- Check tool definitions: Ensure schemas are valid JSON
- Test tools independently: Call tools directly before agent integration
- Review instructions: Vague instructions lead to vague behavior
- Inspect thread history: See the full conversation context