Skip to content
tnsaiDocs
GitHub

Images and speech

Three built-in toolkits in tnsai-tools let an agent generate images, speak text and transcribe audio. Each toolkit exposes one tool per provider, so the model can pick a provider at call time.

ToolkitBuiltInToolToolsDirection
ImageGenToolsIMAGE_GEN_TOOLSdalle3_generate, flux_generate, stability_generateText to image
TextToSpeechToolsTEXT_TO_SPEECH_TOOLSelevenlabs_tts, cartesia_tts, deepgram_ttsText to speech
SpeechToTextToolsSPEECH_TO_TEXT_TOOLSdeepgram_transcribe, assemblyai_transcribe, replicate_whisperAudio file to text

MEDIA_TOOLS adds the OpenAI pair: openai_tts and whisper_transcribe. Register it next to the others when you want OpenAI and another provider in the same agent.

Register the toolkits

Pass the toolkits to builtInTools(...). AgentBuilder.build() requires principal and authorityScope, and liabilitySink is optional.

package com.example.tnsai.docs;

import com.tnsai.accountability.AuthorityScope;
import com.tnsai.accountability.LiabilitySink;
import com.tnsai.agents.Agent;
import com.tnsai.agents.AgentBuilder;
import com.tnsai.enums.BuiltInTool;
import com.tnsai.identity.AgentPrincipal;
import com.tnsai.llm.providers.OpenAIClient;
import com.tnsai.roles.Role;

public final class ToolsMultimodalBuilderExample {
    private ToolsMultimodalBuilderExample() {}

    public static Agent build(
        Role myRole,
        AgentPrincipal principal,
        LiabilitySink sink,
        AuthorityScope scope
    ) {
        return AgentBuilder.create()
            .llm(new OpenAIClient("gpt-4o"))
            .role(myRole)
            .builtInTools(
                BuiltInTool.IMAGE_GEN_TOOLS,
                BuiltInTool.TEXT_TO_SPEECH_TOOLS,
                BuiltInTool.SPEECH_TO_TEXT_TOOLS
            )
            .principal(principal)
            .liabilitySink(sink)
            .authorityScope(scope)
            .build();
    }
}

The agent then calls the tools from a chat turn:

Agent artist = ToolsMultimodalBuilderExample.build(myRole, principal, sink, scope);
String reply = artist.chat("Draw a watercolor painting of a giraffe on Mars");

Every tool returns a JSON string. Each tool checks its arguments before the HTTP call, so a bad value fails with IllegalArgumentException naming the allowed values.

Images: IMAGE_GEN_TOOLS

ToolProviderKeyReturns
dalle3_generateOpenAI DALL-E 3OPENAI_API_KEYprovider, model (dall-e-3), urls, revised_prompt when the model rewrote the prompt
flux_generateFLUX on ReplicateREPLICATE_API_TOKENprovider, model (flux-<model>), urls
stability_generateStability AI Stable ImageSTABILITY_API_KEYprovider, model, urls, finish_reason when present
ToolParametersDefaults
dalle3_generatesize: 1024x1024, 1792x1024, 1024x1792. quality: standard, hd. n: must be 1.1024x1024, standard, 1
flux_generatemodel: schnell, dev, pro. aspectRatio, such as 1:1 or 16:9. outputFormat: webp, jpg, png.schnell, 1:1, webp
stability_generatemodel: core, sd3, ultra. aspectRatio, such as 1:1 or 16:9.core, 1:1

DALL-E and FLUX return provider-hosted URLs. DALL-E URLs expire about an hour after generation, so download the image if you need to keep it. Stability returns the image itself, and urls holds it as a data:image/png;base64,… URI.

Speech: TEXT_TO_SPEECH_TOOLS

ToolProviderKeyModels or voicesDefault
elevenlabs_ttsElevenLabsELEVENLABS_API_KEYeleven_multilingual_v2, eleven_monolingual_v1, eleven_turbo_v2_5, eleven_flash_v2_5eleven_multilingual_v2, voice 21m00Tcm4TlvDq8ikWAM
cartesia_ttsCartesiaCARTESIA_API_KEYsonic-2, sonic-english, sonic-multilingualsonic-2, voice a0e99841-438c-4a64-b679-ae501e7d6091
deepgram_ttsDeepgram AuraDEEPGRAM_API_KEY12 voices, such as aura-asteria-en and aura-orion-enaura-asteria-en

ElevenLabs and Cartesia take a voiceId next to the model. Deepgram picks the voice through model.

All three return the same shape:

{
  "provider": "elevenlabs",
  "model": "eleven_multilingual_v2",
  "audio_uri": "data:audio/mpeg;base64,SUQzBAAAAAAAJ...",
  "audio_bytes": 45920
}

audio_uri plays directly in an <audio> element. Input is capped at 2000 characters per call.

Transcription: SPEECH_TO_TEXT_TOOLS

Each tool takes audioPath, the absolute path to a local file of at most 50 MB. Supported formats are MP3, WAV, M4A, OGG and FLAC.

ToolProviderKeyModelsReturns
deepgram_transcribeDeepgramDEEPGRAM_API_KEYnova-2 (default), nova-2-general, nova-2-meeting, nova-2-phonecall, nova-3, enhanced, baseprovider, model, text, language, confidence
assemblyai_transcribeAssemblyAIASSEMBLYAI_API_KEYuniversal-2provider, model, text, language, audio_duration
replicate_whisperWhisper on ReplicateREPLICATE_API_TOKENlarge-v3 (default), large-v2, medium, smallprovider, model (whisper-<model>), text, language when present

deepgram_transcribe takes a language code, default en. assemblyai_transcribe takes an optional languageCode.

assemblyai_transcribe uploads the file, submits a job and polls it. Polling starts at two seconds, backs off to ten, and gives up after 300 seconds.

The OpenAI whisper_transcribe in MEDIA_TOOLS has its own 25 MB cap, and openai_tts caps input at 4096 characters.

API keys

VariableUsed by
OPENAI_API_KEYdalle3_generate, whisper_transcribe, openai_tts
REPLICATE_API_TOKENflux_generate, replicate_whisper
STABILITY_API_KEYstability_generate
ELEVENLABS_API_KEYelevenlabs_tts
CARTESIA_API_KEYcartesia_tts
DEEPGRAM_API_KEYdeepgram_tts, deepgram_transcribe
ASSEMBLYAI_API_KEYassemblyai_transcribe

A tool reads its key from the environment when it is called, not when the agent is built. You can register a toolkit without its keys. A call without the key throws IllegalStateException, and the message names the missing variable.

  • Catalog: every built-in toolkit.
  • Audio: WhisperClient for transcription outside an agent.
  • Custom tools: write your own @Tool methods.