{"id":51441635,"url":"https://github.com/attenlabs/saa-sdk","last_synced_at":"2026-07-05T12:01:56.533Z","repository":{"id":365981132,"uuid":"1242537003","full_name":"attenlabs/saa-sdk","owner":"attenlabs","description":"Addressee detection for voice agents: device-directed speech detection that runs before STT, so background speech, side conversations, and the agent's own TTS echo never trigger it. No wake word, model-agnostic, drop-in for LiveKit, Pipecat, ElevenLabs, Twilio, and OpenAI. The layer your VAD and turn detection are missing.","archived":false,"fork":false,"pushed_at":"2026-06-29T06:35:44.000Z","size":3974,"stargazers_count":168,"open_issues_count":18,"forks_count":117,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-06-29T08:16:46.066Z","etag":null,"topics":["addressee-detection","ai-agents","barge-in","conversational-ai","device-directed-speech","elevenlabs","livekit","openai","pipecat","real-time","realtime","speech-processing","turn-detection","twilio","voice-activity-detection","voice-agents","voice-ai","voice-assistant","voice-sdk","webrtc"],"latest_commit_sha":null,"homepage":"https://attentionlabs.ai","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/attenlabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-18T14:12:35.000Z","updated_at":"2026-06-29T06:35:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/attenlabs/saa-sdk","commit_stats":null,"previous_names":["attenlabs/saa-sdk"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/attenlabs/saa-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/attenlabs%2Fsaa-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/attenlabs%2Fsaa-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/attenlabs%2Fsaa-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/attenlabs%2Fsaa-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/attenlabs","download_url":"https://codeload.github.com/attenlabs/saa-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/attenlabs%2Fsaa-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35153109,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"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":["addressee-detection","ai-agents","barge-in","conversational-ai","device-directed-speech","elevenlabs","livekit","openai","pipecat","real-time","realtime","speech-processing","turn-detection","twilio","voice-activity-detection","voice-agents","voice-ai","voice-assistant","voice-sdk","webrtc"],"created_at":"2026-07-05T12:01:55.718Z","updated_at":"2026-07-05T12:01:56.526Z","avatar_url":"https://github.com/attenlabs.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/saa-hero-dark.png\"\u003e\n    \u003cimg alt=\"SAA: Selective Auditory Attention\" src=\"./assets/saa-hero.png\" width=\"408\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003ch3 align=\"center\"\u003eTells your voice agent which speech is actually for it.\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003eOne decision per utterance: only addressee speech reaches your STT, LLM, and TTS. No wake word.\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@attenlabs/saa-js\"\u003e\u003cimg alt=\"npm\" src=\"https://img.shields.io/npm/v/@attenlabs/saa-js?label=npm\u0026color=D9FF00\u0026labelColor=060d0f\u0026style=for-the-badge\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/attenlabs-saa/\"\u003e\u003cimg alt=\"PyPI\" src=\"https://img.shields.io/pypi/v/attenlabs-saa?label=pypi\u0026color=D9FF00\u0026labelColor=060d0f\u0026style=for-the-badge\"\u003e\u003c/a\u003e\n  \u003ca href=\"./LICENSE\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/badge/license-Apache--2.0-D9FF00?labelColor=060d0f\u0026style=for-the-badge\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003eDrop-in for the voice-agent stack you already use:\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"./examples/pipecat/\"\u003e\u003cimg alt=\"Pipecat\" src=\"./assets/brands/pipecat.svg\" height=\"28\"\u003e\u003c/a\u003e\n  \u0026nbsp;\u0026nbsp;\n  \u003ca href=\"./examples/livekit/\"\u003e\u003cimg alt=\"LiveKit\" src=\"./assets/brands/livekit.svg\" height=\"28\"\u003e\u003c/a\u003e\n  \u0026nbsp;\u0026nbsp;\n  \u003ca href=\"./examples/elevenlabs/\"\u003e\u003cimg alt=\"ElevenLabs Conversational AI\" src=\"./assets/brands/elevenlabs.svg\" height=\"28\"\u003e\u003c/a\u003e\n  \u0026nbsp;\u0026nbsp;\n  \u003ca href=\"./examples/twilio/\"\u003e\u003cimg alt=\"Twilio Media Streams\" src=\"./assets/brands/twilio.svg\" height=\"28\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## What is SAA?\n\nA voice agent's microphone hears every voice in the room: yours, a coworker's, the kids, a podcast playing on the laptop, the agent's own TTS bleeding back through the speakers. Most pipelines respond to any of it, paying STT for every transcribed second and triggering the LLM on speech that was never directed at the device.\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth align=\"center\" width=\"33%\"\u003eSingle device \u0026middot; robot\u003c/th\u003e\n      \u003cth align=\"center\" width=\"33%\"\u003eSingle device \u0026middot; laptop\u003c/th\u003e\n      \u003cth align=\"center\" width=\"34%\"\u003eMulti-device \u0026middot; two robots\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg alt=\"Pollen Robotics Reachy robot listening; SAA fires only when the speaker addresses it.\" src=\"./assets/reachy-demo-loop.gif\" width=\"100%\"\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg alt=\"Live laptop session. SAA gates speech in a real browser tab; the pill flips green only when the user is addressing the laptop, ambient room speech stays gray.\" src=\"./assets/use-cases/laptop.gif\" width=\"100%\"\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg alt=\"Two Pollen Robotics Reachy robots in the same room, hearing the same audio. Only the addressed robot acts; the other stays still.\" src=\"./assets/use-cases/reachy.gif\" width=\"100%\"\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003csub\u003eOnly addressed speech wakes the robot.\u003c/sub\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003csub\u003ePill flips green only when the user addresses the screen.\u003c/sub\u003e\u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\u003csub\u003eSame room, same audio. Only the addressed robot acts.\u003c/sub\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n**SAA** (Selective Auditory Attention) is a hosted classifier that runs **before STT** and decides, per utterance, whether the speech was directed at the device. Side talk, background media, and the agent's own playback are filtered out, so your STT / LLM / TTS only see audio meant for the agent.\n\n- **No wake word.** SAA decides per-utterance from the audio (and optionally low-rate video) stream.\n- **Hosted.** A real-time WebSocket to attention labs' cloud; the model, weights, and inference run server-side, and these Apache-2.0 client SDKs are thin: they capture, encode, and stream audio (and optional low-rate video). Because it gates before STT, only addressed speech reaches the STT, LLM, and TTS you already run, so your downstream services and logs see less audio, not more. On-device deployment is a separate enterprise licence.\n\n## Ways to integrate\n\n| Shape | Package | Use it when |\n|---|---|---|\n| **Streaming SDK** | [`@attenlabs/saa-js`](./packages/saa-js), [`attenlabs-saa`](./packages/saa-py) | your app captures the audio/video itself and you want typed attention events to gate your own pipeline. Good for web agents, mall kiosks, drive-through agents, and robots. |\n| **LiveKit** | [`saa-livekit-client`](./packages/saa-livekit-client) | you run a [LiveKit Agents](https://docs.livekit.io/agents/) voice agent. SAA joins your room and gates the session. |\n| **Pipecat (Daily)** | [`saa-pipecat-client`](./packages/saa-pipecat-client) | you run a [Pipecat](https://github.com/pipecat-ai/pipecat) voice agent on Daily. SAA joins your Daily room and gates the pipeline through the `\"saa\"` app-message topic. |\n| **ElevenLabs** | [`attenlabs-saa`](./packages/saa-py) | you run an [ElevenLabs Conversational AI](./examples/elevenlabs) agent. SAA gates it via the streaming SDK's `feed_audio` (its room is sealed, so SAA can't join it directly). |\n| **Twilio** | [`attenlabs-saa`](./packages/saa-py) | you run a [Twilio Media Streams](https://www.twilio.com/docs/voice/media-streams) telephony agent. SAA gates inbound/outbound call audio (μ-law 8 kHz resampled to PCM16) via the streaming SDK's `feed_audio`. |\n\n## Install\n\n```bash\nnpm install @attenlabs/saa-js     # JavaScript / browser\npip install attenlabs-saa          # Python (streaming SDK)\npip install saa-livekit-client     # Python (LiveKit)\npip install saa-pipecat-client     # Python (Pipecat on Daily)\n```\n\nGet an API key at [attentionlabs.ai/dashboard](https://attentionlabs.ai/dashboard).\n\n## Streaming SDK\n\nYou capture the media; SAA emits typed events. The key event is `turnReady` / `turn_ready`, one device-directed utterance, captured and ready to forward to your STT or LLM.\n\n```js\nimport { AttentionClient } from \"@attenlabs/saa-js\";\n\nconst client = new AttentionClient({ token: process.env.SAA_API_KEY });\n\n// fires once per device-directed turn; turn.audioBase64 is PCM16 @ 16 kHz\nclient.on(\"turnReady\", (turn) =\u003e yourSTT.send(turn.audioBase64));\n\nawait client.start({ videoElement: document.querySelector(\"video\") });\n```\n\n```python\nimport os\nfrom saa import AttentionClient\n\nclient = AttentionClient(token=os.environ[\"SAA_API_KEY\"])\n\n@client.on_turn_ready\ndef _(turn):\n    # turn.audio_base64, PCM16 @ 16 kHz mono; turn.audio_pcm16, np.int16 array\n    your_stt.send(turn.audio_base64)\n\nclient.start()\n```\n\nFor audio-only deployments, omit `videoElement` (browser) or pass `enable_video=False` (Python).\n\nBoth SDKs also emit `prediction`, `vad`, `state`, `interrupt`, `config`, and `stats` events, and expose `mute()` / `unmute()`, `setThreshold()` / `set_threshold()`, and `markResponding()` / `mark_responding()`. See [`packages/saa-js`](./packages/saa-js) and [`packages/saa-py`](./packages/saa-py).\n\nRunnable end-to-end demos are in [`examples/web/`](./examples/web) (browser) and [`examples/python/`](./examples/python) (terminal).\n\n## LiveKit\n\nFor [LiveKit Agents](https://docs.livekit.io/agents/), `saa-livekit-client` brings SAA into your room to run the classifier and publish events on the `\"saa\"` data topic. Your agent consumes them through `AttentionEngine` and gates the session.\n\n```python\nfrom saa_livekit_client import AttentionEngine, attention_agent_token, start_attention_session\n\nsaa = await start_attention_session(\n    api_key=SAA_API_KEY, livekit_url=LIVEKIT_URL,\n    agent_token=attention_agent_token(api_key=LK_KEY, api_secret=LK_SECRET, room_name=ctx.room.name),\n    room_name=ctx.room.name, participant_identity=user.identity,\n)\nengine = AttentionEngine(ctx.room, agent_identity=saa.agent_identity)\n\n@engine.on_prediction\ndef _(p):\n    session.input.set_audio_enabled(p.aligned_class == 2)   # the gate\n\nawait engine.start()\n```\n\nTwo runnable samples, an OpenAI Realtime agent and a vanilla-JS web client, are in [`examples/livekit/`](./examples/livekit).\n\n## Pipecat on Daily\n\nFor [Pipecat](https://github.com/pipecat-ai/pipecat) voice agents running on Daily, `saa-pipecat-client` brings SAA into your Daily room and publishes events on Daily's app-message channel under the `\"saa\"` topic. Your bot consumes them through `AttentionEngine` (which subscribes via your `DailyTransport`) and gates the pipeline.\n\n```python\nfrom saa_pipecat_client import AttentionEngine, attention_agent_token, start_attention_session\n\nsaa = await start_attention_session(\n    api_key=SAA_API_KEY, room_url=ROOM_URL,\n    agent_token=attention_agent_token(daily_api_key=DAILY_API_KEY, room_name=room_name),\n    participant_identity=human_identity,\n)\nengine = AttentionEngine(transport, agent_identity=saa.agent_identity)\nengine.bind_task(task)\n\n@engine.on_prediction\ndef _(p):\n    addressee_gate.suppressed = (p.aligned_class == 1 and p.confidence \u003e 0.7)\n\nawait engine.start()\n```\n\nA runnable web-client sample is in [`examples/pipecat/`](./examples/pipecat).\n\n## ElevenLabs\n\n[ElevenLabs Conversational AI](https://elevenlabs.io/docs/eleven-agents/overview) runs its agent in a sealed WebRTC room, so SAA can't join it directly. Instead the streaming SDK runs in feed mode: you hand it the agent's microphone audio through `feed_audio` and gate the agent on SAA's `prediction` events.\n\n```python\nfrom saa import AttentionClient\n\n# feed mode: the SDK captures nothing itself; you supply the audio\nsaa = AttentionClient(token=SAA_API_KEY, enable_audio=False, enable_video=False)\n\n@saa.on_prediction\ndef _(p):\n    mic_to_agent.enabled = (p.aligned_class == 2)   # 2 = addressed to the device\n\nsaa.start()\n# in ElevenLabs' AudioInterface input callback:\nsaa.feed_audio(mic_pcm16)\n```\n\nA runnable sample is in [`examples/elevenlabs/`](./examples/elevenlabs).\n\n## Twilio\n\nFor [Twilio Media Streams](https://www.twilio.com/docs/voice/media-streams) telephony agents, the streaming SDK runs in feed mode over the call audio. The adapter transcodes Twilio's μ-law 8 kHz frames to PCM16 16 kHz, feeds them to SAA, and forwards only device-directed turns to your bridge, so side talk, hold music, and the agent's own TTS echo are gated out.\n\n```python\nfrom saa import AttentionClient\n\nsaa = AttentionClient(token=SAA_API_KEY, enable_audio=False, enable_video=False)\n\n@saa.on_turn_ready\ndef _(turn):\n    bridge.on_speech(turn.audio_base64)   # only device-directed call audio continues\n\nsaa.start()\n# in the Twilio media handler, after decoding μ-law -\u003e PCM16:\nsaa.feed_audio(pcm16_frames)\n```\n\nA runnable Media Streams bridge (codec, paced outbound, automatic `mark_responding`) is in [`examples/twilio/`](./examples/twilio).\n\n## Proactive agents (speak first)\n\nThe streaming SDKs expose `markResponding(true)` / `mark_responding(True)` so the agent can assert when *it* is the one speaking, suppressing the gate during its own TTS and resuming once the tail clears. The LiveKit and Pipecat bridges expose the same lifecycle via `engine.responding_start()` / `responding_stop()`, identical surface.\n\n\n## How it composes\n\nSAA is the model-agnostic addressee decision between your VAD and STT. It answers a different question than VAD (is anyone speaking), speaker diarization (which voice it is), turn detection (have they finished), or a wake word (did they say the phrase), so it composes with those layers and can replace the wake word outright.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Where SAA sits in your voice stack: noise suppression and VAD upstream, SAA addressee gate, then STT → LLM → TTS downstream\" src=\"./assets/diagrams/where-saa-sits-dark.svg\" width=\"820\"\u003e\n\u003c/p\u003e\n\n## On-device deployment\n\nThese Apache-2.0 client SDKs stream to the SAA cloud. For deployments where audio must stay on the device (telephony, embedded systems, wearables, robotics, kiosks), request on-device and embedded access at [attentionlabs.ai](https://attentionlabs.ai/#contact).\n\n## Documentation\n\n- [`packages/saa-js/README.md`](./packages/saa-js/README.md), [`packages/saa-py/README.md`](./packages/saa-py/README.md), streaming SDK reference.\n- [`packages/saa-livekit-client/README.md`](./packages/saa-livekit-client/README.md): the LiveKit client.\n- [`packages/saa-pipecat-client/README.md`](./packages/saa-pipecat-client/README.md): the Pipecat-on-Daily client.\n- [`examples/README.md`](./examples/README.md), runnable examples.\n- [`examples/twilio/README.md`](./examples/twilio/README.md): the Twilio Media Streams bridge.\n\n## How SAA compares\n\n| Layer | The question it answers | What it does not tell you |\n|---|---|---|\n| Voice activity detection (VAD) | Is anyone speaking right now? | Whether that speech was meant for the agent |\n| Speaker diarization / speaker ID | Who is speaking? | Whether that person is addressing the agent |\n| Turn detection / endpointing | Has the speaker finished their turn? | Whether the turn was directed at the agent |\n| Wake word | Did they say the trigger phrase? | Natural address with no keyword (and it degrades across multi-turn / hands-busy use) |\n| Noise suppression / audio enhancement | Is the audio clean? | Whether the clean audio was directed at the agent |\n| **SAA (this SDK)** | **Was this utterance directed at the device?** | It does not transcribe, identify the speaker, or denoise; it gates, then hands addressed audio to the layers you already run |\n\nSAA composes with every layer above; it does not replace them (it can make a wake word optional where wake-word UX is the bottleneck).\n\n## FAQ\n\n**Isn't this just VAD?**\nNo. VAD answers \"is anyone speaking?\" and fires on any voice: a coworker, the TV, the person next to your user. SAA answers \"was this speech directed at the device?\" and runs after VAD, so the pipeline only wakes on audio actually meant for the agent.\n\n**Is this speaker identification or diarization?**\nNo. Speaker ID answers \"who is speaking\" and diarization answers \"who said what.\" SAA answers \"who is being spoken to.\" An enrolled user can address the person beside them (not for the agent); an unenrolled stranger can speak straight to the device (for the agent). It is an orthogonal primitive: no enrollment, no speaker profiles.\n\n**Does it run on-device?**\nNo. SAA is a hosted service. The npm and PyPI packages are Apache-2.0 thin clients that capture, encode, and stream audio (and optional low-rate video) to the hosted inference endpoint; the model and weights run server-side. On-device and embedded delivery is a separate enterprise programme; it is not part of the public SDK.\n\n**Does it add latency?**\nYes: one hosted round-trip before STT. SAA does not make addressed speech faster. What it removes is the full STT + LLM + TTS pipeline firing on audio that was never addressed to the agent. Whether that is net-positive depends on how much non-directed audio your environment carries.\n\n**Why bother, what does it save me?**\nIn multi-talker environments, a large share of what your VAD flags was never meant for the agent. SAA drops that audio before STT is invoked, so you transcribe and reason over fewer non-directed seconds and get fewer ghost responses. The cheapest token is the one you never spend.\n\n**Will the agent respond to its own voice?**\nNot if you tell it when it is talking. Call `markResponding(true)` / `mark_responding(True)` when your TTS starts; SAA suppresses the gate during playback and resumes once the tail clears. No mute-mic hack.\n\n**How do I trade off false positives vs. false negatives?**\n`setThreshold()` / `set_threshold()` moves the operating point on the precision-recall curve. When the model is uncertain it fails closed: audio is not forwarded unless the system is confident the speech is addressed to the device. So the conservative default errs toward a possibly-missed command rather than a spurious trigger. Loosen the threshold to forward more readily; tighten it to suppress more aggressively.\n\n**What about my language?**\nThe acoustic model is designed to be language-agnostic, but cross-lingual validation is ongoing and cross-lingual recall is a known limitation under active work. English is where confidence is highest today; test carefully in other languages and in heavy-overlap (simultaneous-speech) environments before relying on it.\n\n**How accurate is it?**\nOn the held-out evaluation in the technical report (arXiv:2604.08412): **0.86 F1 audio-only**, **0.95 F1 audio + video fusion**. Two caveats up front: it fails closed under distribution shift, and cross-lingual recall is a known limitation. The paper figures demonstrate the approach; real-world performance varies by acoustic environment.\n\n**Is it open source?**\nThe client SDKs are Apache-2.0. The model, weights, and inference are a hosted service, not open source; think of SAA as a hosted API with permissively-licensed client libraries, not a self-hostable model.\n\n## License\n\nApache-2.0 across the repo, each package and the examples ship under it (see each subtree's `LICENSE`). The hosted cloud service is governed by the attention labs Terms of Service.\n\n[`SECURITY.md`](./SECURITY.md) · [`CONTRIBUTING.md`](./CONTRIBUTING.md) · [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md) · [`CHANGELOG.md`](./CHANGELOG.md) · [`NOTICE`](./NOTICE) · [`CITATION.cff`](./CITATION.cff)\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003eAn attention labs project. © 2026 Socero Inc.\u003c/sub\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fattenlabs%2Fsaa-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fattenlabs%2Fsaa-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fattenlabs%2Fsaa-sdk/lists"}