Search and read the web
Urai gives you two built-in tools for the web.
web_searchfinds pages. Each result has a title, a URL, and a short description.web_fetchreads pages. It reads more than one URL in one call. It returns the text of each page.
Name these tools in tools[]. Urai does the search and the reads on the server.
You get the answer in one response. Your code does not run a tool call.
Make a request
Section titled “Make a request”curl https://chat.app.urai.dev/api/openai/v1/chat/completions \ -H "Authorization: Bearer $URAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "anthropic/claude-haiku-4-5", "messages": [ { "role": "user", "content": "What is in the latest Rust release? Give your sources." } ], "tools": [ { "type": "function", "function": { "name": "web_search" } }, { "type": "function", "function": { "name": "web_fetch" } } ] }'The same request from an OpenAI SDK:
response = client.chat.completions.create( model="anthropic/claude-haiku-4-5", messages=[{"role": "user", "content": "What is in the latest Rust release? Give your sources."}], tools=[ {"type": "function", "function": {"name": "web_search"}}, {"type": "function", "function": {"name": "web_fetch"}}, ],)print(response.choices[0].message.content)Do not send parameters for these two tools. Urai supplies the two schemas.
The response is an assistant message with finish_reason: "stop". Urai completes
the search and the page reads before it sends the response.
Name the two tools together
Section titled “Name the two tools together”web_search returns a title and two lines of text for each result. This is
sufficient to name a source. It is not sufficient to answer a question about the
content of the source.
web_fetch gives the model the full text. The model selects the results to read.
Urai reads them. The model then writes the answer.
web_fetch uses many tokens. The pages fill the largest part of the prompt. A
question about a new subject can use more than 10,000 prompt tokens. The usage
object shows this count. For a short question, do not name web_fetch.
The tool for each provider
Section titled “The tool for each provider”Each provider has a different name for these tools. Some providers do the search themselves. You always use the same two names. Urai sends the correct tool to the provider.
| Provider | web_search runs as |
web_fetch runs as |
Credentials |
|---|---|---|---|
gemini, vertex, google |
Gemini’s googleSearch |
Gemini’s urlContext |
None |
openai |
OpenAI’s own web search | Jina, run by Urai | Jina |
anthropic |
Anthropic’s own web search | Jina, run by Urai | Jina |
Every other provider, such as openrouter |
Brave Search, run by Urai | Jina, run by Urai | Brave Search and Jina |
Two conditions apply to this table.
- Gemini uses
googleSearchandurlContexttogether. Thus Urai addsurlContextwhen you nameweb_search, also when you do not nameweb_fetch. On Gemini,web_fetchgives youurlContextand not Jina. A different fetch tool with these two tools causes errors in the model. - OpenAI does its own search on Responses API models only. These are the
gpt-5, the codex, and the pro models. On an older Chat Completions model,web_searchis a usual function, and Urai does the search with Brave Search. This needs the Brave Search credential.
When the provider does the search itself, you configure nothing. The provider puts the results in its own answer.
The note that Urai adds to the prompt
Section titled “The note that Urai adds to the prompt”Urai adds a note to your last user message. This occurs on all providers except OpenAI and Gemini.
Current timestamp: 2026-08-13T19:35:01.369771+00:00
[Note: You have access to the `web_search` tool for searching the web and the`web_fetch` tool for reading the full content of web pages. Follow this workflow:1. Use `web_search` to find relevant URLs.2. ALWAYS use `web_fetch` to read the content of the most relevant URLs from thesearch results...]The timestamp gives the model the current date and time. The model uses it to find out if its own data is old. The note tells the model to read the pages. Without the note, the model answers from the short descriptions in the search results.
The note agrees with the tools that you name. If you name only web_search, the
note does not mention web_fetch.
Urai puts the note in the user message and not in the system prompt. Providers keep a cache of the system prompt, and the timestamp is different for each call. In the system prompt, the timestamp makes that cache invalid for each call.
Urai adds the note to the request only. Urai does not write the note in the
stored thread. Thus a thread that you continue with x-thread-id does not repeat
an old timestamp.
Credentials
Section titled “Credentials”| Tool | Provider | Credential |
|---|---|---|
web_search |
Not openai, anthropic, or Gemini |
brave_search |
web_fetch |
Not Gemini | jina |
A credential applies to the full organization. An administrator connects it at Settings → Credentials.
Urai examines the credentials when the request arrives. A request without the necessary credential fails immediately, and not at the tool call:
{ "error": { "message": "web_fetch requires a Jina credential for this organization", "type": "invalid_request_error", "param": "tools", "code": "tool_not_configured" }}The response
Section titled “The response”- The response has the answer only. Urai does the tool calls on the server, and the tool calls are not in the response.
usagecounts the full request. This includes the tokens for the search results and for the pages.- Streaming operates in the usual manner. The tool rounds occur in the stream. The model can write text between two rounds, before the final answer.
- A request does 10 tool rounds at a maximum. Then Urai stops and sends the text of the model.
Urai keeps a cache of each page that it reads. If a recent turn read the same URL, Urai uses the cache and does not read the page again.
Use the web tools with your own tools
Section titled “Use the web tools with your own tools”Name the web tools and your UraiJS tools in the same request. The model selects between them.
{ "model": "anthropic/claude-haiku-4-5", "messages": [ { "role": "user", "content": "Does the vendor on order 4471 have an outage now?" } ], "tools": [ { "type": "function", "function": { "name": "orders" } }, { "type": "function", "function": { "name": "web_search" } }, { "type": "function", "function": { "name": "web_fetch" } } ], "metadata": { "account_id": "acct_8812" }}See Call your UraiJS tools for the way metadata
goes to your own tools. See
Search knowledge collections for the two tools
that read your uploaded documents.