Skip to content

Add agent discovery, CLI commands, module-level agent config, and tests#3

Merged
mahimairaja merged 5 commits intomainfrom
feat/plan-milestone-2-for-openrtc
Mar 19, 2026
Merged

Add agent discovery, CLI commands, module-level agent config, and tests#3
mahimairaja merged 5 commits intomainfrom
feat/plan-milestone-2-for-openrtc

Conversation

@mahimairaja
Copy link
Copy Markdown
Collaborator

@mahimairaja mahimairaja commented Mar 19, 2026

Motivation

  • Provide a way to discover agent modules from a directory instead of registering each agent programmatically.
  • Offer a simple CLI to list and run discovered agents and inject the LiveKit mode for start/dev commands.
  • Make agent examples self-describing via module-level constants so discovery can automatically pick up STT/LLM/TTS/greeting metadata.

Description

  • Implemented AgentPool.discover which loads Python files from a directory, finds a local Agent subclass, and registers it with optional module-level configuration read from AGENT_NAME, AGENT_STT, AGENT_LLM, AGENT_TTS, and AGENT_GREETING attributes.
  • Added helpers _load_agent_module, _find_local_agent_subclass, and _read_module_str to safely import modules and validate configuration values.
  • Reworked the CLI by adding build_parser and a main that supports list, start, and dev commands with a required --agents-dir argument, prints discovered agents for list, and runs the pool for start/dev while injecting sys.argv to set LiveKit mode.
  • Updated examples to expose module-level AGENT_* metadata and switched examples/main.py to use pool.discover(Path(__file__).with_name("agents")).
  • Fixed package __version__ import to use openrtc_python._version and added importlib.util/Path/ModuleType usage in pool.py.
  • Added extensive unit tests and a tests/conftest.py shim to mock livekit.agents for test isolation.

Testing

  • Added tests/test_discovery.py to verify discovery behavior, module config parsing, skipping private modules, import error handling, and ignoring non-local Agent subclasses, and it passed.
  • Added tests/test_cli.py to verify CLI list, start, and dev behaviors and exit codes, and it passed.
  • Added tests/test_pool.py to exercise add, duplicate name checks, type validation, order preservation, and run error behavior, and it passed.

Codex Task

Summary by CodeRabbit

  • New Features

    • CLI adds start, dev, and list subcommands with --agents-dir and optional default provider/greeting overrides
    • Automatic agent discovery from a directory plus per-agent metadata and pool-wide default providers for STT/LLM/TTS/greeting
  • Tests

    • New tests covering CLI flows, discovery behavior, defaults, error cases, and registration ordering
  • Documentation

    • README updated with discovery decorator usage, examples, and CLI docs

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 19, 2026

Warning

Rate limit exceeded

@mahimairaja has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 24 minutes and 11 seconds before requesting another review.

⌛ 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3ecf9b4d-72ea-496f-a83f-b480ca88702d

📥 Commits

Reviewing files that changed from the base of the PR and between d51b02d and 4cb6ca8.

📒 Files selected for processing (1)
  • tests/conftest.py
📝 Walkthrough

Walkthrough

Adds decorator-based agent discovery and directory-based loading: example agents gain @agent_config(...), AgentPool gains defaults and discover() to import modules and register agents, CLI implemented with start/dev/list subcommands, tests and README updated for discovery flow; package exports revised to expose discovery helpers and resolve version via importlib.metadata.

Changes

