accessibility
FreeEnsure accessibility in UI components including semantic HTML, ARIA attributes, keyboard navigation, and WCAG 2.2 AA compliance.
The English summary is being prepared. Showing the original description.
Check voice message pipeline config — verify Whisper, ElevenLabs/OpenAI TTS keys and dependencies.
The English summary is being prepared. Showing the original description.
See how to installReview the instructions the agent will receive before you install.
This skill handles Telegram voice messages end-to-end:
attachment_file_id in channel tagtranscribe-anything)Skill({ skill: 'telegram-voice-pipeline' });
Invoke when:
attachment_file_id attribute (voice or audio message)Telegram voice messages arrive as channel tags:
<channel source="telegram" chat_id="123456" message_id="789" user="username" ts="1234567890" attachment_file_id="BQACAgIAAxkBAAIBc2...">
Key detection logic:
attachment_file_id present → voice/audio message → invoke this skillimage_path present → photo → use image handling insteadCall the Telegram MCP download tool with the file_id from the channel tag:
// MCP tool call (agent uses this directly)
mcp__telegram - relay__download_attachment({ file_id: '<attachment_file_id>' });
// Returns: local file path, e.g. /tmp/voice_abc123.ogg
Verify: The returned path exists and is non-empty (> 1KB for a real voice message).
Error handling: If download fails, reply with a text message: "Sorry, I couldn't download your voice message. Please try again."
Install transcribe-anything if not present:
pip install transcribe-anything
Run transcription:
transcribe-anything /tmp/voice_abc123.ogg --model medium --output_dir /tmp/tg_voice/
Read the transcript:
cat /tmp/tg_voice/voice_abc123.txt
Model selection (trade-off between speed and accuracy):
| Model | Speed | Accuracy | Use when |
|---|---|---|---|
tiny | ~2s | Low | Rapid prototyping only |
small | ~5s | Medium | Short messages, speed priority |
medium | ~12s | High | Default — best balance |
large-v3 | ~30s | Best | Long/complex messages |
Override via env: WHISPER_MODEL=small (default: medium)
Verify: /tmp/tg_voice/<filename>.txt exists and is non-empty.
Error handling: If transcription fails or output is empty, reply: "I received your voice message but couldn't transcribe it. Could you try sending it again or type your message?"
Use the transcribed text as the user input. Generate a text response using the agent's normal response logic.
transcribed_text = contents of /tmp/tg_voice/<filename>.txt
response_text = <agent's generated response to transcribed_text>
Guard max length for TTS: response_text[:4000] (ElevenLabs limit) or response_text[:4096] (OpenAI TTS limit).
ELEVENLABS_API_KEY)import os
from elevenlabs import ElevenLabs
client = ElevenLabs(api_key=os.environ["ELEVENLABS_API_KEY"])
audio = client.text_to_speech.convert(
text=response_text[:4000],
voice_id="JBFqnCBsd6RMkjVDRZzb", # George — clear, neutral voice
model_id="eleven_turbo_v2",
output_format="mp3_44100_128",
)
output_path = "/tmp/tg_voice_response.mp3"
with open(output_path, "wb") as f:
for chunk in audio:
f.write(chunk)
print(f"TTS written to {output_path}")
Override voice via env: ELEVENLABS_VOICE_ID=<voice_id> (default: JBFqnCBsd6RMkjVDRZzb)
OPENAI_API_KEY, no ELEVENLABS_API_KEY)import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
with client.audio.speech.with_streaming_response.create(
model="tts-1",
voice="nova",
input=response_text[:4096],
) as response:
response.stream_to_file("/tmp/tg_voice_response.mp3")
print("TTS written to /tmp/tg_voice_response.mp3")
Selection logic:
if os.environ.get("ELEVENLABS_API_KEY"):
# Use ElevenLabs
else:
# Use OpenAI TTS fallback
Verify: /tmp/tg_voice_response.mp3 exists and is > 1KB.
Error handling: If TTS fails, send response_text as a plain text reply instead of audio.
// MCP tool call
mcp__telegram -
relay__reply({
chat_id: '<chat_id from channel tag>',
text: response_text, // Also send the transcript so user can read it
files: ['/tmp/tg_voice_response.mp3'],
});
Note: Including text alongside the audio file gives the user both a readable transcript and the audio reply — useful for accessibility and noisy environments.
Verify: No error returned from the reply tool.
After a successful reply, clean up to avoid disk accumulation:
rm -f /tmp/tg_voice_response.mp3
rm -rf /tmp/tg_voice/
| Variable | Required | Default | Purpose |
|---|---|---|---|
ELEVENLABS_API_KEY | NO (if OpenAI set) | — | ElevenLabs TTS API key |
ELEVENLABS_VOICE_ID | NO | JBFqnCBsd6RMkjVDRZzb | ElevenLabs voice (George) |
OPENAI_API_KEY | NO (if ElevenLabs set) | — | OpenAI TTS fallback key |
WHISPER_MODEL | NO | medium | Whisper model size |
At least one of ELEVENLABS_API_KEY or OPENAI_API_KEY must be set for TTS to work.
[Telegram] User sends 10-second voice message
↓
[Agent] Detects attachment_file_id in channel tag
↓
[MCP] download_attachment(file_id) → /tmp/voice_abc123.ogg
↓
[Bash] transcribe-anything /tmp/voice_abc123.ogg --model medium → "What is the weather like today?"
↓
[Agent] Generates response: "I don't have real-time weather data, but I can help you check..."
↓
[Python] ElevenLabs TTS → /tmp/tg_voice_response.mp3
↓
[MCP] reply(chat_id, text="I don't have...", files=["/tmp/tg_voice_response.mp3"])
↓
[Telegram] User receives text + audio reply
↓
[Bash] rm /tmp/tg_voice_response.mp3 && rm -rf /tmp/tg_voice/
Total time for 10-second voice message: ~15-25 seconds (download 1s + transcribe 12s + TTS 2s + reply 1s).
attachment_file_id is not a file path, it must be resolved via the MCP toolshell: true for subprocess calls in transcription — use array args with shell: falseimage_path, not attachment_file_id; route them differentlyenable-telegram — Start the channel daemon for background Telegram monitoringtranscription — Whisper transcription workflow (used in Step 2)tts-generation — ElevenLabs and OpenAI TTS (used in Step 4)mcp__telegram-relay__download_attachment, mcp__telegram-relay__replytranscribe-anything: https://github.com/modal-labs/transcribe-anythingFor code discovery and search tasks, follow this priority order:
pnpm search:code "<query>" (Primary intent-based search).ripgrep (for exact keyword/regex matches).Before starting:
cat .claude/context/memory/learnings.md
cat .claude/context/memory/decisions.md
After completing:
.claude/context/memory/learnings.md.claude/context/memory/issues.md.claude/context/memory/decisions.mdASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.
No reviews yet. Tell others what you thought.
No login needed. Share how it worked for you, ask a question, or note where it did not run.
No comments yet. Be the first to write one.
Ensure accessibility in UI components including semantic HTML, ARIA attributes, keyboard navigation, and WCAG 2.2 AA compliance.
The English summary is being prepared. Showing the original description.
Use when you want to improve response quality through meta-cognitive reasoning. Applies 15+ reasoning methods to reconsider and refine initial outputs.
The English summary is being prepared. Showing the original description.
N-round opposing-stance debates for trade-off analysis. Assigns pro/con roles to agents, runs structured debate rounds with quality scoring, and produces a moderator synthesis with confidence-rated recommendation. Generalizable to architecture, technology, security, and design decisions.
The English summary is being prepared. Showing the original description.
Force adversarial code review stance that eliminates confirmation bias — reviewer must find issues or re-analyze
The English summary is being prepared. Showing the original description.
Creates specialized AI agents on-demand when no existing agent matches a request. Use when the Router cannot find a suitable agent for a task. Enables self-evolution by generating persistent agents.
The English summary is being prepared. Showing the original description.
LLM-as-judge evaluation framework with 5-dimension rubric (accuracy, groundedness, coherence, completeness, helpfulness) for scoring AI-generated content quality with weighted composite scores and evidence citations
The English summary is being prepared. Showing the original description.