Docs/Integrations/LangChain

LangChain

Turning the catalog into LangChain tools — installing the toolkit, and why selecting a subset matters more than loading all of them.

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.

bash
pip install langchain-apiverve

Python 3.9 or later. The agent examples use LangChain 1.x (pip install -U langchain) and a model provider package, here langchain-openai.

The shortest working example

python
from langchain.agents import create_agent
from langchain_apiverve import APIVerveToolkit

toolkit = APIVerveToolkit(api_key="apv_...")
tools = toolkit.get_tools(include_apis=["emailvalidator", "disposableemailchecker"])

agent = create_agent(model="openai:gpt-4o", tools=tools)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "Is test@example.com a real address?"}]}
)
print(result["messages"][-1].content)

Keep the key out of the source. The toolkit reads APIVERVE_API_KEY when you do not pass one:

export APIVERVE_API_KEY="apv_..."

See 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:

python
toolkit.get_tools(categories=["Data Validation", "Geography"])
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:

python
toolkit.list_categories()        # category names
toolkit.list_available_apis()    # ids, titles, categories
toolkit.total_apis               # how many were loaded

Category names are matched exactly, so use the names list_categories() returns, such as "Data Validation" rather than "Validation". An unknown category returns no tools.

Endpoint ids are exact

include_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:

python
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:

python
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.

Inside an agent built with create_agent, an APIVerveError is not handed back to the model: it ends the run and raises from agent.invoke. Catch it there:

python
try:
    result = agent.invoke({"messages": [{"role": "user", "content": "Where is 8.8.8.8?"}]})
except APIVerveError as e:
    print(e.status_code, e)

That is the right default for a 401 or a 429, which the model cannot fix and would burn turns retrying. If you want the model to see a 400 and try a corrected argument, catch the error in a wrapper tool or middleware and return the message as the tool result instead.

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 each run's steps with recursion_limit, and give the agent the narrowest tool set that can do the job:

python
agent.invoke({"messages": [...]}, config={"recursion_limit": 10})

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.

Was this page helpful?

Last updated