AI applications are useful for answering questions, summarizing documents, and generating content. However, there is one limitation developers frequently encounter: a language model does not automatically know what happened yesterday or which version of a library was released last week.
A model primarily generates responses using information learned during training and the context provided in the request. When an application needs current information, it needs a way to retrieve relevant external information and provide it to the model.
Amazon Bedrock addresses this requirement with its built-in Web Search tool. It allows supported models to search for current information and use the retrieved results when generating an answer.
The interesting part is that developers do not need to build their own search engine, manage web crawlers, or implement the complete search-and-retrieval loop.
In this article, we will explore how Amazon Bedrock Web Search works and connect it to a normal C# application using ASP.NET Core and HttpClient.
1. What Is Amazon Bedrock Web Search?
Amazon Bedrock Web Search is a hosted search capability that allows supported foundation models to retrieve information from the web during a request.
Normally, an application sends a prompt to a model and receives a generated response. With Web Search enabled, the model can decide whether the question requires current information and invoke the search tool when necessary.
For example, consider an application that asks:
"What are the latest changes in the .NET platform?"
Without web search, the model may generate an answer using its existing knowledge. It might not know about recently released features or updated documentation.
With Web Search enabled, the model can search for relevant information, examine the returned observations, and generate an answer grounded in those results.
Amazon Bedrock handles the search operation on the server side.
This means developers do not need to build and maintain:
- A custom web crawler.
- A search index.
- A separate search API integration.
- A manual search-result processing loop.
- A custom tool-execution mechanism for this built-in search capability.
The model decides when search is necessary and uses the results to generate its response.
2. Understand How Web Search Works
Amazon Bedrock Web Search uses two main operations: Search and Fetch.
Search retrieves relevant observations from the Amazon-maintained web index. These observations include information such as the page title, URL, and content snippet.
Fetch retrieves the content of a specific URL so the model can examine more information from the page.
The overall process looks like this:
- The application sends a user prompt to a supported model.
- The request includes the Web Search tool.
- The model determines whether current information is required.
- The model invokes Search when necessary.
- The search service returns relevant observations.
- The model may invoke Fetch to retrieve additional page content.
- The model generates an answer using the available information.
- The application receives the answer along with source citations.
The important point is that search is controlled by the model. Adding the tool does not mean every request automatically performs a web search.
For example, a question about the difference between a C# class and a struct may not require current information. A question about the latest C# language release probably does.
3. Understand the API Requirements Before Writing Code
One important detail is that Amazon Bedrock Web Search is not available through every Bedrock API.
It currently requires the Responses API through the Amazon Bedrock Mantle endpoint.
The following distinction is important:
Amazon Bedrock interface |
Web Search support |
Bedrock Runtime with InvokeModel |
Not supported |
Bedrock Runtime with Converse |
Not supported |
Bedrock Mantle with Responses API |
Supported for eligible models |
The Web Search tool is available for supported OpenAI GPT models through the Mantle endpoint.
The AWS documentation currently lists supported models and commercial availability in selected US Regions, including:
- US East (N. Virginia): us-east-1
- US East (Ohio): us-east-2
- US West (Oregon): us-west-2
AWS GovCloud has separate supported model and regional availability.
This is important when planning deployment. Do not assume that Web Search is available in every Amazon Bedrock Region. Check the latest AWS documentation before selecting your deployment Region.
For this example, we will use the US West (Oregon) endpoint and the model openai.gpt-5.6-terra.
4. Configure Amazon Bedrock Access
Before integrating Web Search into the application, configure the required access.
The application needs an Amazon Bedrock API key and an IAM identity with the required Web Search permissions.
The basic Web Search actions include:
- bedrock-websearch
- bedrock-websearch
The ExternalWebAccess permission is additionally required when the application allows Fetch to retrieve live content from the external web.
For the initial implementation, we will explicitly disable external web access. This allows Search and cached Fetch operations while keeping retrieval within the AWS boundary.
Store the API key as an environment variable rather than placing it directly in source code.
For example:
export BEDROCK_API_KEY="your-amazon-bedrock-api-key"
The endpoint for this example is:
https://bedrock-mantle.us-west-2.api.aws/openai/v1
Keep the endpoint configurable because different Regions have different endpoint addresses.
5. Create a C# Application Using HttpClient
Now let's connect Amazon Bedrock Web Search to a normal .NET application.
Create a new console project:
dotnet new console -n BedrockWebSearchDemo
cd BedrockWebSearchDemo
We will use HttpClient to send a request directly to the Responses API.
This approach is useful when you want to integrate the capability into an existing .NET service without introducing another SDK dependency.
Replace Program.cs with the following implementation:
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
var apiKey = Environment.GetEnvironmentVariable(
"BEDROCK_API_KEY");
if (string.IsNullOrWhiteSpace(apiKey))
{
throw new InvalidOperationException(
"BEDROCK_API_KEY is not configured.");
}
var endpoint =
"https://bedrock-mantle.us-west-2.api.aws/openai/v1/responses";
using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", apiKey);
var request = new
{
model = "openai.gpt-5.6-terra",
input = "What are the latest developments in .NET?",
tools = new[]
{
new
{
type = "web_search",
external_web_access = false,
search_context_size = "medium"
}
}
};
using var response = await httpClient.PostAsJsonAsync(
endpoint,
request);
var responseBody = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException(
$"Bedrock request failed: {(int)response.StatusCode} " +
$"{response.ReasonPhrase}. Response: {responseBody}");
}
using var document = JsonDocument.Parse(responseBody);
var root = document.RootElement;
Console.WriteLine("Generated Answer:");
foreach (var item in root.GetProperty("output").EnumerateArray())
{
if (!item.TryGetProperty("type", out var itemType) ||
itemType.GetString() != "message")
{
continue;
}
if (!item.TryGetProperty("content", out var content))
{
continue;
}
foreach (var block in content.EnumerateArray())
{
if (!block.TryGetProperty("type", out var blockType) ||
blockType.GetString() != "output_text")
{
continue;
}
if (block.TryGetProperty("text", out var text))
{
Console.WriteLine(text.GetString());
}
if (!block.TryGetProperty("annotations", out var annotations))
{
continue;
}
foreach (var annotation in annotations.EnumerateArray())
{
if (annotation.TryGetProperty("type", out var type) &&
type.GetString() == "url_citation")
{
var title = annotation.GetProperty("title").GetString();
var url = annotation.GetProperty("url").GetString();
Console.WriteLine();
Console.WriteLine($"Source: {title}");
Console.WriteLine($"URL: {url}");
}
}
}
}
Let's understand the important parts.
First, the application reads the API key from the environment. This prevents credentials from being exposed in the source code.
Next, it creates an HTTP request with the model name, user prompt, and Web Search tool configuration.
The following section enables Web Search:
tools = new[]
{
new
{
type = "web_search",
external_web_access = false,
search_context_size = "medium"
}
}
The search context size controls how much search-result context can be returned to the model for each search call.
The available values are:
Value |
Observation budget |
low |
Up to 5 |
medium |
Up to 11 |
high |
Up to 25 |
A larger context can provide more information, but it can also increase input-token usage and associated inference costs.
Finally, the application reads the response and extracts both the generated text and its source citations.
6. Read and Display Source Citations
One of the most useful parts of Web Search is that the response contains citations.
A normal AI-generated answer might provide information without showing where it came from. This makes it difficult for users to verify the information.
Amazon Bedrock Web Search provides URL citation annotations with details such as:
- Source title.
- Source URL.
- Start position in the generated text.
- End position in the generated text.
For example, the response contains annotations similar to this:
{
"type": "url_citation",
"title": "Latest .NET Platform Updates",
"url": "https://example.com/dotnet-updates",
"start_index": 120,
"end_index": 245
}
The application should retain these citations and display them alongside the generated answer.
Do not simply discard the annotations after extracting the response text. They are important for transparency and allow users to verify the information.
Also, a citation does not necessarily mean that Fetch retrieved the complete page. A citation can be based on a Search observation.
7. Control External Web Access
One important consideration when integrating search into an enterprise application is data governance.
Amazon Bedrock provides the external_web_access setting to control whether Fetch can retrieve live content from the external web.
There are two main configurations.
Configuration |
Behavior |
external_web_access = false |
Search uses the Bedrock web index and Fetch uses the Bedrock cache |
external_web_access = true |
Fetch can retrieve live external content when the required IAM permission is available |
For applications that process confidential business information, explicitly setting external_web_access to false is a sensible starting point.
When external access is enabled, the application must also have the bedrock-websearch permission.
This is an important security distinction. Enabling external access can allow request-related information to leave the AWS boundary during retrieval.
Do not assume that an HTTP 200 response means every Fetch operation succeeded. AWS documents that a request can complete using Search observations even when Fetch attempts are denied.
For production applications, review IAM permissions, enable appropriate CloudTrail data-event monitoring, and decide whether external retrieval is acceptable for the information being processed.
8. Production Considerations
A working API integration is only the beginning. Before introducing Web Search into a production application, consider the following areas.
Authentication and secrets management: Store API credentials in a secure configuration provider such as AWS Secrets Manager. Avoid committing keys to Git repositories or writing them into application logs.
Timeouts and cancellation: Configure appropriate request timeouts and pass cancellation tokens through the HTTP request. Search-enabled requests can take longer than ordinary model requests.
Error handling: Handle authentication failures, permission errors, throttling, service errors, and invalid model or Region configurations.
Citation handling: Preserve source titles and URLs. Display citations to users rather than presenting search-grounded information as an unsupported statement.
Cost management: Search context size affects the amount of information passed to the model. Review current Amazon Bedrock pricing and measure token usage for your application's workload.
Monitoring: Use application logs and CloudTrail to investigate request failures and Web Search activity. Avoid logging API keys or sensitive user prompts.
Testing: Test questions that require current information, questions that do not require search, and questions where reliable search results are unavailable.
Summary
Amazon Bedrock Web Search makes it easier to build AI applications that need current information. Instead of creating a custom search engine or managing a separate retrieval workflow, developers can enable the built-in Web Search tool through the Responses API.
In this example, we connected a C# application using HttpClient, configured the model and search tool, and extracted the generated answer with its source citations.
The most important implementation details are selecting a supported model and Region, using the Bedrock Mantle endpoint, configuring IAM permissions, and deciding whether external web access is appropriate.
For production applications, treat citations, security, error handling, and cost management as part of the integration rather than adding them later.
Join the conversation! Your thoughts help the community grow.