keenable
Official Python SDK for Keenable, a web search API built for AI agents: ranked results that come back with the page text already extracted, plus a fetch endpoint that returns any URL as clean markdown.
Keyless by default. Every call works with no account and no key. An optional
KEENABLE_API_KEY only lifts the hourly rate limit.
pip install keenable
Search
from keenable import Keenable
keenable = Keenable() # or Keenable("keen_...") / set KEENABLE_API_KEY
results = keenable.search("how wafer scale chips avoid the memory bottleneck")
for result in results:
print(result.title, result.url)
print(result.snippet)
Results carry the page text in snippet. (description is the page's meta
description and is empty for most pages, so build prompts from snippet.)
Filters are optional and combine freely:
results = keenable.search(
"post-training quantization results",
site="arxiv.org",
published_after="2026-01-01",
snippet_max_length=500,
)
| Argument | What it does |
|---|---|
site |
Restrict to one domain, e.g. "arxiv.org" |
published_after / published_before |
Filter by publication date (YYYY-MM-DD) |
acquired_after / acquired_before |
Filter by when Keenable indexed the page |
snippet_max_length |
Cap the page text returned per result |
mode |
Search mode; "pro" (default) does deeper retrieval |
Ground a model in one line
to_context() renders the result set as a numbered, citable block you can drop
straight into a prompt:
context = keenable.search("cerebras inference benchmarks").to_context()
prompt = f"Answer using only these sources, citing them by number.\n\n{context}\n\nQuestion: ..."
It emits [1] Title (url) headers followed by the page text, adds results whole
until the character budget is reached (max_chars=12000 by default), and never
truncates a source mid-sentence.
To print a source list that matches the citations in the answer, ask which results were actually rendered rather than listing them all:
results = keenable.search("cerebras inference benchmarks")
for index, result in enumerate(results.cited(), start=1):
print(f"[{index}] {result.title} - {result.url}")
Read a full page
page = keenable.fetch("https://cerebras.ai/chip")
print(page.title)
print(page.content) # markdown, boilerplate stripped
print(page.to_context()) # same citable block shape as search results
Tool calling
The SDK ships OpenAI-compatible tool definitions, so any inference API that speaks that schema can call Keenable directly:
from keenable import Keenable, TOOLS, run_tool_call
keenable = Keenable()
response = client.chat.completions.create(model=..., messages=messages, tools=TOOLS)
for call in response.choices[0].message.tool_calls or []:
messages.append(
{
"role": "tool",
"tool_call_id": call.id,
"content": run_tool_call(
keenable, call.function.name, call.function.arguments
),
}
)
TOOLS exposes keenable_search and keenable_fetch; run_tool_call executes
whichever the model picked and returns text ready for the tool message. Both
tools render the same numbered, citable block, so the model can cite a fetched
page the way it cites a search result. arun_tool_call is the async
counterpart, for use with AsyncKeenable.
Async
AsyncKeenable mirrors the sync client:
import asyncio
from keenable import AsyncKeenable
async def main():
async with AsyncKeenable() as keenable:
results = await keenable.search("wafer scale engine")
print(results.to_context())
asyncio.run(main())
Errors
All errors subclass KeenableError:
| Exception | When |
|---|---|
KeenableRateLimitError |
HTTP 429. Set KEENABLE_API_KEY to lift the keyless cap |
KeenableAuthError |
HTTP 401/403, the key was rejected |
KeenableAPIError |
Any other non-2xx response; carries status_code |
KeenableConnectionError |
The API could not be reached |
KeenableInvalidRequestError |
Bad arguments; no request was sent |
Configuration
| Variable | Default | Purpose |
|---|---|---|
KEENABLE_API_KEY |
unset | Lifts the hourly rate limit. Create one at keenable.ai/console |
KEENABLE_API_URL |
https://api.keenable.ai |
Override the API base URL |
Both can also be passed to the constructor as api_key and base_url, alongside
timeout and client_source. Building an integration on top of this SDK? Set
client_source="Your Integration" so your traffic is attributed to you rather
than to the bare SDK.
License
MIT
Metadata
Release files for keenable 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| keenable-0.1.1.tar.gz | 16.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| keenable-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.6 kB
Release files / keenable-0.1.1.tar.gz
| Download URL | keenable-0.1.1.tar.gz |
|---|---|
| Size | 16.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8ef95333abaeb77e335f60d089b8659ed2a1e4d9ce733c9d6c8fe21de552481a
|
|
BLAKE2b-256 checksum How to use checksums |
6afb16b351fed374132f594e7d8536cb6bccb576279030b89645bc1e3f59d9f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 15, 2026.
Transparency logRelease files / keenable-0.1.1-py3-none-any.whl
| Download URL | keenable-0.1.1-py3-none-any.whl |
|---|---|
| Size | 16.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c4a91e4408bf2e269fccb04ea348f2504173d08d0e4e73e905f923123e8a5b8c
|
|
BLAKE2b-256 checksum How to use checksums |
fd887a5e8408699247e9b21c80fe6fd0cd8a3772f71991d0eb6f62defea8c099
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 15, 2026.
Transparency log