Skip to content

fix: accept multi-channel bot.yaml keys with platform field#1772

Merged
MervinPraison merged 2 commits into
mainfrom
cursor/critical-bug-investigation-425d
Jun 2, 2026
Merged

fix: accept multi-channel bot.yaml keys with platform field#1772
MervinPraison merged 2 commits into
mainfrom
cursor/critical-bug-investigation-425d

Conversation

@cursor

@cursor cursor Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Bug and impact

After #1757 (multi-Telegram onboard), praisonai onboard writes bot.yaml with channel keys such as telegram_cfo and a platform: telegram field. BotYamlSchema only allowed channel keys that exactly matched platform names (telegram, discord, …), so praisonai doctor and any path using load_and_validate_bot_yaml failed with Unknown channel 'telegram_cfo' even when the config was valid for the gateway.

Root cause

BotYamlSchema.validate_channels_exist validated the YAML dict key as the platform name and did not model platform on ChannelConfigSchema.

Fix

  • Add platform, routes, and allowed_users to ChannelConfigSchema.
  • Resolve the platform from channel.platform when present, otherwise from the channel key.
  • Regression test for telegram_<role> keys.

Validation

  • Reproduced failure with onboard-style YAML before fix; passes after fix.
  • Manual checks: unknown signal channel still rejected; multi-channel keys accepted.
Open in Web View Automation 

Summary by CodeRabbit

  • New Features
    • Added support for explicit platform configuration per channel, enabling flexible channel naming patterns.
    • Channels can now be configured with allowed_users restrictions.
    • Channels can now define custom routes mappings.

Review Change Stack

…gression)

Onboard generates channels like telegram_cfo with platform: telegram.
BotYamlSchema rejected any channel key not exactly matching a platform name,
so praisonai doctor reported invalid bot.yaml after multi-bot onboard.

Validate using channel.platform when present; extend ChannelConfigSchema for
gateway-style fields used in generated configs.

Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
@MervinPraison

Copy link
Copy Markdown
Owner

@coderabbitai review

@MervinPraison

Copy link
Copy Markdown
Owner

/review

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d99560ff-d943-4b49-b042-0e94a332790c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR extends channel configuration to support explicit per-channel platform specification. ChannelConfigSchema gains platform, allowed_users, and routes fields, while validation logic now respects the explicit platform field when determining which supported platform to validate against, with error messages updated to report both the channel key and resolved platform. A test validates this functionality with Telegram role-specific channels.

Changes

Channel Configuration Enhancement

Layer / File(s) Summary
Channel schema fields and platform validation
src/praisonai/praisonai/bots/_config_schema.py, src/praisonai/tests/unit/test_bot_gap_features.py
ChannelConfigSchema adds optional platform, allowed_users, and routes fields. validate_channels_exist now resolves platform from channel.platform or the channel key and validates against supported platforms, with error messages including both channel name and resolved platform. Test verifies multi-channel Telegram config with explicit platform field is correctly validated.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • MervinPraison/PraisonAI#1757: Multi-telegram multi-channel work that relies on the channels[].platform field additions and validation logic updates from this PR.

Suggested reviewers

  • MervinPraison

Poem

A rabbit hops through channels bright,
With platforms now explicit and right,
Each channel knows its name and mode,
The config schema takes a load,
Validation dances, tests delight! 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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 'fix: accept multi-channel bot.yaml keys with platform field' directly describes the main change: extending BotYamlSchema to accept channel keys with a platform field for multi-channel configurations.
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 cursor/critical-bug-investigation-425d

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.

@MervinPraison

Copy link
Copy Markdown
Owner

@copilot Do a thorough review of this PR. Read ALL existing reviewer comments above from Qodo, Coderabbit, and Gemini first — incorporate their findings.

