Skip to main content

QA Agent

A Q&A assistant with tool calling capabilities.

Difficulty: Intermediate

What You'll Learn

  • LangGraph bind_tools() for tool calling
  • ReAct pattern (reason then act)
  • Tool policy enforcement
  • Multiple HTTP endpoints

Available Tools

ToolDescriptionHTTP Access
get_current_timeCurrent UTC timeNone (local)
calculateMath expressionsNone (local)
lookup_factWikipedia lookupWikipedia API

Setup

agentvisor template create langgraph/qa-agent
cd qa-agent
docker compose up -d
agentvisor serve .

Test It

THREAD=$(curl -sX POST http://localhost:8090/threads | jq -r '.thread_id')

# Time query (uses tool)
curl -sX POST "http://localhost:8090/threads/$THREAD/runs?wait=60s" \
-H "Content-Type: application/json" \
-d '{"input": {"messages": [{"role": "user", "content": "What time is it?"}]}}'

# Calculator (uses tool)
curl -sX POST "http://localhost:8090/threads/$THREAD/runs?wait=60s" \
-H "Content-Type: application/json" \
-d '{"input": {"messages": [{"role": "user", "content": "Calculate sqrt(144) + 10"}]}}'

# Wikipedia (HTTP call through proxy)
curl -sX POST "http://localhost:8090/threads/$THREAD/runs?wait=60s" \
-H "Content-Type: application/json" \
-d '{"input": {"messages": [{"role": "user", "content": "Tell me about Python programming"}]}}'

Key Code

Tool Binding

from langchain_core.tools import tool

@tool
def calculate(expression: str) -> str:
"""Evaluate a mathematical expression."""
# ... implementation

llm = ChatOllama(...)
llm_with_tools = llm.bind_tools([get_current_time, calculate, lookup_fact])

ReAct Graph

builder.add_node("assistant", assistant)
builder.add_node("tools", ToolNode(ALL_TOOLS))

builder.add_conditional_edges(
"assistant",
should_continue,
{"tools": "tools", "end": END}
)
builder.add_edge("tools", "assistant")

Policy Highlights

# Tool allowlist
annotations:
- name: "allowed_tools"
value:
- "get_current_time"
- "calculate"
- "lookup_fact"

# HTTP allowlist (Ollama + Wikipedia)
annotations:
- name: "allowed_patterns"
value:
- "^ollama.*"
- "^en\\.wikipedia\\.org(/.*)?$"

Next Steps