Skip to main content

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)

Source distribution for keenable 0.1.1
File Size Uploaded
keenable-0.1.1.tar.gz 16.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for keenable 0.1.1
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page