{"id":28625208,"url":"https://github.com/shuffle/singul","last_synced_at":"2026-03-03T14:07:33.685Z","repository":{"id":293345275,"uuid":"978016993","full_name":"Shuffle/Singul","owner":"Shuffle","description":"Singul: Connect to your favorite services with a Singul line of code.","archived":false,"fork":false,"pushed_at":"2025-08-26T11:27:10.000Z","size":293,"stargazers_count":20,"open_issues_count":2,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-30T16:48:18.587Z","etag":null,"topics":["ai","api","api-client","automation","data","llm","normalization","open","security","source","standardization","standards"],"latest_commit_sha":null,"homepage":"https://singul.io","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Shuffle.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,"zenodo":null}},"created_at":"2025-05-05T10:44:07.000Z","updated_at":"2025-08-26T11:26:35.000Z","dependencies_parsed_at":"2025-07-09T14:38:33.804Z","dependency_job_id":"e1a23697-ef77-4b19-87bc-70297a0c49cb","html_url":"https://github.com/Shuffle/Singul","commit_stats":null,"previous_names":["shuffle/singul"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/Shuffle/Singul","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shuffle%2FSingul","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shuffle%2FSingul/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shuffle%2FSingul/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shuffle%2FSingul/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Shuffle","download_url":"https://codeload.github.com/Shuffle/Singul/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shuffle%2FSingul/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273699712,"owners_count":25152286,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["ai","api","api-client","automation","data","llm","normalization","open","security","source","standardization","standards"],"created_at":"2025-06-12T08:07:59.260Z","updated_at":"2026-02-10T14:02:46.938Z","avatar_url":"https://github.com/Shuffle.png","language":"Go","readme":"\u003ch1 align=\"center\"\u003e\n\n[\u003cimg src=\"https://shuffler.io/images/logos/singul.svg\" alt=\"Singul Logo\" width=\"100\"/\u003e](https://singul.io)\n\nSingul\n\n\u003c/h1\u003e\n\u003ch4 align=\"center\"\u003e\nConnect to anything with a Singul line of code. Now open source (in Beta)!\n\u003c/h4\u003e\n\n## Usage\nBefore starting, **set the OPENAI_API_KEY environment variable**. Other LLM's work as well - check out [LLM Controls](#llm-controls) further down for more information.\n\n```\nexport OPENAI_API_KEY=key\n```\n\n## Examples\n**CLI**\n```bash\nsingul --help\n\n# List tickets in the OCSF format\nsingul list_tickets jira \nsingul list_tickets service_now \n\n# Send mail in the same format\nsingul send_mail outlook --subject=\"hoy\" --data=\"hello world\" --to=\"test@example.com\"\nsingul send_mail gmail --subject=\"hoy\" --data=\"hello world\" --to=\"test@example.com\"\n```\n\n**Code (python)**:\nInstall the library\n```bash\npip install singul\n```\n\nUse it locally\n```python\nimport singul\n\n# List tickets in the OCSF format\ntickets = singul.run(\"jira\", action=\"list_tickets\", max_items=10)\ntickets = singul.run(\"service_now\", action=\"list_tickets\", max_items=10)\n\n# Send mail in the same format\nsend_mail_response = singul.run(\"outlook\", action=\"send_mail\", subject=\"hoy\", data=\"hello world\" to=\"test@example.com\")\nsend_mail_response = singul.run(\"gmail\", action=\"send_mail\", subject=\"hoy\", data=\"hello world\" to=\"test@example.com\")\n```\n\n**API**: singul.io API with curl\nThis requires an API key from [shuffler.io](https://shuffler.io/register), which is used for storing authentication. \n\n```bash\n# List tickets in the OCSF format\ncurl https://singul.io/api/list_tickets -d '{\"app\": \"jira\"}'\ncurl https://singul.io/api/list_tickets -d '{\"app\": \"service_now\"}'\n\n# Send mail in the same format\ncurl https://singul.io/api/send_mail -d '{\"app\": \"gmail\", \"subject\": \"hoy\", data=\"hello world\", to=\"test@example.com\"}'\ncurl https://singul.io/api/send_mail -d '{\"app\": \"outlook\", \"subject\": \"hoy\", data=\"hello world\", to=\"test@example.com\"}'\n```\n\n## Why Singul\nAPIs and AI Agents should be easier to use and build. Singul solves both by being easy to use, deterministic and controllable. This reduces the barrier to entry for multi-tool development and allows you to build your own AI agents with ease. \n\n**Deterministic because:**\n- LLMs can be unpredictable and unreliable\n- Singul stores translations after the first use, and we have a global library for known translations\n- You have full control of all translations\n- It has a source of truth for APIs, and is not \"guessing\"\n\n**Reliable Translations:**\n- For your input AND output, we store the format and know how to translate it after successful requests. This is then reusable in subsequent requests\n- Singul ensures all input fields ARE in the request, or fails out. You can modify the relevant files to update the body you want to send if this occurs after up to 5 request failures.\n\n**Stable Connections \u0026 stored authentication:**\n- Singul is based on how we built [Shuffle](https://shuffler.io) and how we connect to APIs. We use the knowledge of Shuffle, including apps, categories, tags, actions, authentication mechanisms, code and more. \n\n## LLM Controls\nSet these environment variables to control the behavior of Singul. The AI/LLM section is **FOR NOW** only supporting the OpenAI format, but we intend to add more in the future to make it work well standalone. Examples of how to change to a different providers with environment variables is: \n\n* Local Ollama: OPENAI_API_URL=http://localhost:11434/v1, AI_MODEL=llama2\n* Google Gemini: OPENAI_API_URL=https://generativelanguage.googleapis.com/v1beta/openai, OPENAI_API_KEY=\u003ckey\u003e, AI_MODEL=gemini-2.0-flash\n* xAI Grok: OPENAI_API_URL=https://api.x.ai/v1, OPENAI_API_KEY=\u003ckey\u003e, AI_MODEL=grok-3-mini-fast-beta\n* Anthropic: OPENAI_API_URL=https://api.anthropic.com/v1, OPENAI_API_KEY=\u003ckey\u003e, AI_MODEL=claude-3-7-sonnet-20250219\n* Deepseek: OPENAI_API_URL=https://api.deepseek.com, OPENAI_API_KEY=\u003ckey\u003e, AI_MODEL=deepseek-reasoner\n* Mistral: OPENAI_API_URL=https://api.mistral.ai/v1, OPENAI_API_KEY=\u003ckey\u003e, AI_MODEL=codestral-latest\n* Amazon Bedrock: NOT COMATIBLE YET :((\n...\n\n**Other OpenAI compatible API's also work**\n\n## Environment Variables\n**REQUIRED:**\n```\nOPENAI_API_KEY=\u003ckey\u003e \t# The API key for the OpenAI API, if you want to use a different provider. Default: None\n```\n\n**Singul controls**\n```\nDEBUG=true \t\t\t\t# Enables debug mode\nFILE_LOCATION=./files \t# The location of the files. Default: ./files\nSHUFFLE_ENCRYPTION_MODIFIER=randomstringhere # Required for local encryption of authentication.\n\n# Where to download and control standards from \nGIT_DOWNLOAD_USER=shuffle\nGIT_DOWNLOAD_REPO=standards\n\n# To upload results to a Datastore, find details on https://shuffler.io/admin. This is disabled by default\nSHUFFLE_ORG=\"ORG_ID\"\nSHUFFLE_AUTHORIZATION=\"API KEY\"\nSHUFFLE_BACKEND=\"SHUFFLE BACKEND\"\n```\n\n**LLM controls:**\n```\nAI_MODEL=\u003cmodel\u003e \t\t\t# The model to use for the LLM. We recommend reasoning models. Default: o4-mini\nOPENAI_API_URL=\u003curl\u003e \t# The URL of the OpenAI API, if you want to use a different provider. Default: https://api.openai.com/v1/chat/completions\nOPENAI_API_ORG=\u003corg\u003e \t# The organization ID for the OpenAI API, if you want to use a different provider. Default: None\n```\n\n## Local Test Example\n```\ngo run *.go create_ticket jira --project=SHUF --title=\"title2\" --content=\"cool new body here 2\"\ngo run *.go list_tickets jira --max_results=2\n```\n\n\n## How it works\n![image](https://github.com/user-attachments/assets/4f06b240-2010-40f6-965b-95a9e381f97e)\n\n![image](https://github.com/user-attachments/assets/fb1a0c83-d021-4308-9074-b5af822e2302)\n\n![image](https://github.com/user-attachments/assets/fc659b7c-dbbc-4c36-8e53-fc23b59995e3)\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshuffle%2Fsingul","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshuffle%2Fsingul","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshuffle%2Fsingul/lists"}