The examples use
deepseek/deepseek-v4.1-flash; any OpenRouter model that supports tool calling works. Set OPENROUTER_API_KEY first.
Python
TOOLS holds OpenAI-format definitions for keenable_search and keenable_fetch. run_tool_call runs whichever one the model picked and returns a numbered, citable block for the tool message, so the model can cite a fetched page the same way it cites a search result. Filters, async and errors are in the SDK reference.
TypeScript, AI SDK
stopWhen lets the model search, read the results and then answer; without it generateText stops after the first step and returns only the tool call. The same tools work in streamText. To keep the key out of environment variables on Vercel, see Vercel.
OpenRouter Agent SDK, MCP
createMCPTools reads the tool list from the Keenable MCP server and runs the calls, so there is no tool code to write. To use your key, pass it as a header:
Use your API key
Set
KEENABLE_API_KEY to authenticate — this removes the hourly request cap. Without a key, calls run on the shared public tier at lower rate limits.@keenable/ai-sdk read KEENABLE_API_KEY from the environment; the MCP client takes it as the header above. Create a key in the Keenable console.
Billing
OpenRouter bills the model’s tokens, including the search results the model reads. Keenable calls are billed separately against your Keenable credits, or run on the public tier without a key. This setup is separate from OpenRouter’s ownopenrouter:web_search server tool: Keenable runs as your tool, so it behaves the same on every model and every call goes through your code.