Skip to content

DavidSchmidt00/padel-agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

264 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Playtomic CLI & AI Agent

Warning

This project is under active development. Features and APIs may change.

An AI-powered assistant and comprehensive toolkit for finding available Padel court slots on Playtomic. The project features a LangGraph-based agent that enables natural language interaction for slot search, along with a powerful Python client library and CLI.

✨ Features

  • πŸ€– AI Agent (LangGraph): Natural language interface to find the perfect slot
  • 🐍 Python Client Library: Class-based APIclient with full type hints
  • πŸ’» Command-Line Interface: Direct CLI for quick searches
  • πŸ” Advanced Filtering:
    • Filter by club (slug or name)
    • Filter by court type (SINGLE or DOUBLE)
    • Filter by time range with timezone support
    • Filter by slot duration (60, 90, 120 minutes)
  • 🧠 User Profile (Memory): Remembers your preferences (preferred club, court type, etc.) across sessions
  • πŸ›‘οΈ Robust Error Handling: Custom exceptions for better debugging

πŸ“¦ Installation

From Source

git clone https://github.com/DavidSchmidt00/playtomic-agent.git
cd playtomic-agent
pip install -e .

With Development Dependencies

pip install -e ".[dev]"

βš™οΈ Configuration

The application reads configuration from environment variables (or a .env file in the project root). Start from the provided template:

cp .env.example .env

Required variables

Variable When required Description
GEMINI_API_KEY LLM_PROVIDER=gemini (default) Google Gemini API key β€” get one at aistudio.google.com
NVIDIA_API_KEY LLM_PROVIDER=nvidia NVIDIA API key (starts with nvapi-)
WHATSAPP_PHONE_NUMBER Running whatsapp-agent Phone number with country code (e.g. +491729975477), used for pairing-code login. Without it the agent cannot pair on first run.

Optional variables (with defaults)

Variable Default Description
LLM_PROVIDER gemini LLM backend: gemini or nvidia
DEFAULT_MODEL gemini-3.0-flash-preview / deepseek-ai/deepseek-v3.1-terminus Override the model for the selected provider. Provider defaults are used when unset.
DEFAULT_TIMEZONE Europe/Berlin Timezone used when the user's timezone is unknown
PLAYTOMIC_API_BASE_URL https://api.playtomic.io/v1 Playtomic REST API base URL
LOG_LEVEL INFO Python logging level (DEBUG, INFO, WARNING, ERROR)
WHATSAPP_SESSION_DB data/whatsapp_session.db Path to the SQLite file where neonize stores the WhatsApp session
WHATSAPP_STORAGE_PATH data/whatsapp_users.json Path to the JSON file storing per-user WhatsApp state and history
WHATSAPP_DEVICE_OS Chrome Device OS name reported to WhatsApp (avoids the default Neonize fingerprint)
WHATSAPP_DEVICE_PLATFORM CHROME DeviceProps.PlatformType reported to WhatsApp. Valid values: CHROME, FIREFOX, SAFARI, EDGE, DESKTOP, IOS_PHONE, ANDROID_PHONE
WHATSAPP_SEND_DELAY_WPM 400.0 Simulated typing speed (words/minute) added before sending a reply. Set to 0 to disable.

πŸš€ Usage

1. AI Agent (Natural Language)

Using LangGraph Studio/API

cd src/playtomic_agent
langgraph dev

Then interact through the LangGraph Studio UI or API.

Programmatic Usage

from playtomic_agent.agent import playtomic_agent

# Stream agent responses
for chunk in playtomic_agent.stream(
    {"messages": [{"role": "user", "content":
        "Find a 90-minute double court slot at lemon-padel-club "
        "tomorrow between 18:00 and 20:00"
    }]},
    stream_mode="updates",
):
    for step, data in chunk.items():
        print(f"{step}: {data['messages'][-1].content}")

2. Python Client Library

The modern, class-based client provides full control:

from playtomic_agent.client.api import PlaytomicClient

# Use as context manager for automatic cleanup
with PlaytomicClient() as client:
    # Find available slots
    slots = client.find_slots(
        club_slug="lemon-padel-club",
        date="2026-02-15",
        court_type="DOUBLE",
        start_time="18:00",
        end_time="20:00",
        timezone="Europe/Berlin",
        duration=90
    )

    for slot in slots:
        print(f"{slot.court_name}: {slot.time} - {slot.price}")
        print(f"Book: {slot.get_link()}")

Advanced Usage with Direct Methods

from playtomic_agent.client.api import PlaytomicClient

with PlaytomicClient() as client:
    # 1. Get club information
    club = client.get_club(slug="lemon-padel-club")
    print(f"Club: {club.name} ({len(club.courts)} courts)")

    # 2. Get all available slots
    available_slots = client.get_available_slots(
        club,
        date="2026-02-15",
        start_time="18:00",  # UTC
        end_time="20:00"
    )

    # 3. Filter manually
    filtered = client.filter_slots(
        club,
        available_slots,
        court_type="DOUBLE",
        duration=90
    )

