Skip to content

feat(tools): add tunova music generation tool#6513

Open
erliona wants to merge 1 commit into
crewAIInc:mainfrom
erliona:feat/tunova-music-tool
Open

feat(tools): add tunova music generation tool#6513
erliona wants to merge 1 commit into
crewAIInc:mainfrom
erliona:feat/tunova-music-tool

Conversation

@erliona

@erliona erliona commented Jul 10, 2026

Copy link
Copy Markdown

What

Adds TunovaMusicGenerationTool to crewai-tools — the catalog's first music/audio-generation tool. It generates a complete song (Suno v5.5 quality) from a text prompt via the hosted Tunova API and returns the title + audio URL.

  • POST /api/generate → poll GET /api/jobs/{id} every 10s (configurable wait_seconds cap, default 360)
  • Auth via TUNOVA_API_KEY env var (free tier: 50 tokens ≈ 5 songs, no card — reviewers can actually run it)
  • Uses requests (already a base dependency) — no new dependencies
  • Agent-relevant billing semantics surfaced in the tool's return strings: generation is billed only on successful renders; failures auto-refund, so an agent retrying after a failure never burns money

Why

crewai-tools has search, scraping, files, images and video-adjacent tools, but no music/audio generation. Music is a common ask in content-pipeline crews (videos, podcasts, jingles), and the current DIY path is wiring brittle unofficial Suno wrappers by hand.

Testing

  • 6 unit tests, HTTP fully mocked (style copied from serper_dev_tool_test.py) — 6/6 pass
  • ruff check + ruff format --check (repo's pinned 0.15.1) — clean
  • mypy --config-file pyproject.toml on the new file — clean
  • Import/instantiation smoke-tested via from crewai_tools import TunovaMusicGenerationTool

Notes for maintainers

  • Please apply the llm-generated label — this PR was LLM-assisted (per CONTRIBUTING.md; I can't set labels on this repo).
  • tool.specs.json untouched: the generate-tool-specs.yml bot skips fork PRs — happy for it to be regenerated via workflow_dispatch after merge.
  • Docs under docs/en/ deliberately not touched to keep the diff minimal (298 lines, 6 files) — glad to follow up with a docs PR if you want one.
  • Disclosure: I'm the author of the Tunova service.

🤖 Generated with Claude Code

Adds TunovaMusicGenerationTool, which generates complete songs from text
prompts via the Tunova API (hosted Suno-quality music generation, billed
only on successful renders). Submits a generation job, polls until the
render completes or times out, and returns the track title and audio URL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds TunovaMusicGenerationTool, exports it from both package namespaces, documents its API-key configuration and usage, and tests submission, polling, completion, failure, timeout, instrumental mode, and missing-key behavior.

Changes

Tunova music generation

Layer / File(s) Summary
Tool contract and package exports
lib/crewai-tools/src/crewai_tools/tools/tunova_music_generation_tool/tunova_music_generation_tool.py, lib/crewai-tools/src/crewai_tools/__init__.py, lib/crewai-tools/src/crewai_tools/tools/__init__.py
Defines validated prompt, instrumental, and wait-time inputs; configures TUNOVA_API_KEY; and exports TunovaMusicGenerationTool from both namespaces.
Generation request and job polling
lib/crewai-tools/src/crewai_tools/tools/tunova_music_generation_tool/tunova_music_generation_tool.py
Posts generation requests, polls job status, formats completed clips, and returns failure or timeout messages.
Workflow validation and usage documentation
lib/crewai-tools/tests/tools/tunova_music_generation_tool_test.py, lib/crewai-tools/src/crewai_tools/tools/tunova_music_generation_tool/README.md
Tests successful, instrumental, failed, timeout, and missing-key paths, and documents setup, usage, and response formats.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant TunovaMusicGenerationTool
  participant TunovaAPI
  Caller->>TunovaMusicGenerationTool: run(prompt, options)
  TunovaMusicGenerationTool->>TunovaAPI: POST /api/generate
  TunovaAPI-->>TunovaMusicGenerationTool: job_id
  loop Until completion or deadline
    TunovaMusicGenerationTool->>TunovaAPI: GET /api/jobs/{job_id}
    TunovaAPI-->>TunovaMusicGenerationTool: job status and clips
  end
  TunovaMusicGenerationTool-->>Caller: generation result
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding the Tunova music generation tool.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the new tool, tests, and integration details.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@lib/crewai-tools/src/crewai_tools/tools/tunova_music_generation_tool/tunova_music_generation_tool.py`:
- Around line 102-106: Update the submission error handler around _submit_job to
catch ValueError alongside requests.exceptions.RequestException, preserving the
existing logging and user-friendly failure-string behavior for missing job_id
responses.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0f6c0e4b-a758-4f25-9d36-1baa320aadcf

📥 Commits

Reviewing files that changed from the base of the PR and between 85c467d and eaefaa4.

📒 Files selected for processing (6)
  • lib/crewai-tools/src/crewai_tools/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/tunova_music_generation_tool/README.md
  • lib/crewai-tools/src/crewai_tools/tools/tunova_music_generation_tool/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/tunova_music_generation_tool/tunova_music_generation_tool.py
  • lib/crewai-tools/tests/tools/tunova_music_generation_tool_test.py

Comment on lines +102 to +106
try:
job_id = self._submit_job(prompt, make_instrumental)
except requests.exceptions.RequestException as e:
logger.error(f"Error submitting generation job to Tunova API: {e}")
return f"Failed to submit music generation job: {e}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Catch ValueError alongside RequestException in the submission error handler.

_submit_job raises ValueError at line 74 when the API returns a 2xx response without a job_id field. The except block here only catches requests.exceptions.RequestException, so that ValueError propagates unhandled and crashes the tool instead of returning a user-friendly error string — breaking the agent's workflow.

🐛 Proposed fix
         try:
             job_id = self._submit_job(prompt, make_instrumental)
-        except requests.exceptions.RequestException as e:
+        except (requests.exceptions.RequestException, ValueError) as e:
             logger.error(f"Error submitting generation job to Tunova API: {e}")
             return f"Failed to submit music generation job: {e}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try:
job_id = self._submit_job(prompt, make_instrumental)
except requests.exceptions.RequestException as e:
logger.error(f"Error submitting generation job to Tunova API: {e}")
return f"Failed to submit music generation job: {e}"
try:
job_id = self._submit_job(prompt, make_instrumental)
except (requests.exceptions.RequestException, ValueError) as e:
logger.error(f"Error submitting generation job to Tunova API: {e}")
return f"Failed to submit music generation job: {e}"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@lib/crewai-tools/src/crewai_tools/tools/tunova_music_generation_tool/tunova_music_generation_tool.py`
around lines 102 - 106, Update the submission error handler around _submit_job
to catch ValueError alongside requests.exceptions.RequestException, preserving
the existing logging and user-friendly failure-string behavior for missing
job_id responses.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants