Skip to content

feat(agents): Phase 10A — YouTube transcript subagent#17

Merged
Krasimir-Hristov merged 2 commits into
mainfrom
feature/phase-10a-youtube-agent
May 9, 2026
Merged

feat(agents): Phase 10A — YouTube transcript subagent#17
Krasimir-Hristov merged 2 commits into
mainfrom
feature/phase-10a-youtube-agent

Conversation

@Krasimir-Hristov

@Krasimir-Hristov Krasimir-Hristov commented May 9, 2026

Copy link
Copy Markdown
Owner
  • Add youtube_agent_node: fetches transcript via youtube-transcript-api, oEmbed metadata via YouTube API (no key needed), runs hierarchical LLM summarization (chunk → parallel chunk summaries → final summary)
  • Add YOUTUBE_HANDOFF_TOOL_NAME + transfer_to_youtube_agent @tool in supervisor
  • Update supervisor system prompt with mandatory YouTube URL routing rules
  • Extend orchestrator _should_continue to route to youtube_agent node
  • Add youtube_context: str field to AxonState for cross-turn save flow
  • Add youtube_summary_model setting (default: google/gemini-2.5-flash)
  • Install youtube-transcript-api==0.6.3 + defusedxml==0.7.1

Flow: supervisor detects URL → transfer_to_youtube_agent tool call → youtube_agent_node fetches + summarizes → ToolMessage with JSON payload → supervisor presents title/channel/duration/summary/key_points + asks to save

Summary by CodeRabbit

  • New Features

    • Added YouTube video processing capabilities to extract transcripts from videos, perform intelligent summarization with key point extraction, and generate structured video metadata for enhanced content understanding.
  • Chores

    • Updated application configuration with YouTube processing model settings and added required dependencies for transcript extraction and processing functionality.

Review Change Stack

- Add youtube_agent_node: fetches transcript via youtube-transcript-api,
  oEmbed metadata via YouTube API (no key needed), runs hierarchical
  LLM summarization (chunk → parallel chunk summaries → final summary)
- Add YOUTUBE_HANDOFF_TOOL_NAME + transfer_to_youtube_agent @tool in supervisor
- Update supervisor system prompt with mandatory YouTube URL routing rules
- Extend orchestrator _should_continue to route to youtube_agent node
- Add youtube_context: str field to AxonState for cross-turn save flow
- Add youtube_summary_model setting (default: google/gemini-2.5-flash)
- Install youtube-transcript-api==0.6.3 + defusedxml==0.7.1

Flow: supervisor detects URL → transfer_to_youtube_agent tool call →
youtube_agent_node fetches + summarizes → ToolMessage with JSON payload →
supervisor presents title/channel/duration/summary/key_points + asks to save
@coderabbitai

coderabbitai Bot commented May 9, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@Krasimir-Hristov has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 29 minutes and 21 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1b9d92ba-6a4a-4906-90dd-4afd10029a99

📥 Commits

Reviewing files that changed from the base of the PR and between d9ee895 and f333a3b.

📒 Files selected for processing (6)
  • backend/app/agents/subagents/youtube_agent.py
  • backend/app/agents/subagents/youtube_chunker.py
  • backend/app/agents/subagents/youtube_fetcher.py
  • backend/app/agents/subagents/youtube_summarizer.py
  • backend/app/agents/supervisor.py
  • implementationPlan.MD

Walkthrough

This PR introduces a YouTube sub-agent to the multi-agent orchestrator, enabling the supervisor to delegate YouTube video URLs for transcript summarization. A new youtube_agent_node fetches transcripts and metadata, chunks content, performs hierarchical LLM-based summarization, and returns structured JSON context. The supervisor routing, orchestrator graph, and shared state are extended to support the handoff flow.

Changes

YouTube Sub-Agent & Routing

Layer / File(s) Summary
Data Contracts & Configuration
backend/app/agents/state.py, backend/app/core/config.py
AxonState TypedDict adds youtube_context: str field to persist JSON payloads. Settings adds youtube_summary_model config for LLM selection.
Supervisor Tool & Routing
backend/app/agents/supervisor.py
Added YOUTUBE_HANDOFF_TOOL_NAME constant and transfer_to_youtube_agent() tool. System prompt extended with YouTube URL detection and mandatory tool rules. Model binding updated to include both transfer_to_memory_agent and transfer_to_youtube_agent when tools enabled.
YouTube Sub-Agent Helpers
backend/app/agents/subagents/youtube_agent.py
Module introduces video ID extraction (regex), transcript/oEmbed fetching (via YouTubeTranscriptApi and httpx), transcript chunking (~16k chunks), and parallel LLM-based chunk summarization with semaphore concurrency control.
YouTube Sub-Agent Node Implementation
backend/app/agents/subagents/youtube_agent.py
youtube_agent_node resolves handoff tool_call_id, extracts video URL from human message, fetches transcript/metadata concurrently, performs hierarchical summarization, and returns ToolMessage with JSON payload (video_id, URL, title, channel, duration, summary, key_points). Includes error handling for missing URLs and transcript failures.
Orchestrator Integration & Routing
backend/app/agents/orchestrator.py
_should_continue router extended to detect YOUTUBE_HANDOFF_TOOL_NAME and route to "youtube_agent" node. Graph construction registers youtube_agent node; conditional edges map supervisor → youtube_agent and youtube_agent → supervisor → END. Routing prevents repeated delegation by checking for tool messages in current turn.
Dependencies & Implementation Plan
backend/pyproject.toml, implementationPlan.MD
Added youtube-transcript-api>=1.2.4 dependency. Updated implementation plan with architecture decision log and PHASES 10A–10D: fetch-summarize, transcript persistence, TTS generation, and audio library.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Krasimir-Hristov/AXON#7: Supervisor and multi-agent orchestrator routing foundation that this PR directly extends with YouTube sub-agent support.
  • Krasimir-Hristov/AXON#4: Original AxonState and orchestrator graph structure that this PR modifies by adding youtube_context field and YouTube routing.
  • Krasimir-Hristov/AXON#5: Prior tool-routing and orchestrator conditional logic changes that share the same routing helper (_should_continue) extended here.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically identifies Phase 10A of the YouTube transcript subagent feature, directly matching the PR's primary objective of implementing the youtube_agent_node with transcript fetching and hierarchical summarization.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/phase-10a-youtube-agent

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 and usage tips.

@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: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/app/agents/subagents/youtube_agent.py (1)

1-375: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Split this sub-agent into smaller modules before it grows further.

At 375 lines, this file already exceeds the backend limit and mixes URL parsing, transcript I/O, chunking, prompting, model initialization, and node orchestration in one place. Please break the fetch/parse/summarize/schema pieces apart now; otherwise the Phase 10B/10C additions will make this much harder to change safely.

As per coding guidelines, "Always modular: one responsibility per file" and "No file longer than 300 lines — split into smaller modules."