Review areas:

  1. Bloat check: Are changes minimal and focused? Any unnecessary code or scope creep?
  2. Security: Any hardcoded secrets, unsafe eval/exec, missing input validation?
  3. Performance: Any module-level heavy imports? Hot-path regressions?
  4. Tests: Are tests included? Do they cover the changes adequately?
  5. Backward compat: Any public API changes without deprecation?
  6. Code quality: DRY violations, naming conventions, error handling?
  7. Address reviewer feedback: If Qodo, Coderabbit, or Gemini flagged valid issues, include them in your review
  8. Suggest specific improvements with code examples where possible

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/praisonai/tests/unit/test_bot_gap_features.py (1)

296-315: ⚡ Quick win

Use monkeypatch for env isolation in the new test.

Line 296 mutates process env directly; prefer pytest’s monkeypatch.setenv/delenv to avoid cross-test leakage and simplify cleanup.

Proposed diff
-    def test_multi_channel_custom_keys_with_platform(self):
+    def test_multi_channel_custom_keys_with_platform(self, monkeypatch):
         """Onboard multi-telegram YAML uses telegram_<role> keys plus platform field."""
         from praisonai.bots._config_schema import validate_bot_config
 
-        os.environ["_TEST_CFO_TOKEN"] = "cfo-token"
-        try:
-            raw = {
-                "channels": {
-                    "telegram_cfo": {
-                        "platform": "telegram",
-                        "token": "${_TEST_CFO_TOKEN}",
-                        "group_policy": "mention_only",
-                    },
-                    "telegram_ops": {
-                        "platform": "telegram",
-                        "token": "${_TEST_CFO_TOKEN}",
-                    },
-                }
-            }
-            result = validate_bot_config(raw)
-            assert result.channels["telegram_cfo"].platform == "telegram"
-            assert result.channels["telegram_cfo"].token == "cfo-token"
-        finally:
-            os.environ.pop("_TEST_CFO_TOKEN", None)
+        monkeypatch.setenv("_TEST_CFO_TOKEN", "cfo-token")
+        raw = {
+            "channels": {
+                "telegram_cfo": {
+                    "platform": "telegram",
+                    "token": "${_TEST_CFO_TOKEN}",
+                    "group_policy": "mention_only",
+                },
+                "telegram_ops": {
+                    "platform": "telegram",
+                    "token": "${_TEST_CFO_TOKEN}",
+                },
+            }
+        }
+        result = validate_bot_config(raw)
+        assert result.channels["telegram_cfo"].platform == "telegram"
+        assert result.channels["telegram_cfo"].token == "cfo-token"
🤖 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 `@src/praisonai/tests/unit/test_bot_gap_features.py` around lines 296 - 315,
The test mutates os.environ directly; change it to use pytest's monkeypatch
fixture to isolate env changes: add the monkeypatch parameter to the test
function, replace os.environ["_TEST_CFO_TOKEN"] = "cfo-token" and the
try/finally cleanup with monkeypatch.setenv("_TEST_CFO_TOKEN", "cfo-token") (or
monkeypatch.delenv if needed), and then call validate_bot_config(raw) as before
(refer to validate_bot_config and the test function in
test_bot_gap_features.py); monkeypatch will automatically restore the
environment after the test.
🤖 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.

Nitpick comments:
In `@src/praisonai/tests/unit/test_bot_gap_features.py`:
- Around line 296-315: The test mutates os.environ directly; change it to use
pytest's monkeypatch fixture to isolate env changes: add the monkeypatch
parameter to the test function, replace os.environ["_TEST_CFO_TOKEN"] =
"cfo-token" and the try/finally cleanup with
monkeypatch.setenv("_TEST_CFO_TOKEN", "cfo-token") (or monkeypatch.delenv if
needed), and then call validate_bot_config(raw) as before (refer to
validate_bot_config and the test function in test_bot_gap_features.py);
monkeypatch will automatically restore the environment after the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 60886665-570a-4135-8202-b1e7673f0e28

📥 Commits

Reviewing files that changed from the base of the PR and between d5f1114 and e387ef5.

📒 Files selected for processing (2)
  • src/praisonai/praisonai/bots/_config_schema.py
  • src/praisonai/tests/unit/test_bot_gap_features.py

@MervinPraison

Copy link
Copy Markdown
Owner

@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Focus ONLY on Python packages (praisonaiagents, praisonai). Do NOT modify praisonai-rust or praisonai-ts. Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding.

