The langchain-apiverve package turns endpoints into LangChain tools with typed argument
schemas, so an agent can call them without you hand-writing a Tool per endpoint. Schemas are
fetched from the published catalog at startup, which means a new endpoint becomes an available
tool without a package upgrade.
pip install langchain-apivervePython 3.9 or later.
The shortest working example
from langchain_apiverve import APIVerveToolkit
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_openai import ChatOpenAI
toolkit = APIVerveToolkit(api_key="apv_...")
tools = toolkit.get_tools(categories=["Validation"])
llm = ChatOpenAI(model="gpt-4o")
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools)
executor.invoke({"input": "Is test@example.com a real address?"})Keep the key out of the source. The toolkit reads APIVERVE_API_KEY when you do not pass one:
export APIVERVE_API_KEY="apv_..."toolkit = APIVerveToolkit() # key comes from the environmentSee security for where credentials should live.
Do not give an agent every tool
This is the whole of the advice on this page, and it is the thing most likely to make the difference between an agent that works and one that does not.
get_tools() with no arguments returns a tool for essentially the entire catalog. Every one of
those definitions is serialised into the model's context on every turn. The practical effects
are a large fixed token cost per call, a slower and more expensive agent, and — the real
problem — worse tool selection, because a model choosing between hundreds of similarly-named
options picks wrong more often than one choosing between six.
Four ways to narrow it, in rough order of usefulness:
toolkit.get_tools(categories=["Validation", "Geolocation"])
toolkit.get_tools(include_apis=["emailvalidator", "iplookup", "dnslookup"])
toolkit.get_tools(exclude_apis=["websitescreenshot"])
toolkit.get_tools(max_tools=25)include_apis is the one to reach for in production. An agent with a deliberately chosen
handful of tools is more reliable than one with everything, and you almost always know which
handful the job needs.
To find out what is available while you are deciding:
toolkit.list_categories() # category names
toolkit.list_available_apis() # ids, titles, categories
toolkit.total_apis() # how many were loadedinclude_apis and get_tool take the endpoint's id as published — emailvalidator, not
emailvalidation. A mistyped id is silently absent from the returned list rather than an error,
so an agent that "ignores" a tool is often a tool that was never created. Check against
the catalog, or list_available_apis().
Using one endpoint without an agent
A tool is callable on its own, which is often all you want — deterministic enrichment feeding a chain, with no model deciding whether to call it:
toolkit = APIVerveToolkit()
ip_tool = toolkit.get_tool("iplookup")
data = ip_tool.invoke({"ip": "8.8.8.8"})get_tool returns None for an unknown id, so check the result before using it.
This is usually the better design when the call is not conditional. Deciding whether to look up an IP is a job for a model; looking it up is not, and paying a model to make a decision that is already made adds latency and a failure mode for nothing.
Startup and caching
The toolkit fetches schemas from the published catalog when it is first constructed and caches them in memory for the life of the process. So:
Construct the toolkit once, at startup, not per request. Each new process pays the fetch.
Startup requires network access to the catalog. There is no bundled fallback — if the fetch
fails the constructor raises RuntimeError rather than starting with a partial tool set. In a
locked-down environment, allow assets.apiverve.com.
A long-lived process will not see new endpoints until it restarts or you call
load_api_schemas(force_refresh=True).
Errors
Tool failures raise APIVerveError, which carries status_code and the response body:
from langchain_apiverve import APIVerveError
try:
result = ip_tool.invoke({"ip": "not-an-ip"})
except APIVerveError as e:
print(e.status_code, e)The status codes mean what they mean everywhere else — see
error handling. 401 is the only authentication verdict; 429 is a rate
limit or an exhausted balance.
Decide deliberately whether to let the error reach the agent. Returning the message to the model
lets it retry with a corrected argument, which is often what you want for a 400. For a 429
it is not — the model cannot fix an exhausted balance and will burn turns trying.
What it costs
One call per tool invocation, at that endpoint's rate. Building the toolkit and listing APIs are free.
Agents make this harder to predict than a normal integration, because the number of calls is a
model's decision rather than yours. Two guards worth having from the start: cap agent iterations
with max_iterations on the executor, and give the agent the narrowest tool set that can do the
job. Watch the first day's usage in analytics before leaving anything
running unattended.
Next
MCP is the other way to give a model these tools, and needs no package at all — worth comparing if your agent framework speaks it. All endpoints is the catalog the toolkit loads.