Cohort / File(s) Summary
Example Agents
examples/agents/dental.py, examples/agents/restaurant.py
Imported agent_config and applied @agent_config(...) class decorators to DentalAgent and RestaurantAgent to attach discovery metadata.
Example Main
examples/main.py
Refactored to construct AgentPool with defaults and call pool.discover(Path(...)/"agents") instead of explicit pool.add(...) registrations.
Public API / Version
src/openrtc/__init__.py
__version__ resolved via importlib.metadata.version("openrtc") with PackageNotFoundError fallback; added AgentDiscoveryConfig and agent_config to public exports and expanded __all__.
CLI
src/openrtc/cli.py
Implemented CLI: build_parser(), _pool_kwargs_from_args(), and main(argv) -> int; added start, dev, and list subcommands, agent discovery invocation, listing output, and exit-code behavior for empty discovery.
AgentPool / Discovery
src/openrtc/pool.py
AgentPool.__init__ accepts default_stt/llm/tts/greeting; added _resolve_* helpers, discover(agents_dir) to import modules by path, _load_agent_module, _find_local_agent_subclass, _resolve_discovery_metadata, module-string readers, and new public AgentDiscoveryConfig dataclass plus agent_config decorator.
Tests: fixtures
tests/conftest.py
Added test fixture that injects src/ into sys.path and stubs livekit/livekit.agents types to allow tests to run without the real dependency.
Tests: CLI
tests/test_cli.py
New tests for CLI main() covering list, start, dev, default-provider passthrough, discover() invocation, sys.argv rewriting, and empty-discovery exit behavior.
Tests: Discovery
tests/test_discovery.py
Comprehensive tests for AgentPool.discover() covering decorator vs. legacy module constants, skip _-prefixed files, import error reporting, missing local Agent subclass error, and local vs imported subclass detection.
Tests: Pool
tests/test_pool.py
Renamed test agent TestAgentDemoAgent and added test verifying AgentPool uses pool-level defaults when agent-specific values are omitted.
Docs
README.md
Documented @agent_config decorator, discovery usage with AgentPool(...).discover(...), CLI examples, and backward compatibility with legacy AGENT_* module constants.

Sequence Diagram(s)

sequenceDiagram
    participant User as CLI User
    participant CLI as openrtc.cli.main()
    participant Parser as ArgParser
    participant Pool as AgentPool
    participant FS as FileSystem
    participant Module as Agent Module

    User->>CLI: run (e.g. "list --agents-dir ./agents")
    CLI->>Parser: parse args
    Parser-->>CLI: args (command, agents_dir, defaults...)
    CLI->>Pool: AgentPool(defaults...)
    CLI->>Pool: pool.discover(agents_dir)
    Pool->>FS: list *.py (skip __init__.py, _*)
    FS-->>Pool: file list
    loop per module
        Pool->>Module: import module by path
        Module-->>Pool: module object (or import error)
        Pool->>Pool: _find_local_agent_subclass(module)
        Pool->>Pool: _resolve_discovery_metadata(module, class attrs)
        Pool->>Pool: pool.add(name, AgentClass, resolved providers/greeting)
    end
    Pool-->>CLI: list[AgentConfig]
    CLI->>User: print/list or run agents (start/dev)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Poem

🐇 I hopped through files with a grin,

Tagged agents so discovery could begin,
CLI whistles, pool gathers the team,
From path to runtime — a discoverer's dream! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title comprehensively and accurately captures the four main additions in this PR: agent discovery, CLI commands, module-level agent config, and tests.

✏️ 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 feat/plan-milestone-2-for-openrtc
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/openrtc/__init__.py`:
- Around line 3-4: The current absolute import of openrtc_python._version is
wrong and causes ModuleNotFoundError; update the module-level version import so
it first attempts a relative import of "._version" for __version__, and if that
fails fall back to reading the installed package version via
importlib.metadata.version("openrtc") (assign result to __version__); ensure the
symbol __version__ is defined either way so tests and imports work.

In `@tests/conftest.py`:
- Around line 14-17: The current check uses "if 'livekit.agents' not in
sys.modules" which only detects prior import and can shadow a real install;
change this to attempt importlib.import_module('livekit.agents') inside a
try/except ImportError and only create the types.ModuleType stubs
(livekit_module, agents_module) and inject them into sys.modules if the import
raises ImportError; keep the same names (livekit_module, agents_module) and the
existing sys.modules assignment logic but guarded by the importlib import
failure.

In `@tests/test_discovery.py`:
- Line 8: The import in src/openrtc/__init__.py incorrectly references
openrtc_python._version; update the top-level import to use the correct package
module by replacing the import of __version__ from openrtc_python._version to
openrtc._version so tests can import the package; specifically edit the import
statement in __init__.py that currently reads from openrtc_python._version and
change it to import __version__ from openrtc._version.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ef368770-c988-4bf8-bfd4-ca0fb591ac3f

📥 Commits

Reviewing files that changed from the base of the PR and between 87a4eb1 and 31e9a42.

📒 Files selected for processing (10)
  • examples/agents/dental.py
  • examples/agents/restaurant.py
  • examples/main.py
  • src/openrtc/__init__.py
  • src/openrtc/cli.py
  • src/openrtc/pool.py
  • tests/conftest.py
  • tests/test_cli.py
  • tests/test_discovery.py
  • tests/test_pool.py

Comment thread src/openrtc/__init__.py Outdated
Comment thread tests/conftest.py Outdated
Comment thread tests/test_discovery.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant