Empower LLM agents with QVeris: dynamically search for thousands of live tools (APIs, data sources, automations) and execute them in a tight agent loop.
QVeris provides a tool search + tool execution layer for agents:
- search: the agent can call
search_toolswith a natural-language capability query (e.g. “stock price”, “web search”, “send email”). - execute: after selecting a tool from search results, the agent calls
execute_toolwith the tool id + parameters.
The qveris.Agent wraps this into a loop that:
- searches for suitable tools to complete the task,
- executes proper tools (and your extra tools, if provided),
- feeds tool outputs back into the LLM until it reaches a final answer.
Set the following environment variables (or pass them via QverisConfig / provider configs):
QVERIS_API_KEY: Your QVeris API key. (Get it from QVeris)OPENAI_API_KEY: Your OpenAI (or OpenAI-compatible) provider API key.OPENAI_BASE_URL: Base URL for OpenAI-compatible providers (e.g. OpenAI, OpenRouter etc).
import asyncio
from qveris import Agent, Message
async def main():
# Uses env vars automatically (QVERIS_API_KEY / OPENAI_API_KEY / ...)
agent = Agent()
messages = [
Message(role="user", content="Find a weather tool and check New York weather.")
]
print("Assistant: ", end="", flush=True)
async for event in agent.run(messages): # streaming by default
if event.type == "content" and event.content:
print(event.content, end="", flush=True)
elif event.type == "tool_result" and event.tool_result:
tr = event.tool_result
name = tr.get("name", "unknown")
is_error = tr.get("is_error", False)
result = tr.get("result")
print(f"\n← tool_result: {name} (error={is_error})", flush=True)
if __name__ == "__main__":
asyncio.run(main())This repo includes two example scripts that show different integration styles:
- Interactive streaming chat (
examples/interactive_chat.py): a terminal chat UI that streams tokens and prints tool calls/results as they happen (great for debugging and demos). - Stock debate (
examples/stock_debate.py): two agents debate NVIDIA using non-streaming turns while still surfacing tool calls/results (demonstrates multi-agent orchestration and different models).
QVeris supports several ways to integrate, depending on how much control you want over events and UI.
Use Agent.run(messages) (streaming is the default). You’ll receive StreamEvents as the model streams content and as tools are invoked.
Use Agent.run(messages, stream=False) and handle StreamEvents:
content(full assistant message, non-streaming)tool_call(what the model asked to run)tool_result(what actually ran + output)metrics(token usage if available)error
If you only need the final assistant text (no tool-calls), use:
final_text = await agent.run_to_completion(messages)If you already have an agent framework (or want full control), you can directly use:
qveris.client.tools.SEARCH_TOOL_DEF/EXECUTE_TOOL_DEFto expose tool schemas to your LLMqveris.client.tools.DEFAULT_SYSTEM_PROMPTas a starting system promptqveris.client.api.QverisClientto handle QVeris tool calls
Your loop is responsible for:
- sending messages + tool schemas to the LLM,
- detecting tool calls,
- calling
QverisClient.handle_tool_call(...), - appending tool results back into messages until completion.
By default, Agent() uses an internal OpenAI-compatible provider. If your model API is not OpenAI-compatible, implement a provider that follows LLMProvider (qveris/llm/base.py) and pass it to Agent:
from typing import AsyncGenerator, List
from qveris.llm.base import LLMProvider
from qveris.types import Message, StreamEvent, ChatResponse
from openai.types.chat import ChatCompletionToolParam
from qveris.config import AgentConfig
class MyProvider(LLMProvider):
async def chat_stream(
self,
messages: List[Message],
tools: List[ChatCompletionToolParam],
config: AgentConfig,
) -> AsyncGenerator[StreamEvent, None]:
# Yield StreamEvent(type="content", content="...") and/or tool_call/metrics/etc.
...
async def chat(
self,
messages: List[Message],
tools: List[ChatCompletionToolParam],
config: AgentConfig,
) -> ChatResponse:
# Return ChatResponse(content="...", tool_calls=[...], metrics={...})
...
agent = Agent(llm_provider=MyProvider())- Provider Agnostic: Works with OpenAI, OpenRouter, LocalAI, etc.
- Auto-Tool Execution: The agent automatically searches for tools, executes them, and returns results.
- Smart Context: Automatically prunes old tool results to save tokens (
enable_history_pruning=True). - Multiple Agents: Configure different agents with unique system prompts and temperatures.
- Reasoning Support: Captures reasoning traces from models like Gemini (via OpenRouter) or DeepSeek.