Phase 1: Review per AGENTS.md

  1. Protocol-driven: check heavy implementations vs core SDK
  2. Backward compatible: ensure zero feature regressions
  3. Performance: no hot-path regressions

Phase 2: FIX Valid Issues
4. For any VALID bugs or architectural flaws found by Gemini, CodeRabbit, Qodo, Copilot, or any other reviewer: implement the fix
5. Push all code fixes directly to THIS branch (do NOT create a new PR)
6. Comment a summary of exact files modified and what you skipped

Phase 3: Final Verdict
7. If all issues are resolved, approve the PR / close the Issue
8. If blocking issues remain, request changes / leave clear action items

@praisonai-triage-agent

praisonai-triage-agent Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Claude finished @MervinPraison's task —— View job


Final Architecture Review Complete

Phase 1: Architecture Review per AGENTS.md

  • Read AGENTS.md for architecture guidelines
  • Review changed files for protocol-driven design compliance
  • Check backward compatibility
  • Verify no performance regressions

Phase 2: Fix Valid Issues

  • Fix monkeypatch issue identified by CodeRabbit
  • Address docstring coverage if needed
  • Push fixes to current branch

Phase 3: Final Verdict

  • Approve PR or request changes
  • Provide summary of modifications made

Architecture Review Summary ✅

All architecture requirements met:

  • Protocol-Driven: Changes correctly placed in wrapper package (praisonai), not core SDK
  • Backward Compatible: Zero breaking changes - existing configs continue to work
  • Performance: No hot-path regressions - validation runs once at startup
  • Minimal Scope: Focused fix with no scope creep

Issues Fixed

  1. ✅ Environment Isolation: Fixed test to use pytest.monkeypatch instead of direct os.environ manipulation for proper test isolation
  2. ⚠️ Docstring Coverage: This is a CI warning about overall project coverage (50% vs 80%), not related to these specific changes

Files Modified

  • src/praisonai/tests/unit/test_bot_gap_features.py: Improved test hygiene with monkeypatch

What Was Skipped

  • Docstring coverage improvement: This is a project-wide metric and not blocking for this specific bugfix

Final Verdict: APPROVED

This PR successfully fixes the multi-channel bot.yaml validation bug introduced in #1757. The implementation is architecturally sound, maintains backward compatibility, and includes appropriate test coverage.

Ready for merge.


- Replace direct os.environ manipulation with pytest monkeypatch
- Ensures test environment isolation and automatic cleanup
- Addresses CodeRabbit review feedback

Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
@MervinPraison MervinPraison marked this pull request as ready for review June 2, 2026 06:13
Copilot AI review requested due to automatic review settings June 2, 2026 06:13
@MervinPraison MervinPraison merged commit 8327f8e into main Jun 2, 2026
6 checks passed
@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Accept multi-channel bot.yaml keys with platform field

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Accept multi-channel bot.yaml keys with explicit platform field
• Extend ChannelConfigSchema with platform, allowed_users, routes fields
• Resolve platform from channel.platform when present, fallback to key
• Add regression test for telegram_ multi-channel keys
Diagram
flowchart LR
  A["bot.yaml with<br/>telegram_cfo key"] -->|"platform: telegram<br/>field present"| B["ChannelConfigSchema<br/>with platform field"]
  B -->|"validate_channels_exist<br/>resolves platform"| C["Validation passes<br/>for custom keys"]
  D["Unknown platform<br/>e.g. signal"] -->|"validation check"| E["Validation fails<br/>as expected"]

Loading

Grey Divider

File Changes

1. src/praisonai/praisonai/bots/_config_schema.py 🐞 Bug fix +10/-4

Add platform field and flexible channel key validation

• Added platform, allowed_users, and routes fields to ChannelConfigSchema
• Modified validate_channels_exist to resolve platform from channel.platform when present,
 otherwise from channel key
• Updated error message to include both channel name and resolved platform for clarity
• Supports both traditional platform-named keys and custom multi-channel keys like telegram_cfo

