Skip to content

Migrating to 0.8

No rewrites needed. 0.8 is purely additive: a new WebSearch capability in @effect-uai/core, a ready-made webSearchTool for grounding an LLM, and three search providers (@effect-uai/perplexity, @effect-uai/exa, @effect-uai/tavily). Nothing in the existing surface changed. Bump your dependencies, run typecheck, done.

If you see a 0.8-version compile error that looks like a rename (durationSeconds, GeminiTranscriber, prompts, etc.), you are actually upgrading across an earlier breaking release. Apply the 0.6 → 0.7 rules (and the earlier pages) first.

What’s new (additive, no migration needed)

@effect-uai/core/WebSearch

A generic WebSearch service for searching the live web, in the same shape as every other capability: a portable request floor, a free helper, and provider layers that register both the generic tag and their own typed tag.

import { search } from "@effect-uai/core/WebSearch"
const { results } = yield * search({ query: "effect-ts v4 release notes" })
// results: ReadonlyArray<SearchResult>, portable across providers

CommonSearchRequest carries only the fields most backends honor (query, maxResults, recency, startDate / endDate as DateTime, includeDomains / excludeDomains, country, language). There is no model: pure search has nothing to pick. Where a backend cannot honor a common field, the adapter warnDroppeds rather than silently changing your query.

@effect-uai/core/WebSearchTool

webSearchTool(options?) is a ready-made tool for the agent loop whose only requirement is WebSearch. The model controls the query (and an optional recency); app policy (maxResults, includeDomains / excludeDomains, result rendering) is pinned on the tool, not left to the model.

import { webSearchTool } from "@effect-uai/core/WebSearchTool"
const tools = [webSearchTool({ maxResults: 5 })]

Because the tool sits on the generic tag, the contract the model sees is identical no matter which backend answers.

Three search providers

Provide one provider layer (plus an HttpClient) and your WebSearch-yielding code resolves.

ProviderPackageLayer import
Perplexity@effect-uai/perplexity@effect-uai/perplexity/PerplexitySearch
Exa@effect-uai/exa@effect-uai/exa/ExaSearch
Tavily@effect-uai/tavily@effect-uai/tavily/TavilySearch
import { layer as perplexity } from "@effect-uai/perplexity/PerplexitySearch"
const app = program.pipe(
Effect.provide(
perplexity({ apiKey: Redacted.make(process.env.PERPLEXITY_API_KEY!) }).pipe(
Layer.provide(FetchHttpClient.layer),
),
),
)

Swap PerplexitySearch for ExaSearch or TavilySearch and neither your program nor the model’s tool changes.

Two recipes

  • Grounded answer: the model searches, reads, and writes a cited answer; LLM and search backend swap independently.
  • Deep research: plan a broad question into sub-questions, research each with a parallel sub-agent, and synthesize a cited report you can watch assemble.

See the Web search overview for the full capability tour.