DEV Community

Cover image for Azure AI Agent + Bing Grounding: Real-Time Web Search with Terraform πŸ“š
Suhas Mallesh
Suhas Mallesh

Posted on

Azure AI Agent + Bing Grounding: Real-Time Web Search with Terraform πŸ“š

An agent without grounding hallucinates about current events. Bing Grounding gives your Azure AI agent real-time web search with source citations. Here's how to provision the Bing resource, connect it to your Foundry project, and attach it to your agent with Terraform.

Through this series, we've built Azure AI agents that can reason, call functions, and coordinate multi-agent workflows. But ask one about today's news, current stock prices, or this week's weather, and it either hallucinates or admits its training data has a cutoff.

Bing Grounding connects your agent to real-time web search. When the agent determines it needs current information, it searches Bing, retrieves relevant results, and generates a response grounded in those results with URL citations. The agent decides when to search. Bing provides the facts. Your users get accurate, sourced answers. 🎯

πŸ—οΈ How Bing Grounding Works

User: "What's the weather in Seattle today?"
    ↓
Agent analyzes request β†’ determines it needs current data
    ↓
Agent invokes Bing Grounding tool
    ↓
Bing searches the web, returns relevant results
    ↓
Agent generates response grounded in Bing results
    ↓
User: "It's 55Β°F and partly cloudy in Seattle today."
       [Citation: weather.gov/seattle]
Enter fullscreen mode Exit fullscreen mode

The agent doesn't call the Bing API directly. The Foundry Agent Service handles the Bing integration through a connection resource. You provision the Bing resource, create the connection, and attach the tool to your agent.

πŸ”§ Two Bing Grounding Options

Tool Scope Best For
Grounding with Bing Search Full public web General current events, weather, news, live data
Grounding with Bing Custom Search Specific domains you define Restricted searches (e.g., only your docs site, partner sites)

Bing Search searches the full web. Bing Custom Search lets you restrict results to specific domains, useful when you want grounding but only from trusted sources.

πŸ”§ Terraform: Provision Bing Grounding

Step 1: Create the Bing Grounding Resource

# grounding/bing.tf