🤖 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 `@backend/app/agents/subagents/youtube_agent.py` around lines 1 - 375, The file
is doing multiple responsibilities; split it into smaller modules: 1) create a
youtube_fetcher module containing _extract_video_id, _fetch_oembed,
_fetch_transcript and the _YOUTUBE_URL_RE constant; 2) create a chunker module
with _build_chunks, _CHARS_PER_TOKEN and _CHUNK_SIZE_CHARS; 3) create a
summarizer module that holds _get_summary_model, _CHUNK_SUMMARY_SYSTEM,
_CHUNK_SUMMARY_USER, _FINAL_SUMMARY_USER, _summarize_chunks, and
_build_final_summary (including _MAX_CONCURRENT_SUMMARIES); and 4) keep
orchestration in youtube_agent.py with youtube_agent_node, the tool constants,
and the small helper _error_response only delegating to the new modules; update
imports and adjust calls (e.g., import youtube_fetcher._extract_video_id,
chunker._build_chunks, summarizer._summarize_chunks/_build_final_summary) and
ensure logging and settings usage remain unchanged so behavior is preserved.
🤖 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 `@backend/app/agents/subagents/youtube_agent.py`:
- Around line 218-219: The code currently parses the LLM JSON into a plain dict
and converts key_points with list(), which can turn a string into a char list
and allows arbitrary shape to be persisted to youtube_context; define a Pydantic
v2 model (e.g., YouTubeSummaryPayload with fields summary: str and key_points:
list[str]) near the helpers, then replace the raw json.loads + dict handling in
the function that reads content (the block returning str(data.get("summary",
"")), list(data.get("key_points", []))) to parse/validate via
YouTubeSummaryPayload.model_validate_json(content) (or model_validate after
json.loads) and return the validated summary and key_points; on validation
error, log/raise and avoid persisting corrupted payload. Apply the same change
to the other similar block referenced (lines ~346-355) so both LLM output and
persisted state use the same schema.
- Around line 132-139: The _fetch_transcript function currently offloads
synchronous YouTubeTranscriptApi.get_transcript using asyncio.to_thread which
will exhaust the threadpool under concurrency; replace this by either (A)
switching to an async transcript client that natively supports async calls, or
(B) implement a custom async wrapper that uses httpx.AsyncClient to perform the
same HTTP requests/parameter handling and parse the transcript responses
asynchronously (remove asyncio.to_thread and YouTubeTranscriptApi usage), and if
neither is possible add clear docstring/comments on _fetch_transcript (and where
it’s called) warning about the thread-pool trade-offs and limiting concurrency
(e.g., semaphore) to avoid exhausting the default executor.

In `@backend/app/agents/supervisor.py`:
- Around line 105-113: The supervisor's post-handoff prompt asks "Would you like
me to save this to your library?" even though the supervisor only binds the two
handoff tools and not save_video_transcript; update the supervisor logic (the
code around transfer_to_youtube_agent handling and the handoff tools binding in
supervisor) to either (A) only append the save prompt when save_video_transcript
is actually bound/available in the supervisor's tools set, or (B) bind the
save_video_transcript tool alongside the existing handoff tools so the
affirmative path can be executed; locate references to
transfer_to_youtube_agent, the supervisor tool-binding list, and any code that
formats the final YouTube result (also the similar block around the 164-166
region) and apply the conditional check or tool binding change accordingly.

In `@backend/pyproject.toml`:
- Line 25: The current call to YouTubeTranscriptApi.get_transcript(video_id) is
incompatible with youtube-transcript-api v1.2.0+; replace that call with the new
instance API: construct YouTubeTranscriptApi(), call .fetch(video_id) and then
.to_raw_data() to return the same transcript data (i.e., change
YouTubeTranscriptApi.get_transcript(video_id) to
YouTubeTranscriptApi().fetch(video_id).to_raw_data()). Also update any tests or
callers expecting the old return shape if needed, or alternatively change the
pyproject dependency to youtube-transcript-api<1.2.0 if you prefer to keep the
old static API.

