> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.wantdot.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.wantdot.com/_mcp/server.

# Example: a buyer's agent

> A complete buyer agent in about forty lines of Python.

A complete agent in about forty lines of Python, using only the standard library. It checks a domain; if the owner takes offers, it asks its person to approve limits; once approved, it makes one offer and reports where it stands.

It cannot accept a deal or pay. Those are your own tap, on the link we email you.

## The flow

1. `check_domain`: is there a verified owner who takes offers?
2. `request_mandate`: asks you, by email, to approve the limits. It returns a mandate token. **You must press Approve before the token works.**
3. `offer_with_mandate`: makes an offer inside the limits, marked as sent by an AI agent.
4. `list_my_offers`: shows where each offer stands and whose turn it is.

When it is your agent's turn it can use `counter_offer` or `withdraw_offer`. See the [tool reference](/reference).

## The code

Save as `example-buyer-agent.py`.

```python
"""A buyer's agent for WantDot, using only the Python standard library.

It checks a domain, and if the verified owner takes offers it asks its person to approve a
mandate by email. Once approved, it makes one offer inside the mandate and reports where it stands.
It cannot accept a deal or pay: those are always the person's own tap, on the link we email them.
"""
import json
import sys
import urllib.request

ENDPOINT = "https://wantdot.com/mcp"


def tool(name, **arguments):
    """Call one WantDot tool. Returns its structured result."""
    body = {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": name, "arguments": arguments}}
    request = urllib.request.Request(
        ENDPOINT,
        data=json.dumps(body).encode(),
        headers={"Content-Type": "application/json", "Accept": "application/json, text/event-stream"},
    )
    with urllib.request.urlopen(request, timeout=30) as response:
        reply = json.load(response)
    if "error" in reply:
        sys.exit(f"{name} failed: {reply['error']['message']}")
    return reply["result"]["structuredContent"]


def main(domain, email, max_usd, offer_usd, mandate_token=None):
    found = tool("check_domain", domain=domain)
    print(f"{found['domain']}: {found['status']}")
    if not found.get("wantdot", {}).get("takesOffers"):
        print("The owner is not taking offers on WantDot. Nothing more to do here.")
        return

    if not mandate_token:
        asked = tool("request_mandate", email=email, max_usd=max_usd, domains=[domain], label="Example buyer agent")
        print(f"Asked {email} to approve. Run again with the token once they press Approve:\n{asked['mandateToken']}")
        return

    placed = tool("offer_with_mandate", mandate_token=mandate_token, domain=domain, amount_usd=offer_usd)
    print(placed["message"])
    for offer in tool("list_my_offers", mandate_token=mandate_token)["offers"]:
        print(f"- {offer['domain']}: ${offer['amount']:,.0f}, {offer['status']}{' (your turn)' if offer['yourTurn'] else ''}")


if __name__ == "__main__":
    # python example-buyer-agent.py flowly.com you@example.com 2000 1500 [mandate_token]
    main(sys.argv[1], sys.argv[2], int(sys.argv[3]), int(sys.argv[4]), sys.argv[5] if len(sys.argv) > 5 else None)
```

## Run it

```bash
# Step 1: check, and ask for a mandate
python3 example-buyer-agent.py flowly.com you@example.com 2000 1500

# Step 2: after you press Approve in the email, make the offer
python3 example-buyer-agent.py flowly.com you@example.com 2000 1500 <the mandate token>
```

Use your own email address and amounts you chose. The mandate sets the ceiling: here it allows up to $2,000 and a $1,500 offer.

## Notes

* Replace `flowly.com` with a domain whose owner takes offers. `check_domain` tells you; many will not.
* Calls are limited to about 20 a minute per address.
* The mandate token is a secret. Anyone holding it can act inside the limits until it expires or you stop it.