Skip to content

Native grounding

View on GitHub

Some providers search the web for you. Hand the model a provider-hosted tool and it searches on its own side, then answers with citations attached. This is the native counterpart to grounded answer: same agent loop, but you skip wiring a search backend.

Drop the hosted tool in

Each provider ships its own constructor, since the tools are provider-specific:

import { googleSearchTool } from "@effect-uai/google/Gemini"
import { webSearchTool as anthropicWebSearch } from "@effect-uai/anthropic/Anthropic"
import { webSearchTool as openaiWebSearch } from "@effect-uai/responses/Responses"
const searchTool = googleSearchTool // or anthropicWebSearch() / openaiWebSearch()

You never write a run for it and the loop never asks you to execute it. It sits next to your own Tool.make tools; the model uses it to ground its answer. A hosted tool only works with the provider that hosts it: give a Gemini tool to the Anthropic model and the request fails with AiError.Unsupported.

Run it

Terminal window
GOOGLE_API_KEY=... pnpm tsx recipes/native-grounding/run-node.ts
ANTHROPIC_API_KEY=... pnpm tsx recipes/native-grounding/run-node.ts --provider=anthropic
OPENAI_API_KEY=... pnpm tsx recipes/native-grounding/run-node.ts --provider=openai
QUESTION="who won the 2026 F1 season opener?" \
GOOGLE_API_KEY=... pnpm tsx recipes/native-grounding/run-node.ts

The answer streams to stdout as the model writes it. run-bun.ts and run-deno.ts differ only in the platform HttpClient.