Skip to content
AGNT
All guides
Ecosystem workflowintermediate

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.

AGNT Developer Experience12 minverified 2026-04-12

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.content

The `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 results

Memory 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.

Next steps