{"id":26092865,"url":"https://github.com/agnt-gg/slop","last_synced_at":"2026-04-23T21:04:21.897Z","repository":{"id":281281227,"uuid":"944783467","full_name":"agnt-gg/slop","owner":"agnt-gg","description":"The place for SLOP","archived":false,"fork":false,"pushed_at":"2025-03-22T03:31:47.000Z","size":561,"stargazers_count":449,"open_issues_count":2,"forks_count":36,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-22T04:24:11.371Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/agnt-gg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-08T00:38:40.000Z","updated_at":"2025-03-22T03:31:50.000Z","dependencies_parsed_at":"2025-03-15T04:19:26.206Z","dependency_job_id":null,"html_url":"https://github.com/agnt-gg/slop","commit_stats":null,"previous_names":["agnt-gg/slop"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/agnt-gg/slop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agnt-gg%2Fslop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agnt-gg%2Fslop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agnt-gg%2Fslop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agnt-gg%2Fslop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/agnt-gg","download_url":"https://codeload.github.com/agnt-gg/slop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agnt-gg%2Fslop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32198237,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-23T20:19:26.138Z","status":"ssl_error","status_checked_at":"2026-04-23T20:19:23.520Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-09T11:02:18.172Z","updated_at":"2026-04-23T21:04:21.890Z","avatar_url":"https://github.com/agnt-gg.png","language":"HTML","funding_links":[],"categories":["HTML"],"sub_categories":[],"readme":"# SLOP: Simple Language Open Protocol\n\n\u003e **Because AI shouldn't be complicated**\n\n### 🎯 WHAT SLOP IS:\n- A pattern for AI APIs with 6 basic endpoints\n- Regular HTTP(S) requests with JSON data\n- A standard way to talk to any AI service\n- Based on REST: GET and POST what you need\n\n### 🚫 WHAT SLOP IS NOT:\n- A framework or library you install\n- A new technology or language\n- A specific company's product\n- An additional abstraction in any way\n\n\u003e 💡 **SLOP simply says:** \"AI services should work through plain web requests using patterns we've used for decades.\"\n\nThat's it. Just a pattern. ✨\n\n---\n\n![Star History Chart](https://api.star-history.com/svg?repos=agnt-gg/slop\u0026type=Date)\n\n---\n\n## 1. CORE BELIEFS\n- Everything is an HTTP request\n- Every tool is an API endpoint\n- Every AI is accessible\n- Every developer is welcome\n\n## 2. CORE ENDPOINTS (ALL OPTIONAL)\n\nSLOP is modular - implement only what you need. A server is SLOP-compliant if it implements *any one* of these endpoints following the standard format.\n\n| Endpoint | Method | Purpose | Implementation |\n|----------|--------|---------|----------------|\n| `/chat`  | POST   | Talk to AI | Optional |\n| `/tools` | GET, POST | Use AI tools | Optional |\n| `/memory` | GET, POST, PUT, DELETE | Store and retrieve data | Optional |\n| `/resources` | GET, POST | Access knowledge and files | Optional |\n| `/pay` | POST | Handle payments | Optional |\n| `/info` | GET | Expose server metadata | Optional |\n\n\u003e 💡 **Note:** You don't need to implement all endpoints - just the ones your application requires. \n\u003e Even a single endpoint following SLOP conventions makes your service SLOP-compliant.\n\n\u003e 🔍 **Pro Tip:** Implementing the `/info` endpoint is highly recommended as it allows your SLOP server to self-document its capabilities. \n\u003e This makes it much easier for others to discover and integrate with your service without needing external documentation.\n\n## 3. CONNECTION TYPES\n- Standard HTTP/REST Interface For Most Things\n- WebSocket Support for Persistent Real-Time Connections\n- Server-Sent Events (SSE) for One-Way Real-Time Streaming\n\n## 4. MULTI-AGENT CAPABILITIES\n- Route Queries to Specialized Agents Based on Content\n- Create Agent Networks with Different Skills and Roles\n- Support for Multiple Execution Patterns (Sequential, Parallel, Branching)\n- Persistent Memory Allows Seamless Agent Collaboration\n- Works for Simple to Complex Use Cases:\n\n  - [Advanced Streaming AI Chat Platform](https://github.com/agnt-gg/slop/tree/main/examples/javascript/advanced-examples/pdf-bot-with-stream)\n  - Customer Service Bots with Specialist Routing\n  - Research Assistants with Domain-Specific Agents\n  - Creative Workflows with Multiple AI Collaborators\n  - Game Development with Dynamic NPCs\n  - Smart Home Management with Coordinated AI Agents\n  - Personal Finance Management with Adaptive Advisors\n  - Educational Platforms with Adaptive Learning Agents\n  - Multi-Agent Disaster Response Coordination\n  - Marketing Automation with Targeted Campaign Agents\n  - Health Monitoring Systems with Specialized Health Agents\n  - Travel Planning Assistants with Itinerary Optimization\n  - E-commerce Platforms with Personalized Shopping Assistants\n  - Content Moderation Systems with Specialized Review Agents\n\n---\n\n## 🤝 THE SLOP PROMISE:\n\n### 1. OPEN\n- Free to use\n- Open source\n- No vendor lock\n- Community driven\n- Use any LLM model\n\n### 2. SIMPLE\n- REST based\n- JSON only\n- Standard HTTP\n- Zero dependencies\n\n### 3. FLEXIBLE\n- Any AI model\n- Any tool\n- Any platform\n\n\n---\n\n## ⚡ Quick Start\n\nGet started with the SLOP repo of tools in minutes:\n\n```bash\n# Clone the repository\ngit clone https://github.com/agnt-gg/slop\ncd slop\n\n# Check out the examples\ncd examples/javascript\n\n# Install dependencies\nnpm install\n\n# Start the server\nnpm start\n\n# Your SLOP server is now running at http://localhost:3000\n# Try a simple SLOP request:\ncurl -X POST http://localhost:3000/chat \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"messages\":[{\"role\":\"user\",\"content\":\"Hello SLOP!\"}]}'\n```\n\nOr test any SLOP API with our endpoint inspector:\n```bash\n# Go to the endpoint inspector utility\ncd slop/utilities/slop-inspector/server\n\n# Install and run\nnpm install\nnpm start\n\n# Open http://localhost:4000 in your browser\n# Enter any SLOP API URL to inspect it\n```\n\n---\n\n## 📖 ENDPOINT OPERATIONS (v0.0.1)\n\n### 💬 CHAT\n- `POST /chat` - Send messages to AI\n- `POST /chat` - Create or continue a thread (with thread_id)\n- `GET /chat/:id` - Get a specific chat\n- `GET /chat/thread_:id` - Get all messages in a thread\n- `GET /chat` - List recent chats\n- `GET /chat?type=threads` - List all threads\n\n### 🛠️ TOOLS\n- `GET /tools` - List available tools\n- `POST /tools/:tool_id` - Use a specific tool\n- `GET /tools/:tool_id` - Get tool details\n\n### 🧠 MEMORY\n- `POST /memory` - Store a key-value pair\n- `GET /memory/:key` - Get value by key\n- `GET /memory` - List all keys\n- `PUT /memory/:key` - Update existing value\n- `DELETE /memory/:key` - Delete a key-value pair\n- `POST /memory/query` - Search with semantic query\n\n### 📚 RESOURCES\n- `GET /resources` - List available resources\n- `GET /resources/:id` - Get a specific resource\n- `GET /resources/search?q=query` - Search resources\n- `POST /resources` - Create a new resource\n- `PUT /resources/:id` - Update an existing resource\n- `DELETE /resources/:id` - Delete a resource\n- `GET /resources/prefix/:prefix` - List resources with a specific prefix\n\n### 💳 PAY\n- `POST /pay` - Create a payment\n- `GET /pay/:id` - Get payment status\n\n### ℹ️ INFO\n- `GET /info` - Get server metadata, capabilities, and documentation\n\n---\n\n## 🚀 API EXAMPLES - ALL ENDPOINTS\n\n### 💬 CHAT ENDPOINTS\n\n#### POST /chat\n```json\n// REQUEST\nPOST /chat\n{\n  \"messages\": [\n    {\"role\": \"user\", \"content\": \"Hello, what's the weather like?\"}\n  ],\n  \"model\": \"any-model-id\"\n}\n\n// RESPONSE\n{\n  \"id\": \"chat_123\",\n  \"message\": {\n    \"role\": \"assistant\", \n    \"content\": \"I don't have real-time weather data. You could check a weather service for current conditions.\"\n  }\n}\n```\n\n#### GET /chat/:id\n```json\n// REQUEST\nGET /chat/chat_123\n\n// RESPONSE\n{\n  \"id\": \"chat_123\",\n  \"messages\": [\n    {\"role\": \"user\", \"content\": \"Hello, what's the weather like?\"},\n    {\"role\": \"assistant\", \"content\": \"I don't have real-time weather data. You could check a weather service for current conditions.\"}\n  ],\n  \"model\": \"any-model-id\",\n  \"created_at\": \"2023-05-15T10:30:00Z\"\n}\n```\n\n#### Creating a Thread\n```json\n// REQUEST\nPOST /chat\n{\n  \"thread_id\": \"thread_12345\",  // Thread identifier\n  \"messages\": [\n    {\"role\": \"user\", \"content\": \"Let's discuss project planning\"}\n  ],\n  \"model\": \"any-model-id\"\n}\n\n// RESPONSE\n{\n  \"thread_id\": \"thread_12345\",\n  \"message\": {\n    \"role\": \"assistant\", \n    \"content\": \"Sure, I'd be happy to discuss project planning. What aspects would you like to focus on?\"\n  }\n}\n```\n\n#### Adding to a Thread\n```json\n// REQUEST\nPOST /chat\n{\n  \"thread_id\": \"thread_12345\",\n  \"messages\": [\n    {\"role\": \"user\", \"content\": \"What's our next milestone?\"}\n  ],\n  \"model\": \"any-model-id\"\n}\n\n// RESPONSE\n{\n  \"thread_id\": \"thread_12345\",\n  \"message\": {\n    \"role\": \"assistant\", \n    \"content\": \"To determine the next milestone, we should review your project timeline and priorities. What's the current state of your project?\"\n  }\n}\n```\n\n#### Listing All Threads\n```json\n// REQUEST\nGET /chat?type=threads\n\n// RESPONSE\n{\n  \"threads\": [\n    {\n      \"id\": \"thread_12345\",\n      \"title\": \"Project Planning\",\n      \"last_message\": \"What's our next milestone?\",\n      \"created_at\": \"2023-05-15T10:30:00Z\",\n      \"updated_at\": \"2023-05-15T11:45:00Z\"\n    },\n    {\n      \"id\": \"thread_67890\",\n      \"title\": \"Bug Fixes\",\n      \"last_message\": \"Let's prioritize the login issue\",\n      \"created_at\": \"2023-05-14T14:20:00Z\",\n      \"updated_at\": \"2023-05-14T16:30:00Z\"\n    }\n  ]\n}\n```\n\n#### Getting Thread Messages\n```json\n// REQUEST\nGET /chat/thread_12345\n\n// RESPONSE\n{\n  \"thread_id\": \"thread_12345\",\n  \"title\": \"Project Planning\",\n  \"messages\": [\n    {\n      \"id\": \"msg_001\",\n      \"role\": \"user\", \n      \"content\": \"Let's discuss project planning\",\n      \"created_at\": \"2023-05-15T10:30:00Z\"\n    },\n    {\n      \"id\": \"msg_002\",\n      \"role\": \"assistant\", \n      \"content\": \"Sure, what aspects of the project would you like to plan?\",\n      \"created_at\": \"2023-05-15T10:30:05Z\"\n    },\n    {\n      \"id\": \"msg_003\",\n      \"role\": \"user\", \n      \"content\": \"What's our next milestone?\",\n      \"created_at\": \"2023-05-15T11:45:00Z\"\n    }\n  ],\n  \"model\": \"any-model-id\",\n  \"created_at\": \"2023-05-15T10:30:00Z\",\n  \"updated_at\": \"2023-05-15T11:45:00Z\"\n}\n```\n\n#### Storing Thread Metadata\n```json\n// REQUEST\nPOST /memory\n{\n  \"key\": \"thread:thread_12345\",\n  \"value\": {\n    \"title\": \"Project Planning\",\n    \"participants\": [\"user_1\", \"user_2\"],\n    \"tags\": [\"project\", \"planning\", \"roadmap\"],\n    \"status\": \"active\"\n  }\n}\n\n// RESPONSE\n{\n  \"status\": \"stored\"\n}\n```\n\n#### Searching for Threads\n```json\n// REQUEST\nPOST /memory/query\n{\n  \"query\": \"project planning threads with user_1\",\n  \"filter\": {\n    \"key_prefix\": \"thread:\"\n  }\n}\n\n// RESPONSE\n{\n  \"results\": [\n    {\n      \"key\": \"thread:thread_12345\",\n      \"value\": {\n        \"title\": \"Project Planning\",\n        \"participants\": [\"user_1\", \"user_2\"],\n        \"tags\": [\"project\", \"planning\", \"roadmap\"],\n        \"status\": \"active\"\n      },\n      \"score\": 0.95\n    }\n  ]\n}\n```\n\n#### Updating Thread Metadata\n```json\n// REQUEST\nPUT /memory/thread:thread_12345\n{\n  \"value\": {\n    \"title\": \"Project Planning\",\n    \"participants\": [\"user_1\", \"user_2\", \"user_3\"],  // Added new participant\n    \"tags\": [\"project\", \"planning\", \"roadmap\", \"active\"],\n    \"status\": \"in_progress\"  // Updated status\n  }\n}\n\n// RESPONSE\n{\n  \"status\": \"updated\",\n  \"previous_value\": {\n    \"title\": \"Project Planning\",\n    \"participants\": [\"user_1\", \"user_2\"],\n    \"tags\": [\"project\", \"planning\", \"roadmap\"],\n    \"status\": \"active\"\n  }\n}\n```\n\n#### GET /chat\n```json\n// REQUEST\nGET /chat\n\n// RESPONSE\n{\n  \"chats\": [\n    {\n      \"id\": \"chat_123\",\n      \"snippet\": \"Hello, what's the weather like?\",\n      \"created_at\": \"2023-05-15T10:30:00Z\"\n    },\n    {\n      \"id\": \"chat_456\",\n      \"snippet\": \"Tell me about Mars\",\n      \"created_at\": \"2023-05-14T14:20:00Z\"\n    }\n  ]\n}\n```\n\n### 🛠️ TOOLS ENDPOINTS\n\n#### GET /tools\n```json\n// REQUEST\nGET /tools\n\n// RESPONSE\n{\n  \"tools\": [\n    {\n      \"id\": \"calculator\",\n      \"description\": \"Performs mathematical calculations\",\n      \"parameters\": {\n        \"expression\": \"string\"\n      }\n    },\n    {\n      \"id\": \"weather\",\n      \"description\": \"Gets current weather\",\n      \"parameters\": {\n        \"location\": \"string\"\n      }\n    }\n  ]\n}\n```\n\n#### POST /tools/:tool_id\n```json\n// REQUEST\nPOST /tools/calculator\n{\n  \"expression\": \"15 * 7\"\n}\n\n// RESPONSE\n{\n  \"result\": 105\n}\n```\n\n#### GET /tools/:tool_id\n```json\n// REQUEST\nGET /tools/calculator\n\n// RESPONSE\n{\n  \"id\": \"calculator\",\n  \"description\": \"Performs mathematical calculations\",\n  \"parameters\": {\n    \"expression\": {\n      \"type\": \"string\",\n      \"description\": \"Mathematical expression to evaluate\"\n    }\n  },\n  \"example\": \"15 * 7\"\n}\n```\n\n### 🧠 MEMORY ENDPOINTS\n\n#### POST /memory\n```json\n// REQUEST\nPOST /memory\n{\n  \"key\": \"user_preference\",\n  \"value\": {\n    \"theme\": \"dark\",\n    \"language\": \"en\"\n  }\n}\n\n// RESPONSE\n{\n  \"status\": \"stored\"\n}\n```\n\n#### GET /memory/:key\n```json\n// REQUEST\nGET /memory/user_preference\n\n// RESPONSE\n{\n  \"key\": \"user_preference\",\n  \"value\": {\n    \"theme\": \"dark\",\n    \"language\": \"en\"\n  },\n  \"created_at\": \"2023-05-15T10:30:00Z\"\n}\n```\n\n#### GET /memory\n```json\n// REQUEST\nGET /memory\n\n// RESPONSE\n{\n  \"keys\": [\n    {\n      \"key\": \"user_preference\",\n      \"created_at\": \"2023-05-15T10:30:00Z\"\n    },\n    {\n      \"key\": \"search_history\",\n      \"created_at\": \"2023-05-14T14:20:00Z\"\n    }\n  ]\n}\n```\n\n#### PUT /memory/:key\n```json\n// REQUEST\nPUT /memory/user_preference\n{\n  \"value\": {\n    \"theme\": \"light\",\n    \"language\": \"en\"\n  }\n}\n\n// RESPONSE\n{\n  \"status\": \"updated\",\n  \"previous_value\": {\n    \"theme\": \"dark\",\n    \"language\": \"en\"\n  }\n}\n```\n\n#### DELETE /memory/:key\n```json\n// REQUEST\nDELETE /memory/user_preference\n\n// RESPONSE\n{\n  \"status\": \"deleted\"\n}\n```\n\n#### POST /memory/query\n```json\n// REQUEST\nPOST /memory/query\n{\n  \"query\": \"What theme settings do I have?\",\n  \"limit\": 1\n}\n\n// RESPONSE\n{\n  \"results\": [\n    {\n      \"key\": \"user_preference\",\n      \"value\": {\n        \"theme\": \"dark\",\n        \"language\": \"en\"\n      },\n      \"score\": 0.92\n    }\n  ]\n}\n```\n\n### 📚 RESOURCES ENDPOINTS\n\n#### GET /resources\n```json\n// REQUEST\nGET /resources\n\n// RESPONSE\n{\n  \"resources\": [\n    {\n      \"id\": \"mars-101\",\n      \"title\": \"Mars: The Red Planet\",\n      \"type\": \"article\"\n    },\n    {\n      \"id\": \"document-123\",\n      \"name\": \"project_plan.pdf\",\n      \"type\": \"file\"\n    }\n  ]\n}\n```\n\n#### GET /resources/:id\n```json\n// REQUEST\nGET /resources/mars-101\n\n// RESPONSE\n{\n  \"id\": \"mars-101\",\n  \"title\": \"Mars: The Red Planet\",\n  \"type\": \"article\",\n  \"content\": \"Mars is the fourth planet from the Sun and the second-smallest planet in the Solar System...\",\n  \"metadata\": {\n    \"source\": \"astronomy-db\",\n    \"last_updated\": \"2023-05-10\"\n  }\n}\n```\n\n#### POST /resources\n```json\n// REQUEST\nPOST /resources\n{\n  \"id\": \"notes/hello\",\n  \"title\": \"Hello Notes\",\n  \"type\": \"note\",\n  \"content\": \"This is a new resource\",\n  \"metadata\": {\n    \"created_by\": \"user_123\",\n    \"tags\": [\"notes\", \"hello\"]\n  }\n}\n\n// RESPONSE\n{\n  \"status\": \"created\",\n  \"resource\": {\n    \"id\": \"notes/hello\",\n    \"title\": \"Hello Notes\",\n    \"type\": \"note\",\n    \"content\": \"This is a new resource\",\n    \"metadata\": {\n      \"created_by\": \"user_123\",\n      \"tags\": [\"notes\", \"hello\"],\n      \"created_at\": \"2023-06-15T10:30:00Z\"\n    }\n  }\n}\n```\n\n#### PUT /resources/:id\n```json\n// REQUEST\nPUT /resources/notes/hello\n{\n  \"title\": \"Updated Hello Notes\",\n  \"content\": \"This content has been updated\",\n  \"metadata\": {\n    \"tags\": [\"notes\", \"hello\", \"updated\"]\n  }\n}\n\n// RESPONSE\n{\n  \"status\": \"updated\",\n  \"resource\": {\n    \"id\": \"notes/hello\",\n    \"title\": \"Updated Hello Notes\",\n    \"type\": \"note\",\n    \"content\": \"This content has been updated\",\n    \"metadata\": {\n      \"created_by\": \"user_123\",\n      \"tags\": [\"notes\", \"hello\", \"updated\"],\n      \"created_at\": \"2023-06-15T10:30:00Z\",\n      \"updated_at\": \"2023-06-15T11:45:00Z\"\n    }\n  }\n}\n```\n\n#### DELETE /resources/:id\n```json\n// REQUEST\nDELETE /resources/notes/hello\n\n// RESPONSE\n{\n  \"status\": \"deleted\",\n  \"id\": \"notes/hello\"\n}\n```\n\n#### GET /resources/prefix/:prefix\n```json\n// REQUEST\nGET /resources/prefix/notes\n\n// RESPONSE\n{\n  \"resources\": [\n    {\n      \"id\": \"notes/hello\",\n      \"title\": \"Hello Notes\",\n      \"type\": \"note\"\n    },\n    {\n      \"id\": \"notes/todo\",\n      \"title\": \"To-Do List\",\n      \"type\": \"note\"\n    }\n  ]\n}\n```\n\n\u003e **Note on Hierarchical Resource IDs**: SLOP supports hierarchical resource IDs using path segments (e.g., `notes/hello`). When using hierarchical IDs:\n\u003e \n\u003e 1. The full path is treated as a single ID when using `GET`, `PUT`, or `DELETE` operations on `/resources/:id`\n\u003e 2. Use the `/resources/prefix/:prefix` endpoint to retrieve all resources under a specific prefix\n\u003e 3. Hierarchical IDs enable organizing resources in a folder-like structure\n\u003e 4. The hierarchy is purely logical - implementations may store resources however they prefer\n\n#### GET /resources/search\n```json\n// REQUEST\nGET /resources/search?q=mars\n\n// RESPONSE\n{\n  \"results\": [\n    {\n      \"id\": \"mars-101\",\n      \"title\": \"Mars: The Red Planet\",\n      \"type\": \"article\",\n      \"score\": 0.98\n    },\n    {\n      \"id\": \"solar-system\",\n      \"title\": \"Our Solar System\",\n      \"type\": \"article\",\n      \"score\": 0.75\n    }\n  ]\n}\n```\n\n### 💳 PAY ENDPOINTS\n\n#### POST /pay\n```json\n// REQUEST\nPOST /pay\n{\n  \"amount\": 5.00,\n  \"currency\": \"USD\",\n  \"description\": \"API usage - 1000 tokens\",\n  \"payment_method\": \"card_token_123\"\n}\n\n// RESPONSE\n{\n  \"transaction_id\": \"tx_987654\",\n  \"status\": \"success\",\n  \"receipt_url\": \"https://api.example.com/receipts/tx_987654\"\n}\n```\n\n#### GET /pay/:id\n```json\n// REQUEST\nGET /pay/tx_987654\n\n// RESPONSE\n{\n  \"transaction_id\": \"tx_987654\",\n  \"amount\": 5.00,\n  \"currency\": \"USD\",\n  \"description\": \"API usage - 1000 tokens\",\n  \"status\": \"success\",\n  \"created_at\": \"2023-05-15T10:30:00Z\",\n  \"receipt_url\": \"https://api.example.com/receipts/tx_987654\"\n}\n```\n\n\n### ℹ️ INFO ENDPOINT\n\n#### GET /info\n```json\n// REQUEST\nGET /info\n\n// RESPONSE\n{\n  \"name\": \"Example SLOP Server\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A SLOP-compliant AI assistant API\",\n  \"endpoints\": [\n    {\n      \"path\": \"/chat\",\n      \"methods\": [\"GET\", \"POST\"],\n      \"description\": \"Chat with the AI assistant\"\n    },\n    {\n      \"path\": \"/tools\",\n      \"methods\": [\"GET\"],\n      \"description\": \"List available tools\"\n    }\n  ],\n  \"creator\": {\n    \"name\": \"SLOP Community\",\n    \"website\": \"https://slop.ai\",\n    \"email\": \"hello@slop.ai\"\n  },\n  \"links\": {\n    \"documentation\": \"https://slop.ai/docs\",\n    \"github\": \"https://github.com/agnt-gg/slop\"\n  },\n  \"capabilities\": {\n    \"streaming\": true,\n    \"websockets\": true,\n    \"models\": [\"default-model\"]\n  }\n}\n```\n\n### 🔐 AUTH EXAMPLES\n\nAuthentication in SLOP uses standard HTTP headers. Here are examples in both JavaScript and Python:\n\n#### JavaScript Example\n```javascript\n// Using fetch\nconst callSlop = async (endpoint, data) =\u003e {\n  const response = await fetch(`https://api.example.com${endpoint}`, {\n    method: 'POST',\n    headers: {\n      'Authorization': 'Bearer your-token-here',\n      'Content-Type': 'application/json'\n    },\n    body: JSON.stringify(data)\n  });\n  return response.json();\n};\n\n// Using axios\nconst axios = require('axios');\nconst api = axios.create({\n  baseURL: 'https://api.example.com',\n  headers: {\n    'Authorization': 'Bearer your-token-here'\n  }\n});\n\n// Make authenticated requests\nawait api.post('/chat', {\n  messages: [{ content: 'Hello!' }]\n});\n```\n\n#### Python Example\n```python\nimport requests\n\n# Using requests\nheaders = {\n    'Authorization': 'Bearer your-token-here',\n    'Content-Type': 'application/json'\n}\n\n# Function to make authenticated requests\ndef call_slop(endpoint, data=None):\n    base_url = 'https://api.example.com'\n    method = 'GET' if data is None else 'POST'\n    response = requests.request(\n        method=method,\n        url=f'{base_url}{endpoint}',\n        headers=headers,\n        json=data\n    )\n    return response.json()\n\n# Make authenticated requests\nchat_response = call_slop('/chat', {\n    'messages': [{'content': 'Hello!'}]\n})\n```\n\nRemember: SLOP uses standard HTTP auth - no special endpoints needed! 🔑\n\n### 🛡️ SCOPE HEADERS FOR LIMITING AI SCOPE\n\nSLOP uses standard HTTP headers to control AI safety and permissions:\n\n```http\nX-SLOP-Scope: chat.read,tools.calculator,memory.user.read\n```\n\n#### Common Scopes\n\nchat.read # Read chat history\nchat.write # Send messages\ntools.* # Access all tools\ntools.safe.* # Access only safe tools\nmemory.user.* # Full user memory access\nmemory..read # Read-only memory access\n\n\n#### Examples\n\n```http\n# Safe: Calculator within scope\nPOST /tools/calculator\nX-SLOP-Scope: tools.calculator.execute\n{\n    \"expression\": \"2 + 2\"\n}\n\n# Blocked: No execute permission\nPOST /tools/system-cmd\nX-SLOP-Scope: tools.calculator.execute\n{\n    \"cmd\": \"rm -rf /\"\n}\n\n// RESPONSE\n{\n    \"error\": \"Scope violation: tools.execute-code requires explicit permission\",\n    \"permitted\": false\n}\n```\n\nRemember: Security through simplicity! 🔒\n\n---\n\n\n## 🔄 SSE STREAMING IN SLOP\n\nSLOP supports streaming responses through Server-Sent Events (SSE) - perfect for token-by-token AI outputs:\n\n### Adding SSE to Your SLOP Implementation\n\n#### JavaScript Example\n```javascript\n// Add this streaming endpoint to your SLOP implementation\napp.post('/chat/stream', async (req, res) =\u003e {\n  const { messages } = req.body;\n  const userQuery = messages[0].content;\n  \n  // Set SSE headers\n  res.setHeader('Content-Type', 'text/event-stream');\n  res.setHeader('Cache-Control', 'no-cache');\n  res.setHeader('Connection', 'keep-alive');\n  \n  // Create streaming response\n  const stream = await openai.chat.completions.create({\n    model: \"gpt-4\",\n    messages: [\n      { role: \"system\", content: \"You are a helpful assistant.\" },\n      { role: \"user\", content: userQuery }\n    ],\n    stream: true\n  });\n  \n  // Send tokens as they arrive\n  for await (const chunk of stream) {\n    const content = chunk.choices[0]?.delta?.content || '';\n    if (content) {\n      res.write(`data: ${JSON.stringify({ content })}\\n\\n`);\n    }\n  }\n  res.write('data: [DONE]\\n\\n');\n  res.end();\n});\n```\n\n#### Python Example\n```python\n@app.route('/chat/stream', methods=['POST'])\ndef chat_stream():\n    data = request.json\n    user_query = data['messages'][0]['content']\n    \n    def generate():\n        stream = openai.chat.completions.create(\n            model=\"gpt-4\",\n            messages=[\n                {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n                {\"role\": \"user\", \"content\": user_query}\n            ],\n            stream=True\n        )\n        for chunk in stream:\n            content = chunk.choices[0].delta.content or ''\n            if content:\n                yield f\"data: {json.dumps({'content': content})}\\n\\n\"\n        yield \"data: [DONE]\\n\\n\"\n    \n    return Response(generate(), content_type='text/event-stream')\n```\n\n#### Client Consumption\n```javascript\n// Browser JavaScript to consume the stream\nconst eventSource = new EventSource('/chat/stream');\neventSource.onmessage = (event) =\u003e {\n  if (event.data === '[DONE]') {\n    eventSource.close();\n    return;\n  }\n  const data = JSON.parse(event.data);\n  // Append incoming token to UI\n  document.getElementById('response').innerHTML += data.content;\n};\n```\n\n### Why SSE is SLOP-Friendly:\n- Uses standard HTTP - no new protocols\n- Works with existing authentication\n- Simple implementation - minimal code\n- Compatible with all HTTP clients\n- Lower overhead than WebSockets\n\nRemember: Add `/stream` suffix to endpoints that support streaming! 🚿\n\n## 🔌 WEBSOCKET STREAMING IN SLOP\n\nSLOP also supports WebSocket for bidirectional streaming - ideal for real-time AI interactions:\n\n### Adding WebSocket to Your SLOP Implementation\n\n#### JavaScript Example (Node.js with ws)\n```javascript\n// Server-side WebSocket implementation\nconst WebSocket = require('ws');\nconst wss = new WebSocket.Server({ port: 8080 });\n\nwss.on('connection', (ws) =\u003e {\n  ws.on('message', async (message) =\u003e {\n    try {\n      const data = JSON.parse(message);\n      const { messages } = data;\n      const userQuery = messages[0].content;\n      \n      // Create streaming response\n      const stream = await openai.chat.completions.create({\n        model: \"gpt-4\",\n        messages: [\n          { role: \"system\", content: \"You are a helpful assistant.\" },\n          { role: \"user\", content: userQuery }\n        ],\n        stream: true\n      });\n      \n      // Send tokens as they arrive\n      for await (const chunk of stream) {\n        const content = chunk.choices[0]?.delta?.content || '';\n        if (content \u0026\u0026 ws.readyState === WebSocket.OPEN) {\n          ws.send(JSON.stringify({ content }));\n        }\n      }\n      \n      if (ws.readyState === WebSocket.OPEN) {\n        ws.send(JSON.stringify({ status: \"complete\" }));\n      }\n    } catch (error) {\n      if (ws.readyState === WebSocket.OPEN) {\n        ws.send(JSON.stringify({ error: error.message }));\n      }\n    }\n  });\n});\n```\n\n#### Python Example (with FastAPI and websockets)\n```python\nfrom fastapi import FastAPI, WebSocket\nimport json\nimport openai\n\napp = FastAPI()\n\n@app.websocket(\"/chat/ws\")\nasync def websocket_endpoint(websocket: WebSocket):\n    await websocket.accept()\n    \n    try:\n        while True:\n            data = await websocket.receive_text()\n            data_json = json.loads(data)\n            user_query = data_json['messages'][0]['content']\n            \n            stream = openai.chat.completions.create(\n                model=\"gpt-4\",\n                messages=[\n                    {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n                    {\"role\": \"user\", \"content\": user_query}\n                ],\n                stream=True\n            )\n            \n            for chunk in stream:\n                content = chunk.choices[0].delta.content or ''\n                if content:\n                    await websocket.send_text(json.dumps({\"content\": content}))\n            \n            await websocket.send_text(json.dumps({\"status\": \"complete\"}))\n    \n    except Exception as e:\n        await websocket.send_text(json.dumps({\"error\": str(e)}))\n```\n\n#### Client Consumption\n```javascript\n// Browser JavaScript to connect to WebSocket\nconst socket = new WebSocket('ws://localhost:8080');\nlet responseText = '';\n\n// Send a message when connection is open\nsocket.onopen = function(event) {\n  socket.send(JSON.stringify({\n    messages: [{ role: 'user', content: 'Tell me about SLOP protocol' }]\n  }));\n};\n\n// Listen for messages\nsocket.onmessage = function(event) {\n  const data = JSON.parse(event.data);\n  \n  if (data.content) {\n    responseText += data.content;\n    document.getElementById('response').innerText = responseText;\n  }\n  \n  if (data.status === 'complete') {\n    console.log('Response complete');\n  }\n  \n  if (data.error) {\n    console.error('Error:', data.error);\n  }\n};\n\n// Handle errors\nsocket.onerror = function(error) {\n  console.error('WebSocket Error:', error);\n};\n\n// Clean up on close\nsocket.onclose = function(event) {\n  console.log('Connection closed');\n};\n```\n\n### Why WebSockets for SLOP:\n- Bidirectional communication for complex interactions\n- Persistent connection for multiple exchanges\n- Real-time feedback and typing indicators\n- Supports advanced features like user interruptions\n- Ideal for chat applications and interactive AI assistants\n\nRemember: Use `/ws` suffix to indicate WebSocket endpoints in your SLOP implementation! 🔌\n\n---\n\n## 🔄 RESOURCE MANAGEMENT IMPLEMENTATION EXAMPLE\n\nHere's a simple JavaScript implementation of the resource management endpoints:\n\n```javascript\n// In-memory resource store\nconst resources = {};\n\n// GET /resources - List all resources\napp.get('/resources', (req, res) =\u003e {\n  res.json({ resources: Object.values(resources) });\n});\n\n// GET /resources/:id - Get a specific resource\napp.get('/resources/:id', (req, res) =\u003e {\n  const resourceId = req.params.id;\n  \n  if (!resources[resourceId]) {\n    return res.status(404).json({ error: 'Resource not found' });\n  }\n  \n  res.json(resources[resourceId]);\n});\n\n// POST /resources - Create a new resource\napp.post('/resources', (req, res) =\u003e {\n  const { id, title, content, type, metadata = {} } = req.body;\n  \n  if (!id || !title) {\n    return res.status(400).json({ error: 'Resource ID and title are required' });\n  }\n  \n  if (resources[id]) {\n    return res.status(409).json({ error: 'Resource with this ID already exists' });\n  }\n  \n  const now = new Date().toISOString();\n  \n  const resource = {\n    id,\n    title,\n    type: type || 'document',\n    content: content || '',\n    metadata: {\n      ...metadata,\n      created_at: now\n    }\n  };\n  \n  resources[id] = resource;\n  \n  res.status(201).json({\n    status: 'created',\n    resource\n  });\n});\n\n// PUT /resources/:id - Update an existing resource\napp.put('/resources/:id', (req, res) =\u003e {\n  const resourceId = req.params.id;\n  const { title, content, type, metadata = {} } = req.body;\n  \n  if (!resources[resourceId]) {\n    return res.status(404).json({ error: 'Resource not found' });\n  }\n  \n  const now = new Date().toISOString();\n  const existingResource = resources[resourceId];\n  \n  const updatedResource = {\n    ...existingResource,\n    title: title || existingResource.title,\n    content: content !== undefined ? content : existingResource.content,\n    type: type || existingResource.type,\n    metadata: {\n      ...existingResource.metadata,\n      ...metadata,\n      updated_at: now\n    }\n  };\n  \n  resources[resourceId] = updatedResource;\n  \n  res.json({\n    status: 'updated',\n    resource: updatedResource\n  });\n});\n\n// DELETE /resources/:id - Delete a resource\napp.delete('/resources/:id', (req, res) =\u003e {\n  const resourceId = req.params.id;\n  \n  if (!resources[resourceId]) {\n    return res.status(404).json({ error: 'Resource not found' });\n  }\n  \n  delete resources[resourceId];\n  \n  res.json({\n    status: 'deleted',\n    id: resourceId\n  });\n});\n\n// GET /resources/prefix/:prefix - List resources with a specific prefix\napp.get('/resources/prefix/:prefix', (req, res) =\u003e {\n  const prefix = req.params.prefix;\n  \n  const matchingResources = Object.values(resources)\n    .filter(resource =\u003e \n      resource.id.startsWith(prefix + '/')\n  );\n  \n  res.json({ resources: matchingResources });\n});\n\n// GET /resources/search - Search resources\napp.get('/resources/search', (req, res) =\u003e {\n  const query = req.query.q?.toLowerCase() || '';\n  \n  if (!query) {\n    return res.status(400).json({ error: 'Search query is required' });\n  }\n  \n  const results = Object.values(resources)\n    .filter(resource =\u003e \n      resource.title.toLowerCase().includes(query) || \n      (resource.content \u0026\u0026 resource.content.toLowerCase().includes(query))\n    )\n    .map(resource =\u003e ({\n      id: resource.id,\n      title: resource.title,\n      type: resource.type,\n      score: 0.9 // In a real implementation, you would calculate a relevance score\n    }));\n  \n  res.json({ results });\n});\n```\n\nThis implementation provides:\n- Full CRUD operations for resources\n- Support for hierarchical resource IDs\n- Prefix-based resource listing\n- Simple text search functionality\n\nFor production use, you would replace the in-memory store with a database and add proper authentication and error handling.\n\n---\n\nLet's collab! SLOP Discord: https://discord.com/invite/nwXJMnHmXP\n\n🎉 **Enjoy using SLOP!** 🎉 \n\nSLOP is an open sourced protocol launched under the MIT license by [@NathanWilbanks](https://discord.com/invite/nwXJMnHmXP) of the AGNT.gg open source agent building platform.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagnt-gg%2Fslop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagnt-gg%2Fslop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagnt-gg%2Fslop/lists"}