LangChain TTS tool using Audra HTTP — Audra

Once an agent can write the script, the next question is always 'can it voice it?' Yes — wrap Audra as a tool. This is the exact @tool definition, focused on the two failure modes that make LLM-driven TTS flaky: unbounded input and untrusted wait times.

The tool definition

from langchain_core.tools import tool
import requests, os, hashlib

AUDRA_KEY = os.environ["AUDRA_API_KEY"]

@tool
def narrate(text: str, filename: str) -> str:
    """Render narration audio from a script and save it as an MP3 file.

    Args:
        text: The script to narrate. Keep under 8000 characters per call;
              split longer scripts and call once per section.
        filename: Output file name ending in .mp3 (no slashes).
    """
    if len(text) > 9000:
        return "ERROR: text too long — split into sections under 8000 chars"
    if "/" in filename or not filename.endswith(".mp3"):
        return "ERROR: filename must be a bare .mp3 name"

    r = requests.post(
        "https://audratalks.com/v2/speech",
        headers={
            "Authorization": f"Bearer {AUDRA_KEY}",
            "Idempotency-Key": hashlib.sha256(text.encode()).hexdigest(),
        },
        json={"model": "audra-essential", "voice": "june",
              "text": text, "format": "mp3"},
        timeout=3600,
    )
    if r.status_code == 429:
        return f"ERROR: rate limited, retry after {r.headers['Retry-After']}s"
    r.raise_for_status()
    open(filename, "wb").write(r.content)
    return f"saved {filename} ({len(text)} chars rendered)"

Design decisions that matter for agents

Wiring it in

Bind it like any other tool: tools=[narrate] in create_react_agent, or as a node in a LangGraph graph that follows your script-writing node. Rate limits apply per API key, not per agent: 60 RPM free, 120 RPM paid — if you fan out parallel narrate calls in a Graph with branches, add a semaphore. Model choice and voice slugs are documented at /docs and /voices.