Loop
How it worksThe loopWhy LoopPricingDocs
guide OpenAI Agents SDK

Use Loop with OpenAI Agents.

Wrap Loop's REST API as @function_tool decorators and drop them into any gpt-4o or o3 agent. The SDK auto-generates JSON schemas from your type hints and docstrings — no manual tool definitions needed.

Install: pip install openai-agents requests. Set OPENAI_API_KEY in your env. No Loop key required in the free tier (30 reads/min).
option 1 Agents SDK — four Loop tools

Define all four Loop operations as @function_tool functions, pass them to Agent(tools=[...]), and let the model decide when to call each one.

loop_agent.py
import asyncio
import requests
from agents import Agent, Runner, function_tool

BASE = "https://api.stayinloop.dev/v1"


@function_tool
def search_loop(query: str, location: str = "Kreuzberg, Berlin") -> list:
    """Search for local businesses using Loop.

    Args:
        query: Natural language description, e.g. "vegan outdoor seating".
        location: Area hint, default is Kreuzberg, Berlin.
    """
    return requests.get(
        f"{BASE}/search",
        params={"q": query, "location": location},
    ).json()["results"]


@function_tool
def get_loop_details(result_id: str) -> dict:
    """Get full details and a result_token for a Loop result.

    Args:
        result_id: The result_id from a search() result.
    """
    return requests.get(f"{BASE}/details/{result_id}").json()


@function_tool
def verify_loop(result_id: str, claim: str) -> dict:
    """Verify a specific claim about a business live.

    Args:
        result_id: The result_id from a search() result.
        claim: What to check, e.g. "open tonight" or "has outdoor seating".
    """
    return requests.get(
        f"{BASE}/verify/{result_id}",
        params={"claim": claim},
    ).json()


@function_tool
def report_loop(result_token: str, outcome: str) -> dict:
    """Report what happened after acting on a result. Mutates the record's confidence.

    Args:
        result_token: The token returned by get_loop_details().
        outcome: One of: correct, wrong, booked, closed, other.
    """
    return requests.post(
        f"{BASE}/report",
        json={"result_token": result_token, "outcome": outcome},
    ).json()


agent = Agent(
    name="Loop agent",
    instructions=(
        "You help users find local businesses in Kreuzberg, Berlin. "
        "Always call search_loop first, then get_loop_details for the chosen result. "
        "Call verify_loop before making a definitive claim. "
        "Call report_loop with the outcome when the task is done."
    ),
    tools=[search_loop, get_loop_details, verify_loop, report_loop],
)


async def main():
    result = await Runner.run(
        agent,
        "Find a quiet vegan restaurant with outdoor seating for tonight.",
    )
    print(result.final_output)


asyncio.run(main())
option 2 async agent — parallel details + verify

Async @function_tool functions work natively with the SDK. Use asyncio.gather to fan out get_details and verify in one round-trip.

loop_async_agent.py
import asyncio
import httpx
from agents import Agent, Runner, function_tool

BASE = "https://api.stayinloop.dev/v1"


@function_tool
async def search_loop_async(query: str, location: str = "Kreuzberg, Berlin") -> list:
    """Search for local businesses. Async version for high-throughput agents.

    Args:
        query: Natural language search query.
        location: Area hint.
    """
    async with httpx.AsyncClient() as client:
        r = await client.get(
            f"{BASE}/search",
            params={"q": query, "location": location},
        )
    return r.json()["results"]


@function_tool
async def get_and_verify(result_id: str, claim: str) -> dict:
    """Get details and verify a claim in parallel.

    Args:
        result_id: The result_id from a search result.
        claim: What to verify, e.g. "open now".
    """
    async with httpx.AsyncClient() as client:
        details, obs = await asyncio.gather(
            client.get(f"{BASE}/details/{result_id}"),
            client.get(f"{BASE}/verify/{result_id}", params={"claim": claim}),
        )
    return {**details.json(), "observation": obs.json()}


agent = Agent(
    name="Loop async agent",
    instructions="Find businesses and verify claims using Loop. Always call get_and_verify.",
    tools=[search_loop_async, get_and_verify],
)


async def main():
    result = await Runner.run(agent, "Is Burgermeister in Kreuzberg open right now?")
    print(result.final_output)


asyncio.run(main())
ChatGPT connector: custom MCP connectors in ChatGPT require a Business or Enterprise/Edu account. For code-based agents this @function_tool approach is the recommended path. ChatGPT guide →
← Full API referencePython REST guide →