Use OpenAI function calling with AGNT venue tools
Define AGNT's venue search, booking, and memory APIs as OpenAI function definitions — any GPT-4 agent can call them natively.
This guide walks you through defining AGNT's core endpoints as OpenAI function definitions, then building a chat loop that lets GPT-4 call them autonomously. By the end, your OpenAI-powered agent can search venues, book tables, and remember user preferences — all proxied through AGNT's REST API with no custom middleware.
Prerequisites
- An AGNT developer API key (get one at /developers).
- Python 3.10+ with the openai package installed.
- An OpenAI API key with GPT-4 access.
What you're building
A GPT-4 agent with three function definitions: `search_venues` (semantic venue search by intent), `create_booking` (book a table at a venue), and `read_user_memory` (retrieve user preferences for personalization). When GPT-4 decides to call a function, your code proxies the call to AGNT's REST API, injects the result back into the conversation, and lets the model compose a natural-language response.
The key insight: OpenAI's function calling is the integration layer. You define the schema once, and the model figures out when and how to call each function based on the user's message. No prompt hacks, no regex parsing — structured tool use all the way down.
Step 1 — Get an AGNT API key
Head to [/developers](/developers) and generate a developer key. Give it scopes for `venues.read`, `bookings.write`, and `memory.read`. The key starts with `ag_` and is shown exactly once — store it in your password manager immediately.
You'll use this key in the Authorization header for every AGNT API call your function-calling loop makes.
Step 2 — Define AGNT functions for OpenAI
OpenAI's function calling requires a JSON schema for each function. Here are the three definitions for AGNT's core endpoints:
agnt_functions = [
{
"name": "search_venues",
"description": "Search for restaurants, bars, and cafes in Bali by intent, cuisine, or vibe.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Natural language search query, e.g. 'romantic sunset dinner in Uluwatu'"
},
"city": {
"type": "string",
"description": "City to search in, e.g. 'Bali', 'Canggu', 'Ubud'",
"default": "Bali"
},
"limit": {
"type": "integer",
"description": "Max number of results to return",
"default": 5
}
},
"required": ["query"]
}
},
{
"name": "create_booking",
"description": "Book a table at an AGNT venue. Returns a confirmation with booking ID and details.",
"parameters": {
"type": "object",
"properties": {
"venue_id": {
"type": "string",
"description": "The AGNT venue UUID from search results"
},
"date": {
"type": "string",
"description": "Booking date and time in ISO 8601 format, e.g. '2026-04-15T19:00:00'"
},
"party_size": {
"type": "integer",
"description": "Number of guests"
}
},
"required": ["venue_id", "date", "party_size"]
}
},
{
"name": "read_user_memory",
"description": "Read stored preferences and history for a user. Use before searching to personalize results.",
"parameters": {
"type": "object",
"properties": {
"user_id": {
"type": "string",
"description": "The AGNT user UUID"
},
"keys": {
"type": "array",
"items": { "type": "string" },
"description": "Memory keys to retrieve, e.g. ['dietary', 'price_range', 'favorite_areas']"
}
},
"required": ["user_id"]
}
}
]The `description` fields are critical — GPT-4 uses them to decide when to call each function. Keep them concrete: what the function does, what kind of input it expects, and what it returns.
Step 3 — Build the function calling loop
The core loop: send a chat completion with the function definitions, check if the model wants to call a function, execute the call against AGNT's API, inject the result, and let the model respond.
import json
import os
import requests
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
AGNT_API_KEY = os.environ["AGNT_API_KEY"]
AGNT_BASE = "https://api.agntdot.com/api"
def call_agnt(name: str, args: dict) -> dict:
"""Proxy a function call to AGNT's REST API."""
headers = {"Authorization": f"Bearer {AGNT_API_KEY}"}
if name == "search_venues":
resp = requests.get(
f"{AGNT_BASE}/venues/search",
params={"q": args["query"], "city": args.get("city", "Bali"), "limit": args.get("limit", 5)},
headers=headers,
)
elif name == "create_booking":
resp = requests.post(
f"{AGNT_BASE}/bookings",
json={"venue_id": args["venue_id"], "date": args["date"], "party_size": args["party_size"]},
headers=headers,
)
elif name == "read_user_memory":
resp = requests.get(
f"{AGNT_BASE}/memory",
params={"user_id": args["user_id"], "keys": ",".join(args.get("keys", []))},
headers=headers,
)
else:
return {"error": f"Unknown function: {name}"}
return resp.json()
def chat(user_message: str, messages: list) -> str:
messages.append({"role": "user", "content": user_message})
response = client.chat.completions.create(
model="gpt-4",
messages=messages,
functions=agnt_functions,
function_call="auto",
)
msg = response.choices[0].message
# Loop while the model wants to call functions
while msg.function_call:
fn_name = msg.function_call.name
fn_args = json.loads(msg.function_call.arguments)
# Execute against AGNT
result = call_agnt(fn_name, fn_args)
# Inject the function result back into the conversation
messages.append(msg) # the assistant's function_call message
messages.append({
"role": "function",
"name": fn_name,
"content": json.dumps(result),
})
# Let the model process the result
response = client.chat.completions.create(
model="gpt-4",
messages=messages,
functions=agnt_functions,
function_call="auto",
)
msg = response.choices[0].message
messages.append(msg)
return msg.contentThe `while msg.function_call` loop is the key pattern. GPT-4 may chain multiple function calls — for example, reading memory first, then searching with personalized parameters. The loop handles this transparently.
Step 4 — Handle booking confirmations
When `create_booking` succeeds, AGNT returns a structured confirmation. Your agent should format it as a clear, user-friendly message:
# AGNT booking response shape:
# {
# "booking_id": "bk_a1b2c3d4",
# "venue_name": "Cafe Vida",
# "date": "2026-04-15T19:00:00",
# "party_size": 2,
# "status": "confirmed",
# "confirmation_code": "VIDA-8842",
# "cancellation_deadline": "2026-04-15T17:00:00"
# }GPT-4 will naturally format this into a conversational confirmation — something like: "Your table for 2 at Cafe Vida is confirmed for April 15 at 7 PM. Confirmation code: VIDA-8842. You can cancel up to 2 hours before." The structured response gives the model everything it needs without you writing formatting templates.
Step 5 — Add memory for personalization
The real power unlocks when you read user memory before searching. Memory lets the agent incorporate dietary restrictions, budget preferences, and favorite neighborhoods without the user repeating themselves every session.
# In your system prompt, instruct GPT-4 to check memory first:
system_prompt = """You are a venue discovery assistant powered by AGNT.
Before searching for venues, call read_user_memory to check if the user
has stored preferences (dietary restrictions, price range, favorite areas).
Incorporate those preferences into your search query."""
messages = [{"role": "system", "content": system_prompt}]
# Now when the user says "find me dinner tonight", GPT-4 will:
# 1. Call read_user_memory(user_id="...", keys=["dietary", "price_range", "favorite_areas"])
# 2. Get back: {"dietary": "vegetarian", "price_range": "mid", "favorite_areas": ["Canggu", "Pererenan"]}
# 3. Call search_venues(query="vegetarian dinner mid-range Canggu or Pererenan")
# 4. Return personalized resultsMemory turns a generic venue search into a personalized concierge. The user says "find me dinner" and gets vegetarian spots in Canggu because the agent already knows their preferences. This is the same memory layer that powers AGNT's native Telegram bot — your OpenAI agent reads the same user profile.
Why this matters
OpenAI function calling is the most widely deployed tool-use interface in production today. By defining AGNT's endpoints as function schemas, you make the entire AGNT venue network accessible to any GPT-4 application — chatbots, assistants, autonomous agents, Zapier AI actions, anything that speaks the OpenAI API.
The function definitions are the integration layer. No custom middleware, no webhook plumbing, no SDK to maintain. Define the schema, point the proxy at AGNT's REST API, and the model handles the rest. When AGNT adds new endpoints, you add new function definitions — the loop code never changes.