Loop
How it worksThe loopWhy LoopPricingDocs
guide LangChain · LangGraph

Use Loop with LangChain.

Decorate Loop's REST calls with @tool and pass them to create_react_agent from LangGraph — or any LangChain AgentExecutor. The agent searches, verifies, and reports outcomes automatically. No key required in the free tier.

option 1 LangGraph create_react_agent (recommended)

create_react_agent from langgraph.prebuilt is the modern LangChain-ecosystem way to build tool-calling agents. Decorate each Loop wrapper with @tool from langchain.tools, pass them with a chat model — the agent handles tool dispatch and looping.

Install: pip install langchain langchain-openai langgraph requests
loop_langchain.py
from langchain.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
import requests

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

@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 table for 4'.
        location: Area hint, default Kreuzberg, Berlin.
    """
    return requests.get(f"{BASE}/search", params={"q": query, "location": location}).json()[
        "results"
    ]


@tool
def get_loop_details(result_id: str) -> dict:
    """Get full details for a Loop search result, including a result_token for report().

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


@tool
def verify_loop(result_id: str, claim: str) -> dict:
    """Re-check a specific claim against live sources before acting.

    Args:
        result_id: id from a search result.
        claim: What to verify, e.g. 'is_open_now', 'has_outdoor_seating'.
    """
    return requests.get(f"{BASE}/verify/{result_id}", params={"claim": claim}).json()


@tool
def report_loop(result_token: str, outcome: str) -> dict:
    """Report what happened after acting on a Loop result. Improves data for everyone.

    Args:
        result_token: From get_loop_details(), valid 30 minutes.
        outcome: One of correct, wrong, booked, closed, other.
    """
    return requests.post(
        f"{BASE}/report", json={"result_token": result_token, "outcome": outcome}
    ).json()


tools = [search_loop, get_loop_details, verify_loop, report_loop]
llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = create_react_agent(llm, tools)

result = agent.invoke({"messages": [("user", "Find a vegan restaurant with outdoor seating in Kreuzberg")]})
print(result["messages"][-1].content)
option 2 async tools — parallel details + verify

LangGraph supports async tools natively. Use httpx.AsyncClient to fan out get_details and verify in parallel — useful when the agent needs to check multiple candidates quickly.

Install: pip install langchain langchain-openai langgraph httpx
loop_langchain_async.py
import asyncio
import httpx
from langchain.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

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

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

    Args:
        query: Natural-language need, e.g. 'quiet table for 2'.
        location: Area hint, default Kreuzberg, Berlin.
    """
    async with httpx.AsyncClient() as client:
        r = await client.get(f"{BASE}/search", params={"q": query, "location": location})
        return r.json()["results"]


@tool
async def get_and_verify(result_id: str, claim: str = "open now") -> dict:
    """Get full details and verify a claim in parallel.

    Args:
        result_id: id from a search result.
        claim: Claim to verify live, default 'open now'.
    """
    async with httpx.AsyncClient() as client:
        details_req = client.get(f"{BASE}/details/{result_id}")
        verify_req = client.get(f"{BASE}/verify/{result_id}", params={"claim": claim})
        details_r, verify_r = await asyncio.gather(details_req, verify_req)
        return {**details_r.json(), "observation": verify_r.json()}


llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = create_react_agent(llm, [search_loop_async, get_and_verify])

async def main():
    result = await agent.ainvoke(
        {"messages": [("user", "Outdoor vegan table for 4 in Kreuzberg, verify it's open now")]}
    )
    print(result["messages"][-1].content)

asyncio.run(main())
Prefer MCP? If your LangChain setup supports MCP clients, point it at https://stayinloop.dev/mcp. The four tools load automatically with no schema wrappers. See the Claude guide for the MCP connector path.
Free tier: 30 reads/min, no key required. To get 60 reads/min and appear named on the signals board, pass Authorization: Bearer sk_live_… as a header or append ?key=sk_live_… to any URL.
← Full API referenceWatch your calls on the signals board →