@keenable/ai-sdk
v0.1.0
Published
Keenable web search and page-fetch tools for the Vercel AI SDK. Keyless by default.
Readme
@keenable/ai-sdk
Keenable web search and page-fetch tools for the Vercel AI SDK.
Keyless by default. The tools work with no account and no API key against
Keenable's public endpoints. An optional KEENABLE_API_KEY lifts the hourly
rate limit; it is never a prerequisite, so an example using these tools runs
for whoever copies it.
Installation
npm install @keenable/ai-sdkai and zod are peer dependencies, and you already have both in an AI SDK
project. There is no provider SDK to install: the package talks to the Keenable
HTTP API through the official keenable
client. Node 18 or newer.
Quick start
import { openai } from "@ai-sdk/openai";
import { generateText, stepCountIs } from "ai";
import { keenableTools } from "@keenable/ai-sdk";
const { text } = await generateText({
model: openai("gpt-5.6-sol"),
tools: keenableTools(),
stopWhen: stepCountIs(6),
prompt: "What changed in the latest Bun release? Cite the pages you used.",
});keenableTools() returns both tools keyed by the names the model sees,
keenable_search and keenable_fetch, sharing one client. Pass a key to lift
the rate limit, or leave it out entirely:
const tools = keenableTools({ apiKey: process.env.KEENABLE_API_KEY });The tools
keenable_search
Searches the web and returns ranked pages, each with the page text already extracted, so a typical question is answered without a second round trip.
import { keenableSearch } from "@keenable/ai-sdk";
const tools = {
keenable_search: keenableSearch({
site: "arxiv.org", // pin every search to one domain
maxResults: 5,
snippetMaxLength: 2000,
}),
};Returns { query, results: [{ title, url, snippet, publishedAt }] }. The page
text is in snippet; description is the page's meta description and is
absent for most pages, so it is not returned at all.
The model can also set site, publishedAfter and publishedBefore per call.
Anything you configure on the tool is the default when the model leaves it out.
| Option | Default | What it does |
|---|---|---|
| site | unset | Restrict every search to one domain |
| publishedAfter / publishedBefore | unset | Publication-date window (YYYY-MM-DD) |
| maxResults | all | Keep at most this many results |
| snippetMaxLength | 1000 | Characters of page text kept per result |
snippetMaxLength matters more here than with other search APIs: Keenable
returns whole-page text on every result, an order of magnitude more than a
typical snippet, so an uncapped result set would spend the context window on
pages the model never chose to read. keenable_fetch is how it opts into one.
keenable_fetch
Reads one URL and returns its main content as markdown, boilerplate stripped.
import { keenableFetch } from "@keenable/ai-sdk";
const tools = { keenable_fetch: keenableFetch({ contentMaxLength: 20_000 }) };Returns { url, title, content, publishedAt }. Longer pages are truncated and
marked with [truncated], and the marker counts against contentMaxLength, so
the tool never returns more than the budget it was given.
Configuration
Every client option of the keenable
SDK is accepted by all three factories:
| Option | Environment | Purpose |
|---|---|---|
| apiKey | KEENABLE_API_KEY | Lifts the hourly rate limit. Optional |
| baseUrl | KEENABLE_API_URL | Point at a different Keenable deployment |
| timeoutMs | | Request timeout, default 30000 |
| fetch | | Custom fetch, for a proxy or a test |
| client | | A Keenable instance to use as-is |
License
MIT