In `@implementationPlan.MD`:
- Around line 261-264: The plan contains conflicting provider/model sources
(hardcoded gpt-4o-mini in youtube_agent vs settings.youtube_summary_model, and
TTS described both as OpenAI direct API and OpenRouter); unify these by choosing
a single configuration surface (e.g., settings.youtube_summary_model for
summarization and settings.tts_provider or settings.tts_api for TTS) and update
all references and descriptions to use those settings; ensure youtube_agent
reads from settings.youtube_summary_model (remove any gpt-4o-mini hardcode) and
the TTS section consistently documents the selected provider (OpenAI vs
OpenRouter) driven by settings.tts_provider so future implementers have one
source of truth.
- Around line 270-302: The markdown fenced-block containing the process flow
(starting with "User pastes YouTube URL" and steps like
"transfer_to_youtube_agent") lacks a language tag and the SQL fences (e.g., code
sections containing "INSERT into video_transcripts" and "INSERT into
audio_entries") are not separated by blank lines; update the flow block to
include a language (e.g., ```text or ```flow) and add a blank line before and
after each SQL fenced block so the SQL fences are isolated, then run
markdownlint to confirm no more fenced-block violations.

---

Outside diff comments:
In `@backend/app/agents/subagents/youtube_agent.py`:
- Around line 1-375: The file is doing multiple responsibilities; split it into
smaller modules: 1) create a youtube_fetcher module containing
_extract_video_id, _fetch_oembed, _fetch_transcript and the _YOUTUBE_URL_RE
constant; 2) create a chunker module with _build_chunks, _CHARS_PER_TOKEN and
_CHUNK_SIZE_CHARS; 3) create a summarizer module that holds _get_summary_model,
_CHUNK_SUMMARY_SYSTEM, _CHUNK_SUMMARY_USER, _FINAL_SUMMARY_USER,
_summarize_chunks, and _build_final_summary (including
_MAX_CONCURRENT_SUMMARIES); and 4) keep orchestration in youtube_agent.py with
youtube_agent_node, the tool constants, and the small helper _error_response
only delegating to the new modules; update imports and adjust calls (e.g.,
import youtube_fetcher._extract_video_id, chunker._build_chunks,
summarizer._summarize_chunks/_build_final_summary) and ensure logging and
settings usage remain unchanged so behavior is preserved.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 78a11cb7-164d-43a4-9305-9f6bac327c8e

📥 Commits

Reviewing files that changed from the base of the PR and between c6f03a5 and d9ee895.

⛔ Files ignored due to path filters (1)
  • backend/uv.lock is excluded by !**/*.lock, !**/uv.lock
📒 Files selected for processing (7)
  • backend/app/agents/orchestrator.py
  • backend/app/agents/state.py
  • backend/app/agents/subagents/youtube_agent.py
  • backend/app/agents/supervisor.py
  • backend/app/core/config.py
  • backend/pyproject.toml
  • implementationPlan.MD

Comment thread backend/app/agents/subagents/youtube_agent.py Outdated
Comment thread backend/app/agents/subagents/youtube_agent.py Outdated
Comment thread backend/app/agents/supervisor.py
Comment thread backend/pyproject.toml
Comment thread implementationPlan.MD Outdated
Comment thread implementationPlan.MD Outdated
- Split youtube_agent.py (375 lines) into 3 focused modules:
  youtube_fetcher.py, youtube_chunker.py, youtube_summarizer.py
  (each under 170 lines; agent.py now ~140 lines — within 300-line rule)

- Add Pydantic validation for LLM JSON output:
  YouTubeSummaryPayload validates final summary response (prevents string
  key_points being turned into a char list via list())
  YouTubeVideoPayload validates full persisted payload before model_dump_json()

- Update transcript API to youtube-transcript-api v1.x instance API:
  YouTubeTranscriptApi().fetch(video_id).to_raw_data()
  replaces deprecated static YouTubeTranscriptApi.get_transcript()

- Add thread-pool usage docstring to fetch_transcript (asyncio.to_thread note)

- Remove premature save CTA from supervisor system prompt:
  'Would you like me to save this to your library?' removed since
  save_video_transcript tool is not yet bound (Phase 10B)

- Fix implementationPlan.MD conflicting notes:
  gpt-4o-mini hardcode → settings.youtube_summary_model (Gemini 2.5 Flash)
  OpenAI direct TTS → OpenRouter openai/gpt-audio-mini
  Add language tag to flow fenced block; isolate SQL fences with blank lines
@Krasimir-Hristov Krasimir-Hristov merged commit 50a2b1b into main May 9, 2026
2 checks passed
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.

1 participant