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
| Tool | Description | HTTP Access |
|---|---|---|
get_current_time | Current UTC time | None (local) |
calculate | Math expressions | None (local) |
lookup_fact | Wikipedia lookup | Wikipedia 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
- Task Agent: Human-in-the-loop workflows