3. Command-Line Interface

The CLI supports two main modes: search and slots.

Search for Clubs

Find clubs by location (using geocoding) or by name.

# Search by Location
playtomic-cli search --location "Berlin"

# Search by Name
playtomic-cli search --name "Lemon Padel"

Find Available Slots

Find slots for a specific club.

# Find all slots for today
playtomic-cli slots --club-slug lemon-padel-club

# Find 90-minute double court slots tomorrow
playtomic-cli slots \
    --club-slug lemon-padel-club \
    --date 2026-02-15 \
    --court-type DOUBLE \
    --duration 90 \
    --start-time 18:00 \
    --end-time 20:00 \
    --timezone Europe/Berlin

# Output as JSON
playtomic-cli slots --club-slug lemon-padel-club --json

🧠 User Profile (Memory)

The agent can remember your preferences across sessions using Browser Local Storage.

Supported preferences:

  • Preferred Club: Your go-to padel club
  • City: Your default location for club searches
  • Court Type: SINGLE or DOUBLE
  • Duration: Preferred slot duration (e.g., 90 minutes)
  • Preferred Time: Your usual play time (e.g., "evenings")

How it works:

  1. When you search, the agent may suggest saving your preferences.
  2. A confirmation prompt appears in the chat β€” click "Save" or "No thanks".
  3. Saved preferences appear as pills above the chat box and are used automatically in future searches.
  4. You can remove individual preferences or clear all at any time.

🌐 Web UI (Experimental) βœ…

A minimal, extensible web frontend is included to interact with the LangGraph-based Playtomic agent. The frontend is a small React app (Vite) that talks to a FastAPI endpoint exposed by the Python service. It provides a centered chat UI with Markdown rendering, a loading indicator, and a user profile card.

  1. Start the Dev Container in VS Code or Cursor.

  2. The Backend (FastAPI) and Frontend (React) servers will automatically start via VS Code Tasks.

  3. Access the web app at http://localhost:8080 to use the chat interface.

If running outside the container:

  1. Install Python dependencies and start the API server:
pip install -e .
uvicorn playtomic_agent.api:app --host 0.0.0.0 --port 8082
  1. Start the frontend (port 8080):
cd web
npm install
npm run dev -- --port 8080
  1. Open your browser at http://localhost:8080 to use the chat interface.

Notes:

  • The frontend displays tool execution status (e.g. "Searching for clubs...") and the final assistant reply. Internal reasoning details are hidden.
  • Add API-related settings (e.g. GEMINI API keys) to .env when using the agent for real runs.

πŸ—οΈ Architecture

For a deep dive into the project's internals, see the Developer Guide.

Quick Overview

graph TD
    User[User] -->|Chat| Frontend[React Web UI]
    Frontend -->|Unidirectional Stream| Backend[Python API (FastAPI)]
    Backend -->|Orchestrates| Agent[LangGraph Agent]
    Agent -->|Uses| Tools[Tools]
    Tools -->|Calls| PlaytomicAPI[Playtomic API]
    Agent -->|Queries| LLM[Google Gemini]
Loading

The project is split into two main parts:

  1. Backend (src/): Python application using LangChain/LangGraph and FastAPI.
  2. Frontend (web/): React application using Vite.

πŸ§ͺ Development

Running Tests

# Run all tests
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=src/playtomic_agent --cov-report=html

# Run specific test file
pytest tests/test_client.py -v

Code Quality

# Format code
black src/ tests/

# Lint
ruff check src/ tests/

# Type checking
mypy src/

πŸ“š API Reference

PlaytomicClient

Main client class for interacting with the Playtomic API.

Methods:

  • get_club(slug=None, name=None) - Fetch club information
  • get_available_slots(club, date, start_time=None, end_time=None) - Get available slots
  • filter_slots(club, available_slots, court_type=None, duration=None) - Filter slots
  • find_slots(club_slug, date, **filters) - Convenience method combining all steps

Exceptions:

  • ClubNotFoundError - Club not found
  • MultipleClubsFoundError - Multiple clubs match identifier
  • APIError - API request failed
  • ValidationError - Invalid input parameters

Models

All models are Pydantic models with full validation:

  • Club - Represents a Playtomic club
  • Court - Represents a court (single/double)
  • Slot - Represents an available time slot

🀝 Contributing

Contributions are welcome! Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch
  3. Install development dependencies: pip install -e ".[dev]"
  4. Write tests for new features
  5. Ensure all tests pass: pytest tests/
  6. Format code: black src/ tests/
  7. Submit a pull request

πŸ“ License

MIT

πŸ™ Acknowledgments

  • Built with LangGraph for AI agent orchestration
  • Powered by Google Gemini for natural language understanding
  • Uses the Playtomic API for court availability data

πŸ”— Links

About

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Contributors