diff --git a/app.py b/app.py index 8bd3034..f4d7ad6 100644 --- a/app.py +++ b/app.py @@ -4,9 +4,9 @@ import logging from datetime import datetime, timezone from pathlib import Path from typing import List -from fastapi import FastAPI, HTTPException, Header, Security +from fastapi import FastAPI, HTTPException, Header, Security, Request from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials -from fastapi.responses import JSONResponse +from fastapi.responses import JSONResponse, HTMLResponse from typing import Optional security = HTTPBearer() @@ -239,9 +239,14 @@ def find_onetime_schedule_for_user(api_key: str, schedule_id: str) -> tuple[dict @web_app.get("/") -async def root(): +async def root(request: Request): """Landing page with usage instructions.""" - return { + + # Check if browser is requesting HTML + accept_header = request.headers.get("accept", "") + wants_html = "text/html" in accept_header + + info = { "service": "Letta Switchboard", "description": "Free hosted message routing service for Letta agents", "version": "1.0.0", @@ -280,6 +285,149 @@ async def root(): "authentication": "All endpoints require 'Authorization: Bearer YOUR_LETTA_API_KEY' header", "support": "https://github.com/cpfiffer/letta-switchboard/issues" } + + if wants_html: + html_content = """ + + + + Letta Switchboard + + + + + +

🔀 Letta Switchboard

+

Free hosted message routing service for Letta agents

+ +

Features

+ + +

Quick Start with cURL

+ +
+

Send a one-time message:

+
curl -X POST https://letta--switchboard-api.modal.run/schedules/one-time \\
+  -H 'Authorization: Bearer YOUR_LETTA_API_KEY' \\
+  -H 'Content-Type: application/json' \\
+  -d '{
+    "agent_id": "agent-xxx",
+    "execute_at": "2025-11-13T09:00:00Z",
+    "message": "Hello from Switchboard!"
+  }'
+
+ +
+

Create recurring schedule (weekdays at 9am):

+
curl -X POST https://letta--switchboard-api.modal.run/schedules/recurring \\
+  -H 'Authorization: Bearer YOUR_LETTA_API_KEY' \\
+  -H 'Content-Type: application/json' \\
+  -d '{
+    "agent_id": "agent-xxx",
+    "cron": "0 9 * * 1-5",
+    "message": "Daily standup reminder"
+  }'
+
+ +

CLI (Natural Language Support)

+

The CLI supports natural language for easier scheduling:

+ +
+

Installation:

+
git clone https://github.com/cpfiffer/letta-switchboard.git
+cd letta-switchboard/cli
+go build -o letta-switchboard
+./letta-switchboard config set-api-key YOUR_LETTA_API_KEY
+
+ +
+

Usage:

+
# Send immediately
+./letta-switchboard send --agent-id agent-xxx --message "Hello!"
+
+# Schedule with natural language
+./letta-switchboard send --agent-id agent-xxx --message "Reminder" --execute-at "tomorrow at 9am"
+
+# Recurring schedule
+./letta-switchboard recurring create --agent-id agent-xxx --message "Daily standup" --cron "every weekday"
+
+ +

Available Endpoints

+
POST /schedules/one-time - Create a one-time schedule
+
POST /schedules/recurring - Create a recurring schedule
+
GET /schedules/one-time - List your one-time schedules
+
GET /schedules/recurring - List your recurring schedules
+
GET /schedules/one-time/{id} - Get specific one-time schedule
+
GET /schedules/recurring/{id} - Get specific recurring schedule
+
DELETE /schedules/one-time/{id} - Delete one-time schedule
+
DELETE /schedules/recurring/{id} - Delete recurring schedule
+
GET /results - List execution results
+
GET /results/{schedule_id} - Get result for specific schedule
+ +
+ Authentication: All endpoints require Authorization: Bearer YOUR_LETTA_API_KEY header +
+ +

Documentation & Support

+

📖 Full documentation: github.com/cpfiffer/letta-switchboard

+

🐛 Issues & support: GitHub Issues

+

💬 API response: View as JSON

+ + + """ + return HTMLResponse(content=html_content) + + return info @web_app.post("/schedules/recurring")