Skip to content

Exa Contents

Exa reads a URL through its /contents endpoint and returns the page as clean markdown, or as HTML when you ask for it. It shares the @effect-uai/exa package with Exa search, so the same key powers both.

Install

Terminal window
pnpm add @effect-uai/core @effect-uai/exa effect

Wire it up

import { Config, Effect, Layer } from "effect"
import { FetchHttpClient } from "effect/unstable/http"
import { layer as exaLayer } from "@effect-uai/exa/ExaContents"
const provider = Layer.unwrap(
Effect.gen(function* () {
const apiKey = yield* Config.redacted("EXA_API_KEY")
return exaLayer({ apiKey })
}),
)
const mainLayer = provider.pipe(Layer.provide(FetchHttpClient.layer))

exaLayer registers two service tags from one implementation:

  • ExaContents: the typed tag. Yield this for the knobs below.
  • WebRead: the generic tag for provider-portable code.

Calling it

import { ExaContents } from "@effect-uai/exa/ExaContents"
const program = Effect.gen(function* () {
const reader = yield* ExaContents
return reader.read({
url: "https://effect.website/docs",
format: "markdown",
maxCharacters: 8000,
})
})

Every field from CommonReadRequest works here. The typed request adds:

FieldTypeMeaning
livecrawlnever fallback preferred alwaysFetch live vs serve from Exa’s cache.
maxCharactersnumberCap the returned content length.

See also

  • Web reading: the cross-provider concept and the portable request / response shapes.
  • Exa search: the other capability on this package.