Skip to content

feat(tts): add optional provider parameter to text_to_speech tool - #47462

Closed
Cdddo wants to merge 1 commit into
NousResearch:mainfrom
Cdddo:feat/tts-provider-parameter
Closed

Cdddo wants to merge 1 commit into
NousResearch:mainfrom
Cdddo:feat/tts-provider-parameter

Conversation

@Cdddo

@Cdddo Cdddo commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an optional provider parameter to the text_to_speech tool that lets the model select a TTS provider per-call instead of always using the globally configured tts.provider.

Motivation

Currently, text_to_speech reads tts.provider from ~/.hermes/config.yaml. If a user configures Edge TTS as default but an agent task needs ElevenLabs for a specific call, there's no way to do that without changing global config mid-conversation.

This is a common need:

  • Agent skills that need high-quality voices for specific outputs
  • Multi-agent setups where different agents need different TTS backends
  • Tasks mixing fast TTS (Edge) for drafts with premium TTS (ElevenLabs/OpenAI) for final output

Changes

tools/tts_tool.py:

  1. Added optional provider: Optional[str] = None parameter to text_to_speech_tool()
  2. When provider is set, it bypasses the configured default and routes directly to the specified backend
  3. Accepts built-in names (edge, openai, elevenlabs, minimax, xai, mistral, gemini, neutts, kittentts, piper), user-declared command provider names, or plugin-registered names
  4. Updated the tool schema (TTS_SCHEMA) to include the new parameter
  5. Updated the registry handler lambda to pass the parameter through

When provider is omitted (the default), behavior is unchanged — reads from tts.provider in config.yaml.

Backward Compatibility

  • Fully backward compatible — provider defaults to None
  • All existing tests use keyword arguments and continue to pass
  • CLI voice mode (_voice_speak_response) is unaffected
  • No schema breaking changes — new parameter is optional

Testing

  • Syntax validated: ast.parse() passes
  • Import verified: inspect.signature() shows ['text', 'output_path', 'provider']
  • Existing test patterns confirmed: all callers use text= and output_path= keyword args

Closes #47459

Adds an optional provider parameter to the text_to_speech tool that lets the model select a TTS provider per-call instead of always using the globally configured tts.provider.

When provider is set, it bypasses the configured default and routes directly to the specified backend.

When omitted (the default), the tool behaves exactly as before.

Closes NousResearch#47459
@alt-glitch alt-glitch added type/feature New feature or request comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint tool/tts Text-to-speech and transcription P3 Low — cosmetic, nice to have labels Jun 16, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused implementation. The current-main premise is real: text_to_speech_tool() still takes its provider solely from tts.provider at tools/tts_tool.py:2177-2178.

Problems

  • This changes an explicit current contract. tools/tts_tool.py:2160-2161 says the model sends text while the user configures provider, and the exposed schema at tools/tts_tool.py:2844 says provider is “not model-selected.” A maintainer decision is needed before adding a model-controlled override.
  • The proposed override is not validated. An unrecognized value reaches the existing Edge fallback at tools/tts_tool.py:2357-2378, so a typo would not use the selected provider.
  • The PR changes only tools/tts_tool.py and includes no regression coverage for override/default/invalid-provider routing.

Suggested changes

  • Confirm the intended provider-selection contract first. If it is approved, reject unknown or unavailable override values and add routing tests for built-ins, command providers, plugins, and the default fallback.

Automated hermes-sweeper review.

Comment thread tools/tts_tool.py
def text_to_speech_tool(
text: str,
output_path: Optional[str] = None,
provider: Optional[str] = None,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes provider selection model-controlled, but the current tool contract says the user configures provider and the schema says it is not model-selected. Please obtain an explicit maintainer decision before exposing this parameter.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-massive Sweeper blast radius: massive — everyone, every turn (invariant surface) labels Jul 14, 2026
@teknium1

Copy link
Copy Markdown
Collaborator

Merged into main via consolidated salvage PR #73513 (merge 4aac89b429). Your schema-exposed per-call provider override was cherry-picked as 0a83af7 with your authorship — it was the earlier and better-shaped of the two candidates.

Your contribution is credited to you in git history. Thank you! Closing this PR as merged-via-salvage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have sweeper:blast-massive Sweeper blast radius: massive — everyone, every turn (invariant surface) sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades tool/tts Text-to-speech and transcription type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add per-call provider parameter to TTS tool

3 participants