HyperSaaS
BackendAI Chat

Tools

Plain Python tools available to AI agents.

Tools in HyperSaaS are plain Python functions with no framework-specific decorators. Each agent handler wraps them for its own runtime.

Available Tools

ToolFileDescription
Web Searchchat/tools/web_search.pySearch Google through SerpApi
Weatherchat/tools/weather.pyGet current weather via WeatherAPI.com
Locationchat/tools/location.pyFind a place's coordinates via the Google Geocoding API
Knowledge Basedocuments/rag_tool.pySearch attached knowledge bases (RAG)
URL Ingestdocuments/url_ingest_tool.pyIngest content from a URL

Tool Architecture

Tools are defined as plain functions in chat/tools/:

# chat/tools/weather.py
def get_weather(location: str) -> str:
    """Get current weather for a location."""
    # Pure Python — no @tool decorator, no framework imports
    response = requests.get(WEATHER_API_URL, params={"q": location, "key": API_KEY})
    return response.json()

Each handler wraps them differently:

LangGraph (in chat/handlers/langgraph/tools.py):

from langchain_core.tools import tool
from backend.chat.tools.weather import get_weather as get_weather_impl

@tool
def get_weather(location: str) -> str:
    """Get current weather for a location."""
    return get_weather_impl(location)

PydanticAI (in chat/handlers/pydantic_ai/agent.py):

@agent.tool_plain
def get_weather(location: str) -> str:
    """Get current weather for a location."""
    return get_weather_impl(location)

Tool registration in the LangGraph wrapper module is guarded by except ImportError blocks that log a warning naming the disabled tool — a broken dependency degrades that one capability visibly instead of silently removing it from every agent session.

Knowledge Base Search Tool

The RAG tool is special — it needs access to the chat session to know which knowledge bases to search:

# documents/rag_tool.py
def search_knowledge_base_impl(query: str, session) -> str:
    """Pure function — no framework dependency."""
    results = search_documents(
        query=query,
        session_id=str(session.id),
        workspace_id=str(session.workspace_id),
    )
    return json.dumps(results)

The LangGraph wrapper uses InjectedToolArg to inject the session at runtime:

@tool
def search_knowledge_base(
    query: str,
    config: Annotated[RunnableConfig, InjectedToolArg],
) -> str:
    session = config["configurable"]["session"]
    return search_knowledge_base_impl(query, session)

Knowledge-Base Questions

When a chat has knowledge bases attached, the LangGraph agent's first step for each question is a knowledge-base search, made by the graph rather than left to the model. Models told to search still answer questions that look like general knowledge from memory. On the benchmark, every answer graded below 4 out of 5 was one where the agent had skipped the search. Answers must cite the results they used.

Agent Limits

An agent run stops after 10 steps (recursion_limit), so one message can't loop through tools indefinitely. Tool results reach the model marked as untrusted data.

Web search, location and weather call paid APIs. Each call that returns an answer is recorded as AIUsage with purpose tool_call, at a fixed price per call, against the chat's workspace and the person asking. Both agent frameworks record under the LangGraph tools' names:

# workspaces/usage.py
TOOL_CALL_PRICES = {
    "google_search_serp_api_tool": Decimal("0.015"),  # SerpApi Developer: $75 for 5,000 searches
    "get_location_coordinates": Decimal("0.005"),     # Google Geocoding API: $5 per 1,000 requests
    "get_weather_forecast": Decimal("0.0001"),        # WeatherAPI.com
}

A call that comes back with an error (a missing key, bad input, an outage) costs nothing. Change the prices to match your plans. The knowledge-base search records its own model calls (rewriting, embedding, reranking) as it runs.

Adding a New Tool

  1. Create chat/tools/your_tool.py with a plain Python function
  2. Add the LangChain wrapper in chat/handlers/langgraph/tools.py
  3. Add the PydanticAI wrapper in chat/handlers/pydantic_ai/agent.py
  4. Update the system prompt in chat/handlers/langgraph/nodes.py to describe the tool
  5. If it calls a paid API, add its price to TOOL_CALL_PRICES, keyed by the tool's name

Required API Keys

ToolEnvironment Variable
Web SearchSERPAPI_API_KEY
WeatherWEATHERAPI_COM_API_KEY
LocationGOOGLE_MAPS_API_KEY
Knowledge BaseOPENAI_API_KEY (for embeddings)

On this page