Skip to main content

Chatbot Agent

A conversational AI chatbot with context memory using Ollama.

Difficulty: Basic

tip

This example is covered step-by-step in the Tutorial. The tutorial walks through creating, running, and understanding this agent in detail.

Quick Reference

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

What You'll Learn

  • LangGraph add_messages for conversation history
  • AgentVisor™ checkpointing for state persistence
  • HTTP proxy for LLM access
  • Basic policy structure

Architecture

User -> Thread API -> Agent -> HTTP Proxy -> Ollama LLM
|
Checkpointer (Temporal)

Key Code

State Definition

from langgraph.graph.message import add_messages

class ChatState(TypedDict):
messages: Annotated[list, add_messages]

The add_messages annotation automatically accumulates conversation history.

LLM Setup

import os

from langchain_ollama import ChatOllama

OLLAMA_BASE_URL = os.environ.get("OLLAMA_BASE_URL", "http://localhost:11434")
OLLAMA_MODEL = os.environ.get("OLLAMA_MODEL", "llama3.2:1b")

llm = ChatOllama(
base_url=OLLAMA_BASE_URL,
model=OLLAMA_MODEL,
temperature=0.7,
)

All requests go through AgentVisor's HTTP proxy automatically. The default OLLAMA_BASE_URL is a loopback address, which the proxy's SSRF guard blocks by default — this template ships an agentvisor.yaml that allowlists it (see Policy Highlights below and proxy.ssrf_allowed_cidrs in the configuration reference).

Graph

builder = StateGraph(ChatState)
builder.add_node("chat", chat)
builder.set_entry_point("chat")
builder.add_edge("chat", END)

graph = builder.compile(checkpointer=AgentVisorCheckpointer())

Policy Highlights

Unlike the newer annotations-driven examples, this policy hardcodes the allowed pattern directly in Rego rather than reading it from a resource annotation:

# Extract target from MRN (mrn:agentvisor:http:host/path -> host/path)
http_target := substring(input.resource.id, count("mrn:agentvisor:http:"), -1)

# Allow Ollama endpoints
allow if {
helpers.is_authenticated
regex.match("^ollama(:\\d+)?(/.*)?$", http_target)
}

# Also allow localhost:11434 / 127.0.0.1:11434 for --sandbox=none

Next Steps