src/praisonai/praisonai/bots/_config_schema.py


2. src/praisonai/tests/unit/test_bot_gap_features.py 🧪 Tests +22/-0

Add regression test for multi-channel custom keys

• Added test_multi_channel_custom_keys_with_platform test case
• Uses monkeypatch for environment variable isolation instead of direct os.environ manipulation
• Validates that custom channel keys like telegram_cfo and telegram_ops with explicit platform
 field are accepted
• Verifies token interpolation and platform field preservation in validated config

src/praisonai/tests/unit/test_bot_gap_features.py


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Jun 2, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0)

Grey Divider


Action required

1. Platform remains unset 🐞 Bug ≡ Correctness
Description
validate_channels_exist() derives a platform from (channel.platform or name) for validation but
doesn’t persist it back onto the ChannelConfigSchema, so configs that omit platform leave
channel.platform == None. praisonai doctor later calls platform.upper() and will crash with
AttributeError for these common configs.
Code

src/praisonai/praisonai/bots/_config_schema.py[R111-113]

Evidence
The schema allows platform-less channels but leaves channel.platform as None, while doctor
checks call platform.upper() unconditionally, causing a crash for standard configs like `channels:
{telegram: {...}}`.

src/praisonai/praisonai/bots/_config_schema.py[100-118]
src/praisonai/praisonai/bots/_config_schema.py[24-33]
src/praisonai/praisonai/cli/features/doctor/checks/bot_checks.py[238-286]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BotYamlSchema.validate_channels_exist()` accepts channels whose key is the platform name (e.g., `telegram`) but does not populate `ChannelConfigSchema.platform` when it is omitted. Downstream code (doctor checks) assumes `platform` is a string and calls `.upper()`, which will crash when `platform` is `None`.

## Issue Context
This PR made `platform` optional to support custom channel keys like `telegram_cfo`, but it also needs to preserve backward compatibility for the long-standing `{channels: {telegram: {...}}}` format.

## Fix Focus Areas
- src/praisonai/praisonai/bots/_config_schema.py[93-118]
- src/praisonai/praisonai/bots/_config_schema.py[24-36]
- src/praisonai/praisonai/cli/features/doctor/checks/bot_checks.py[233-286]

## Suggested implementation
- In `validate_channels_exist()`, after computing `platform = (channel.platform or name).lower()`, assign it back to the model (e.g., `channel.platform = platform`) so all channels have a normalized non-null platform.
- Consider normalizing with `.strip().lower()` to avoid whitespace issues.
- Add a defensive fallback in doctor check (`platform = channel_config.platform or channel_name`) to avoid future crashes if `platform` is ever missing.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. allowed_users type too narrow 🐞 Bug ⚙ Maintainability
Description
ChannelConfigSchema.allowed_users is Optional[str], so gateway-style YAML that uses
allowed_users: ["99", "88"] will fail schema validation even though the gateway runtime and tests
support list-form allowlists. This makes the schema inconsistent with the supported gateway.yaml
format advertised by the module.
Code

src/praisonai/praisonai/bots/_config_schema.py[R32-33]

Evidence
The schema is explicitly intended for bot.yaml / gateway.yaml, but the gateway runtime and tests
show allowed_users is supported as either a string or a list; the new schema field only accepts
strings, creating an inconsistency that can break validation flows.

src/praisonai/praisonai/bots/_config_schema.py[1-5]
src/praisonai/praisonai/bots/_config_schema.py[24-33]
src/praisonai/praisonai/gateway/server.py[1606-1633]
src/praisonai/tests/unit/gateway/test_channel_allowlist.py[39-54]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`ChannelConfigSchema.allowed_users` is typed as `Optional[str]`, which rejects list-form `allowed_users` configurations (e.g., `allowed_users: ["99", "88"]`). The gateway runtime explicitly supports both comma-separated strings and lists.

## Issue Context
This module is documented as validating both `bot.yaml` and `gateway.yaml`. The gateway path already handles list-form allowlists and has tests covering it.

## Fix Focus Areas
- src/praisonai/praisonai/bots/_config_schema.py[1-5]
- src/praisonai/praisonai/bots/_config_schema.py[24-36]
- src/praisonai/praisonai/gateway/server.py[1628-1633]
- src/praisonai/tests/unit/gateway/test_channel_allowlist.py[39-54]

## Suggested implementation
- Change the type to accept both formats, e.g.:
 - `allowed_users: str | List[str] | None = None`
 - (optionally) add a `field_validator("allowed_users")` to normalize strings into a `List[str]` (split by comma) while leaving lists unchanged.
- Add/extend a unit test in `test_bot_gap_features.py` to ensure `validate_bot_config()` accepts list-form `allowed_users`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@greptile-apps

greptile-apps Bot commented Jun 2, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes BotYamlSchema to accept channel keys like telegram_cfo (written by praisonai onboard after #1757) by resolving the effective platform from channel.platform when present rather than treating the dict key itself as the platform name. It also adds platform, routes, and allowed_users fields to ChannelConfigSchema.

  • Core fix (validate_channels_exist): the (channel.platform or name).lower() fallback correctly handles both legacy bare keys (telegram) and new role-suffixed keys (telegram_cfo); a regression test covers both cases.
  • allowed_users type: the new field is declared as Optional[str], which conflicts with its implied list semantics and the sibling allowlist: List[str] field — a YAML list value would fail Pydantic validation.
  • platform validation: no field-level validator guards the new platform field; invalid values are only caught when the entire BotYamlSchema is assembled, so a standalone ChannelConfigSchema can silently hold an unsupported platform string.

Confidence Score: 4/5

The core channel-key resolution fix is correct and well-tested; the two new schema fields have minor type and validation gaps that are non-breaking but warrant a follow-up.

The platform-resolution logic and validate_channels_exist rewrite are straightforward and the regression test exercises the main scenario. The allowed_users: Optional[str] type will silently reject any YAML that passes a list, but since no gateway code currently reads it the impact is limited. The missing field-level platform validator is a defence-in-depth gap rather than a present defect.

_config_schema.py — specifically the allowed_users type and the lack of a platform field validator on ChannelConfigSchema.

Important Files Changed

Filename Overview
src/praisonai/praisonai/bots/_config_schema.py Adds platform, allowed_users, and routes to ChannelConfigSchema; updates validate_channels_exist to resolve the effective platform from channel.platform when present, falling back to the key name. Core fix is sound. allowed_users is typed Optional[str] while its semantics and sibling field allowlist suggest a list.
src/praisonai/tests/unit/test_bot_gap_features.py Adds test_multi_channel_custom_keys_with_platform regression test covering the primary fix; both channels share the same env-var token, and only telegram_cfo attributes are asserted — telegram_ops is not verified but this is cosmetic.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["validate_bot_config(raw)"] --> B["BotYamlSchema(**raw)"]
    B --> C["ChannelConfigSchema per key"]
    C --> D{"channel.platform set?"}
    D -- "Yes" --> E["platform = channel.platform.lower()"]
    D -- "No" --> F["platform = key_name.lower()"]
    E --> G{"platform in valid_platforms?"}
    F --> G
    G -- "Yes" --> H["Validation passes ✓"]
    G -- "No" --> I["ValueError: Unknown channel '...' (platform '...')"]
Loading

Reviews (1): Last reviewed commit: "fix: use monkeypatch for env isolation i..." | Re-trigger Greptile

group_policy: str = "respond_all" # respond_all, mention_only, command_only
allowlist: List[str] = Field(default_factory=list)
blocklist: List[str] = Field(default_factory=list)
allowed_users: Optional[str] = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 allowed_users is typed Optional[str], but the field name and the PR description ("channels can now be configured with allowed_users restrictions") both imply a list of identifiers. The existing allowlist: List[str] field on the same model serves a comparable purpose. If a user writes allowed_users: [user1, user2] in their YAML, Pydantic will reject it with a type error because a list cannot be coerced to str. The type should be List[str] with an empty default to match intent and avoid silent single-entry-only behaviour.

Suggested change
allowed_users: Optional[str] = None
allowed_users: List[str] = Field(default_factory=list)


class ChannelConfigSchema(BaseModel):
"""Schema for a single channel configuration."""
platform: Optional[str] = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The platform field on ChannelConfigSchema accepts any arbitrary string and is only validated later by the model-level validator in BotYamlSchema. A misconfigured standalone ChannelConfigSchema (e.g. constructed directly in tests or other code) will silently accept platform: "signal" without complaint. Adding a field-level validator here would catch errors earlier, regardless of how the schema is instantiated.

Suggested change
platform: Optional[str] = None
platform: Optional[str] = None
@field_validator("platform")
@classmethod
def validate_platform(cls, v: Optional[str]) -> Optional[str]:
if v is None:
return v
valid = {"telegram", "discord", "slack", "whatsapp", "email", "agentmail"}
if v.lower() not in valid:
raise ValueError(
f"Unknown platform '{v}'. Supported: {', '.join(sorted(valid))}"
)
return v.lower()

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copilot AI 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.

Pull request overview

This PR updates the bot YAML validation schema to support multi-channel configurations where channel keys are custom identifiers (e.g. telegram_cfo) and the actual platform is specified via a platform: field—matching the praisonai onboard output introduced in #1757. It also adds a regression test to ensure these configs validate successfully.

Changes:

  • Extend ChannelConfigSchema to include platform (and accept gateway-style fields like routes / allowed_users).
  • Update channel validation to validate against the resolved platform (channel.platform when present, else the channel key).
  • Add a unit test covering telegram_<role> channel keys with platform: telegram.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/praisonai/praisonai/bots/_config_schema.py Accept custom channel keys by resolving/validating platform via platform field; expands per-channel schema fields.
src/praisonai/tests/unit/test_bot_gap_features.py Adds regression test ensuring onboard-style multi-channel YAML validates and env tokens resolve.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +26 to 30
platform: Optional[str] = None
token: str = ""
mode: str = "poll" # poll | ws | webhook | hybrid
group_policy: str = "respond_all" # respond_all, mention_only, command_only
allowlist: List[str] = Field(default_factory=list)
Comment on lines +111 to +113
for name, channel in self.channels.items():
platform = (channel.platform or name).lower()
if platform not in valid_platforms:
Comment on lines +111 to +113
for name, channel in self.channels.items():
platform = (channel.platform or name).lower()
if platform not in valid_platforms:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Platform remains unset 🐞 Bug ≡ Correctness

validate_channels_exist() derives a platform from (channel.platform or name) for validation but
doesn’t persist it back onto the ChannelConfigSchema, so configs that omit platform leave
channel.platform == None. praisonai doctor later calls platform.upper() and will crash with
AttributeError for these common configs.
Agent Prompt
## Issue description
`BotYamlSchema.validate_channels_exist()` accepts channels whose key is the platform name (e.g., `telegram`) but does not populate `ChannelConfigSchema.platform` when it is omitted. Downstream code (doctor checks) assumes `platform` is a string and calls `.upper()`, which will crash when `platform` is `None`.

## Issue Context
This PR made `platform` optional to support custom channel keys like `telegram_cfo`, but it also needs to preserve backward compatibility for the long-standing `{channels: {telegram: {...}}}` format.

## Fix Focus Areas
- src/praisonai/praisonai/bots/_config_schema.py[93-118]
- src/praisonai/praisonai/bots/_config_schema.py[24-36]
- src/praisonai/praisonai/cli/features/doctor/checks/bot_checks.py[233-286]

## Suggested implementation
- In `validate_channels_exist()`, after computing `platform = (channel.platform or name).lower()`, assign it back to the model (e.g., `channel.platform = platform`) so all channels have a normalized non-null platform.
- Consider normalizing with `.strip().lower()` to avoid whitespace issues.
- Add a defensive fallback in doctor check (`platform = channel_config.platform or channel_name`) to avoid future crashes if `platform` is ever missing.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@MervinPraison MervinPraison deleted the cursor/critical-bug-investigation-425d branch June 12, 2026 23:14
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.

3 participants