# AI agents & LLMs

SerpWiz is built to be called by software — including LLM agents that need fresh search results.

## What's available

| Resource | URL | Use |
|---|---|---|
| `llms.txt` | [`https://serpwiz.com/llms.txt`](https://serpwiz.com/llms.txt) | Short index of the docs for LLMs. |
| `llms-full.txt` | [`https://serpwiz.com/llms-full.txt`](https://serpwiz.com/llms-full.txt) | Every docs page in one Markdown file. |
| Markdown pages | Append `.md` to any docs URL, e.g. [`/docs/google-search.md`](/docs/google-search.md) | Clean text without page chrome. |
| OpenAPI 3.1 | [`https://serpwiz.com/openapi.json`](https://serpwiz.com/openapi.json) | Tool and client generation. |
| MCP server | [`https://api.serpwiz.com/mcp`](/docs/mcp) | Hosted tools for Claude, ChatGPT, Cursor, VS Code and other MCP clients. Users connect by signing in (OAuth 2.1); no key to copy. |

## Function-calling schema

Drop this into any tool-use / function-calling API, then have your code call SerpWiz when the model asks:

```json
{
  "name": "google_search",
  "description": "Search Google in real time and return the results page as JSON (organic results, ads, top stories, knowledge panel, People Also Ask, related searches). Use for current events, facts that change, or anything after your training data.",
  "input_schema": {
    "type": "object",
    "properties": {
      "q":    { "type": "string", "description": "Search query. Supports Google operators like site: and quotes." },
      "gl":   { "type": "string", "description": "2-letter country code, e.g. us" },
      "hl":   { "type": "string", "description": "Language code, e.g. en" },
      "page": { "type": "integer", "minimum": 1, "description": "Results page, 10 per page" },
      "tbs":  { "type": "string", "description": "Time filter: qdr:h, qdr:d, qdr:w, qdr:m or qdr:y" }
    },
    "required": ["q"]
  }
}
```

The tool handler is one HTTP call:

```python
import os, requests

def google_search(**args):
    r = requests.get("https://api.serpwiz.com/v1/google/search", params=args,
                     headers={"X-API-Key": os.environ["SERPWIZ_API_KEY"]}, timeout=60)
    if r.status_code != 200:
        return {"error": r.json()["error"]["message"]}   # let the model see what went wrong
    data = r.json()
    # Trim to what the model needs: fewer tokens, same answer quality.
    return {
        "results": [{k: x.get(k) for k in ("position", "title", "url", "description")} for x in data.get("results", [])],
        "related": [k["keyword"] for k in data.get("related_keywords", {}).get("keywords", [])],
    }
```

## Tips for agents

- **Trim responses** before passing them to the model — titles, URLs and snippets are usually enough.
- **Failed calls are free**, so let the agent retry `429`/`5xx` after `Retry-After`.
- **Concurrency is capped by RPS.** Parallel tool calls past your limit get `429`; queue them or upgrade.
- **Keep the key server-side.** Never put an API key in a prompt or in client code.