resource "azapi_resource" "bing_grounding" {
  type      = "Microsoft.Bing/accounts@2025-05-01-preview"
  name      = "${var.environment}-bing-grounding"
  location  = "global"
  parent_id = azurerm_resource_group.this.id

  body = {
    kind = "Grounding"
    sku = {
      name = "G1"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Why azapi? The Bing Grounding resource isn't available in the azurerm provider yet. The azapi provider gives access to the latest Azure resource types directly.

Step 2: Connect Bing to Your Foundry Project

# grounding/connection.tf

resource "azapi_resource" "bing_connection" {
  type      = "Microsoft.CognitiveServices/accounts/connections@2025-06-01"
  name      = "${var.environment}-bing-connection"
  parent_id = azurerm_cognitive_account.ai_foundry.id

  schema_validation_enabled = false

  body = {
    properties = {
      category  = "ApiKey"
      target    = azapi_resource.bing_grounding.output.properties.endpoint
      authType  = "ApiKey"
      isSharedToAll = true
      credentials = {
        key = azapi_resource.bing_grounding.output.properties.accessKeys.key1
      }
      metadata = {
        ApiType    = "Bing"
        ResourceId = azapi_resource.bing_grounding.id
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This creates a connection between your Foundry project and the Bing resource. The connection ID is what your agent code references when attaching the Bing tool.

Step 3: Output the Connection ID

# grounding/outputs.tf

resource "local_file" "agent_config" {
  filename = "${path.module}/agent_code/agent_config.json"
  content = jsonencode({
    foundry_endpoint  = azurerm_cognitive_account.ai_foundry.endpoint
    deployment_name   = azurerm_cognitive_deployment.agent_model.name
    agent_name        = "${var.environment}-grounded-agent"
    instruction       = var.agent_instruction
    bing_connection_id = azapi_resource.bing_connection.id
  })
}
Enter fullscreen mode Exit fullscreen mode

🐍 Create Agent with Bing Grounding

# agent_code/create_agent.py

from azure.ai.agents import AgentsClient
from azure.ai.agents.models import BingGroundingTool
from azure.identity import DefaultAzureCredential
import json

with open("agent_config.json") as f:
    config = json.load(f)

client = AgentsClient(
    endpoint=config["foundry_endpoint"],
    credential=DefaultAzureCredential(),
)

# Create Bing grounding tool from connection
bing_tool = BingGroundingTool(
    connection_id=config["bing_connection_id"]
)

# Create agent with Bing grounding
agent = client.create_agent(
    model=config["deployment_name"],
    name=config["agent_name"],
    instructions="""You are a helpful assistant with access to real-time 
    web search. When answering questions about current events, weather, 
    news, stock prices, or any time-sensitive information, use Bing 
    Search to ground your response. Always include source citations.""",
    tools=bing_tool.definitions,
)

print(f"Agent created: {agent.id}")
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ Query the Grounded Agent

# Create thread and send message
thread = client.threads.create()
client.messages.create(
    thread_id=thread.id,
    role="user",
    content="What are the top tech headlines today?"
)

# Run the agent
run = client.runs.create_and_process(
    thread_id=thread.id,
    agent_id=agent.id,
)

# Get response with citations
if run.status == "completed":
    messages = client.messages.list(thread_id=thread.id)
    for msg in messages:
        if msg.role == "assistant":
            # Print the response text
            print(msg.content[0].text.value)

            # Print URL citations
            if hasattr(msg.content[0].text, "annotations"):
                for annotation in msg.content[0].text.annotations:
                    if hasattr(annotation, "url_citation"):
                        print(f"  Source: {annotation.url_citation.url}")
Enter fullscreen mode Exit fullscreen mode

The response includes inline URL citations. When Bing contributes to the answer, annotations link back to the source websites. These citations must be displayed to end users per Microsoft's Use and Display Requirements.

πŸ“ Combining Bing Grounding with Other Tools

An agent can have Bing Grounding alongside function calling tools:

from azure.ai.agents.models import BingGroundingTool, FunctionTool

bing_tool = BingGroundingTool(connection_id=config["bing_connection_id"])

exchange_rate_tool = FunctionTool(
    name="get_exchange_rate",
    description="Get live exchange rates between currencies.",
    parameters={
        "type": "object",
        "properties": {
            "currency_from": {"type": "string", "description": "Source currency code"},
            "currency_to": {"type": "string", "description": "Target currency code"},
        },
        "required": ["currency_from", "currency_to"]
    }
)

# Agent with both grounding and function tools
agent = client.create_agent(
    model=config["deployment_name"],
    name="full-agent",
    instructions="""You are a helpful assistant.
    Use Bing Search for current events, news, and general web queries.
    Use get_exchange_rate for live currency conversion rates.
    Choose the right tool based on the question.""",
    tools=bing_tool.definitions + [exchange_rate_tool],
)
Enter fullscreen mode Exit fullscreen mode

The agent routes between Bing for general web queries and your custom functions for specific operations. No conflicts between tool types.

πŸ“ Adding Azure AI Search (Private Docs)

For grounding against both public web and private documents, combine Bing with Azure AI Search:

from azure.ai.agents.models import (
    BingGroundingTool,
    AzureAISearchTool,
)

bing_tool = BingGroundingTool(connection_id=config["bing_connection_id"])

search_tool = AzureAISearchTool(
    index_connection_id=config["search_connection_id"],
    index_name=config["search_index_name"],
)

agent = client.create_agent(
    model=config["deployment_name"],
    name="fully-grounded-agent",
    instructions="""You are a company assistant.
    Use Bing for current events and public information.
    Use Azure AI Search for company policies and internal documents.
    Answer general knowledge questions directly.""",
    tools=bing_tool.definitions + search_tool.definitions,
)
Enter fullscreen mode Exit fullscreen mode

The agent now has three paths: Bing for public web, AI Search for private docs, and direct answers for general knowledge.

⚠️ Gotchas and Tips

Citation display is required. When Bing Grounding contributes to a response, you must display the URL citations to end users. This is a requirement from Microsoft's Use and Display Requirements, not optional.

Data crosses compliance boundary. Bing queries are sent outside the Azure compliance boundary to the Bing service. Assess whether this meets your compliance requirements, especially in regulated industries.

Bing Grounding has per-transaction pricing. Each time the agent invokes the Bing tool, it counts as a grounding transaction. Check the Bing Grounding pricing page for current rates.

Agent decides when to search. The agent uses Bing only when it determines web search is needed. Clear instructions about when to use Bing help prevent unnecessary searches on questions the model can answer from general knowledge.

Connection-based architecture. The Bing resource connects to your Foundry project via a connection resource. If you move to a different project, recreate the connection. The Bing resource itself is reusable across projects.

⏭️ Series Complete!

This is Post 4 of the Azure AI Agents with Terraform series, and the final post of the entire multi-cloud blog series.


Your agent is fully grounded. Bing for real-time web data. AI Search for private documents. Function calling for live APIs. From a simple model endpoint to a production-ready, multi-agent, grounded AI system - all defined in Terraform and Python. πŸ“š

Top comments (0)