Skip to content

feat(reddit): add moderation blocks - #12945

Open
ntindle wants to merge 13 commits into
devfrom
feat/reddit-moderation-blocks
Open

feat(reddit): add moderation blocks#12945
ntindle wants to merge 13 commits into
devfrom
feat/reddit-moderation-blocks

Conversation

@ntindle

@ntindle ntindle commented Apr 29, 2026

Copy link
Copy Markdown
Member

Why / What / How

Why: AutoGPT already supported Reddit posting and messaging workflows, but it did not expose moderator-focused Reddit actions. Adding them naively would mean asking every Reddit user to grant ban/remove/modmail authority just to read or post, so this PR adds the moderation capabilities and keeps elevated scopes opt-in.

What: Seven Reddit moderation blocks in a dedicated module, per-block least-privilege OAuth scopes (moderator scopes are no longer in the provider-wide default set), granted-scope persistence on the Reddit OAuth handler, unambiguous comment-vs-post targeting, and backend tests plus synced block docs.

How: Each moderation block declares only the elevated scope it actually uses via RedditCredentialsField(required_scopes=...)modposts for mod queue/remove/approve/lock, modcontributors for ban/unban, modmail for modmail. The baseline scopes are merged in by RedditCredentialsField because BaseOAuthHandler.handle_default_scopes replaces rather than unions DEFAULT_SCOPES. State-changing blocks are marked is_sensitive_action=True and require a t1_/t3_-prefixed thing ID so a moderation action can never land on an unrelated object that happens to share the bare ID.

Changes 🏗️

  • Added backend/blocks/reddit_moderation.py with Mod Queue, Remove Reddit Post, Approve Reddit Post, Lock Reddit Post, Ban Subreddit User, Unban Subreddit User, and Send Mod Mail.
  • Kept moderator scopes out of RedditOAuthHandler.DEFAULT_SCOPES. Users connecting Reddit for read/post-only workflows are never asked for moderator authority; only blocks that need it request modposts / modcontributors / modmail. modlog is not requested at all — no block reads the moderation log.
  • Persisted the scopes Reddit actually granted on token exchange and refresh (normalizing Reddit's * wildcard to the requested set), so a non-moderator's credential can't silently claim mod scopes and fail later with an opaque 403.
  • Required an explicit t1_/t3_ prefix on Remove/Approve/Lock inputs — bare IDs are rejected with an actionable error because Reddit posts and comments share an ID namespace. Mod Queue emits prefixed IDs, so the blocks chain directly.
  • Bounded moderator inputs at the schema level: Mod Queue limit (1–100), ban duration (1–999 days, Reddit's cap), and max_length on ban reason/note/message and modmail subject/body.
  • Added backend tests covering every destructive PRAW call shape (approve, lock/unlock, ban, unban, modmail, remove), comment-vs-submission resolution, ambiguous-ID rejection, per-block scope declarations, and the OAuth granted-scope/wildcard handling.
  • Regenerated block docs and completed the manual documentation sections for the new Reddit moderation blocks.
  • No frontend changes: credential scope matching and the incremental scope-upgrade flow (credentials_scopes/login?scopes=…&credential_id=…) already exist and handle these blocks as-is.
  • No configuration or environment changes.

Checklist 📋

For code changes:

  • I have clearly listed my changes in the PR description
  • I have made a test plan
  • I have tested my changes according to the test plan:
    • poetry run pytest backend/blocks/test/test_reddit_moderation.py backend/integrations/oauth/reddit_test.py
    • poetry run pytest backend/blocks/test/test_block.py (shared block harness over every block's test_input/test_output)
    • poetry run format && poetry run lint
    • poetry run python scripts/generate_block_docs.py --check (block docs sync)

For configuration changes:

  • .env.default is updated or already compatible with my changes
  • docker-compose.yml is updated or already compatible with my changes
  • I have included a list of my configuration changes in the PR description (under Changes)

Note

High Risk
Introduces automated ban, remove, and modmail actions with real subreddit impact; OAuth scope changes affect all Reddit connections but are designed to limit over-requesting and mis-recorded grants.

Overview
Adds seven Reddit moderation blocks (mod queue, remove/approve/lock, ban/unban, modmail) in reddit_moderation.py, wired through PRAW with is_sensitive_action on state-changing steps and schema bounds on queue size, ban duration, and text fields.

OAuth is tightened for least privilege: RedditCredentialsField can declare per-block elevated scopes merged with baseline scopes from RedditOAuthHandler; moderator scopes stay out of provider defaults so read/post flows are not asked for mod authority. Token exchange/refresh now stores scopes Reddit actually granted (including * → requested set), not only what was requested.

Moderation targets require t1_ / t3_ fullnames (bare IDs rejected); mod queue outputs prefixed IDs for chaining. Tests cover blocks, scope metadata, and OAuth behavior; integration docs list the new blocks. Minor executor test fixtures mock expert_id and onboarding_db.increment_onboarding_runs.

Reviewed by Cursor Bugbot for commit b9ecb28. Bugbot is set up for automated code reviews on this repo. Configure here.

Add 7 new moderation blocks to the Reddit integration:
- ModQueueBlock: fetch the subreddit mod queue
- RemoveRedditPostBlock: remove a post (with optional spam flag)
- ApproveRedditPostBlock: approve a post from the mod queue
- LockRedditPostBlock: lock/unlock comments on a post
- BanSubredditUserBlock: temp or perma-ban a user
- UnbanSubredditUserBlock: lift a ban
- SendModMailBlock: send modmail from a subreddit to a user

Also add required OAuth2 scopes to RedditOAuthHandler:
modposts, modcontributors, modmail, modlog
@ntindle
ntindle requested a review from a team as a code owner April 29, 2026 18:31
@ntindle
ntindle requested review from Pwuts and kcze and removed request for a team April 29, 2026 18:31
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban Apr 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR targets the master branch but does not come from dev or a hotfix/* branch.

Automatically setting the base branch to dev.

@github-actions
github-actions Bot changed the base branch from master to dev April 29, 2026 18:31
@github-actions github-actions Bot added platform/backend AutoGPT Platform - Back end platform/blocks labels Apr 29, 2026
Comment thread autogpt_platform/backend/backend/blocks/reddit.py Outdated
@coderabbitai

coderabbitai Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds Reddit moderation Blocks and tests, parses and stores granted OAuth scopes on token exchange/refresh, propagates required scopes into Reddit credential fields, introduces wildcard scope semantics and a shared frontend scope-matching helper, and updates docs for moderation blocks.

Changes

Cohort / File(s) Summary
Backend — Reddit moderation blocks
autogpt_platform/backend/backend/blocks/reddit_moderation.py
New module adding moderator Blocks: ModQueueBlock, RemoveRedditPostBlock, ApproveRedditPostBlock, LockRedditPostBlock, BanSubredditUserBlock, UnbanSubredditUserBlock, SendModMailBlock with typed I/O, required scopes, PRAW helpers, and test mocks.
Backend — Reddit credential field
autogpt_platform/backend/backend/blocks/reddit.py
RedditCredentialsField signature extended to `required_scopes: set[str]
Backend — OAuth scope parsing & storage
autogpt_platform/backend/backend/integrations/oauth/reddit.py, autogpt_platform/backend/backend/integrations/oauth/reddit_test.py
Adds RedditOAuthHandler._get_granted_scopes to derive granted scopes (handles space-delimited string, list, and "*" wildcard) and stores granted scopes on token exchange and refresh; tests validate parsing and wildcard behavior and refresh-token preservation.
Backend — Tests for moderation flows
autogpt_platform/backend/backend/blocks/test/test_reddit_moderation.py
New pytest module validating required scopes, mocked PRAW interactions for modqueue, remove/approve/lock, ban/unban validation and behavior, and modmail sending.
Backend — Credential matching tests & utils
autogpt_platform/backend/backend/copilot/tools/http_credentials_test.py, autogpt_platform/backend/backend/copilot/tools/utils.py
Adds test verifying wildcard-scoped credentials satisfy any required scopes; _credential_has_required_scopes now treats missing scopes safely and supports "*" wildcard semantics.
Frontend — Shared scope helper
autogpt_platform/frontend/src/lib/credentials/hasRequiredCredentialScopes.ts
New exported helper hasRequiredCredentialScopes(grantedScopes, requiredScopes) implementing normalization and wildcard ("*") semantics.
Frontend — Scope-matching refactors & tests
autogpt_platform/frontend/src/.../useAgentRunModal.tsx, .../CredentialsGroupedView/helpers.ts, .../CredentialsInput/useCredentialsInput.ts, .../InputRenderer/.../CredentialField/helpers.ts, .../useCredentials.ts, .../useCredentials.test.ts
Replaces inline Set/every scope checks with shared hasRequiredCredentialScopes usage; adds tests for wildcard-scope behavior and adjusts imports.
Docs — Integrations
docs/integrations/README.md, docs/integrations/block-integrations/misc.md
Adds README and detailed docs entries for Reddit moderation Blocks, listing inputs/outputs and required permission scopes.

Sequence Diagram(s)

sequenceDiagram
  participant Block as Moderation Block
  participant Creds as Credential Store
  participant OAuth as RedditOAuthHandler
  participant API as Reddit API / PRAW

  Block->>Creds: request credentials (include required_scopes)
  Creds-->>Block: return OAuth2Credentials (granted scopes)
  Block->>API: perform moderator action (use credentials)
  API-->>Block: action result

  Note over OAuth,Creds: On auth exchange / refresh\nOAuth parses granted scopes and updates Creds
  OAuth->>Creds: store updated scopes (from token response)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

Possible security concern, Review effort 5/5

Suggested reviewers

  • Pwuts
  • kcze
  • Swiftyos

Poem

🐇 I hopped through tokens, scopes in tow,
I sprouted mod blocks—ban, lock, and show,
I taught creds to speak the scopes they knew,
Sent modmail, pruned queues, and bounded through,
Carrot-coded cheers — a rabbit's review!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.37% 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
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.
Title check ✅ Passed The title clearly and concisely identifies the primary change: adding Reddit moderation blocks.
Description check ✅ Passed The description directly explains the Reddit moderation blocks, OAuth scope handling, tests, documentation, and risk.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/reddit-moderation-blocks

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.

Comment thread autogpt_platform/backend/backend/blocks/reddit.py Outdated
Comment thread autogpt_platform/backend/backend/blocks/reddit.py Outdated
Comment thread autogpt_platform/backend/backend/blocks/reddit.py Outdated
@codecov

codecov Bot commented Apr 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.37%. Comparing base (c038eb5) to head (b9ecb28).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev   #12945      +/-   ##
==========================================
- Coverage   77.64%   74.37%   -3.28%     
==========================================
  Files        2859     2778      -81     
  Lines      217035   216997      -38     
  Branches    20673    20532     -141     
==========================================
- Hits       168513   161381    -7132     
- Misses      44011    51275    +7264     
+ Partials     4511     4341     -170     
Flag Coverage Δ
platform-backend 83.76% <100.00%> (+0.07%) ⬆️
platform-frontend-e2e 30.17% <ø> (-0.21%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Platform Backend 83.76% <100.00%> (+0.07%) ⬆️
Platform Frontend 35.09% <ø> (-20.04%) ⬇️
AutoGPT Libs ∅ <ø> (∅)
Classic AutoGPT 28.43% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@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.

Actionable comments posted: 3

🧹 Nitpick comments (1)
autogpt_platform/backend/backend/blocks/reddit.py (1)

2675-2697: Mark the moderator mutations as sensitive actions.

DeleteRedditPostBlock and DeleteRedditCommentBlock already opt into is_sensitive_action=True, but these new moderator mutators do not. Remove/approve/lock/ban/unban/send-modmail are at least as privileged, so they should carry the same safeguard metadata.

Also applies to: 2739-2759, 2792-2814, 2871-2899, 2956-2979, 3021-3047

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/blocks/reddit.py` around lines 2675 - 2697,
The moderator mutation blocks (e.g., RemoveRedditPostBlock and other new
moderator mutators referenced in the diff) must be marked as sensitive actions
like DeleteRedditPostBlock/DeleteRedditCommentBlock; update each block's
super().__init__ call to include is_sensitive_action=True so moderator
operations (remove/approve/lock/ban/unban/send-modmail) carry the same safeguard
metadata as the existing delete blocks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@autogpt_platform/backend/backend/blocks/reddit.py`:
- Around line 2848-2851: The SchemaField "duration" currently allows any int
including 0 or negatives; before calling Reddit API (the calls to
sub.banned.add(...) in the ban-handling functions), validate that duration is
either None or a positive integer and raise/return a validation error for
non-positive values so you never pass 0/negative into Reddit; adjust the logic
that computes the "permanent" output so it is only true when duration is None
(or omitted) and not set when invalid inputs are rejected; apply the same
validation pattern to the other ban-related blocks referenced (the sections
around the sub.banned.add(...) usages at the other ranges).
- Around line 2547-3077: The moderation blocks were added into an already large
reddit.py; extract all moderation-specific classes and helpers into a new module
to reduce file size and clarify responsibilities. Create a new module (e.g.,
reddit_moderation.py) and move the classes ModQueueBlock, RemoveRedditPostBlock,
ApproveRedditPostBlock, LockRedditPostBlock, BanSubredditUserBlock,
UnbanSubredditUserBlock, SendModMailBlock plus their inner Input/Output schemas
and the related static helper methods get_mod_queue, remove_post, approve_post,
set_lock, ban_user, unban_user, send_modmail into it; update imports in the
original reddit.py to import those classes from the new module, preserve the
same IDs/test_* metadata and test_mock keys, and export them where needed so
external callers/tests keep the same symbols. Ensure any references to
RedditCredentialsField, strip_reddit_prefix, get_praw, settings, Block,
BlockSchemaInput/Output, SchemaField, BlockCategory, TEST_CREDENTIALS,
TEST_CREDENTIALS_INPUT remain imported (move or re-import) and run a quick test
run to verify no import cycles were introduced.

In `@autogpt_platform/backend/backend/integrations/oauth/reddit.py`:
- Around line 39-42: Remove moderator-level scopes ("modposts",
"modcontributors", "modmail", "modlog") from DEFAULT_SCOPES so ordinary Reddit
auth falls back to least privilege; update handle_default_scopes() to use the
reduced DEFAULT_SCOPES. Ensure any moderation-specific OAuth flows explicitly
add those moderator scopes only in the code paths that initiate moderator
workflows (instead of relying on DEFAULT_SCOPES). Also stop persisting the
requested scope list verbatim: when storing scopes after the OAuth exchange,
persist the actual granted scopes returned by Reddit (the token response scope
string/array) rather than the original requested scopes in the handler that
records OAuth results.

---

Nitpick comments:
In `@autogpt_platform/backend/backend/blocks/reddit.py`:
- Around line 2675-2697: The moderator mutation blocks (e.g.,
RemoveRedditPostBlock and other new moderator mutators referenced in the diff)
must be marked as sensitive actions like
DeleteRedditPostBlock/DeleteRedditCommentBlock; update each block's
super().__init__ call to include is_sensitive_action=True so moderator
operations (remove/approve/lock/ban/unban/send-modmail) carry the same safeguard
metadata as the existing delete blocks.
🪄 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

Run ID: 5bbf2486-f27e-44e2-b96e-64da708bd8c8

📥 Commits

Reviewing files that changed from the base of the PR and between c08b977 and a065f69.

📒 Files selected for processing (2)
  • autogpt_platform/backend/backend/blocks/reddit.py
  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: test (3.13)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.11)
  • GitHub Check: Check PR Status
  • GitHub Check: end-to-end tests
🧰 Additional context used
📓 Path-based instructions (3)
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

autogpt_platform/backend/**/*.py: Use poetry run ... command for executing Python package dependencies
Use top-level imports only — avoid local/inner imports except for lazy imports of heavy optional dependencies like openpyxl
Use absolute imports with from backend.module import ... for cross-package imports; single-dot relative imports are acceptable for sibling modules within the same package; avoid double-dot relative imports
Do not use duck typing — avoid hasattr/getattr/isinstance for type dispatch; use typed interfaces/unions/protocols instead
Use Pydantic models over dataclass/namedtuple/dict for structured data
Do not use linter suppressors — no # type: ignore, # noqa, # pyright: ignore; fix the type/code instead
Prefer list comprehensions over manual loop-and-append patterns
Use early return with guard clauses first to avoid deep nesting
Use %s for deferred interpolation in debug log statements for efficiency; use f-strings elsewhere for readability (e.g., logger.debug("Processing %s items", count) vs logger.info(f"Processing {count} items"))
Sanitize error paths by using os.path.basename() in error messages to avoid leaking directory structure
Be aware of TOCTOU (Time-Of-Check-Time-Of-Use) issues — avoid check-then-act patterns for file access and credit charging
Use transaction=True for Redis pipelines to ensure atomicity on multi-step operations
Use max(0, value) guards for computed values that should never be negative
Keep files under ~300 lines; if a file grows beyond this, split by responsibility (extract helpers, models, or a sub-module into a new file)
Keep functions under ~40 lines; extract named helpers when a function grows longer
...

Files:

  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
  • autogpt_platform/backend/backend/blocks/reddit.py
autogpt_platform/{backend,autogpt_libs}/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
  • autogpt_platform/backend/backend/blocks/reddit.py
autogpt_platform/backend/backend/blocks/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/backend/blocks/**/*.py: Inherit from 'Block' base class with input/output schemas when adding new blocks in backend
Implement 'run' method with proper error handling in backend blocks
Generate block UUID using 'uuid.uuid4()' when creating new blocks in backend
Write tests alongside block implementation when adding new blocks in backend

autogpt_platform/backend/backend/blocks/**/*.py: For blocks handling files, use store_media_file() with return_format="for_local_processing" when processing with local tools (ffmpeg, MoviePy, PIL)
For blocks handling files, use store_media_file() with return_format="for_external_api" when sending content to external APIs (Replicate, OpenAI)
For blocks returning files, use store_media_file() with return_format="for_block_output" to enable auto-adaptation to execution context (workspace:// in CoPilot, data URI in graphs)
When creating new blocks, inherit from Block base class, define input/output schemas using BlockSchema, implement async run method, and generate unique block ID using uuid.uuid4()

Files:

  • autogpt_platform/backend/backend/blocks/reddit.py
🧠 Learnings (16)
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.

Applied to files:

  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-03-05T15:42:08.207Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12297
File: .claude/skills/backend-check/SKILL.md:14-16
Timestamp: 2026-03-05T15:42:08.207Z
Learning: In Python files under autogpt_platform/backend (recursively), rely on poetry run format to perform formatting (Black + isort) and linting (ruff). Do not run poetry run lint as a separate step after poetry run format, since format already includes linting checks.

Applied to files:

  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-03-16T16:35:40.236Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/api/features/workflow_import.py:54-63
Timestamp: 2026-03-16T16:35:40.236Z
Learning: Avoid using the word 'competitor' in public-facing identifiers and text. Use neutral naming for API paths, model names, function names, and UI text. Examples: rename 'CompetitorFormat' to 'SourcePlatform', 'convert_competitor_workflow' to 'convert_workflow', '/competitor-workflow' to '/workflow'. Apply this guideline to files under autogpt_platform/backend and autogpt_platform/frontend.

Applied to files:

  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-03-31T15:37:38.626Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12623
File: autogpt_platform/backend/backend/copilot/tools/agent_generator/fixer.py:37-47
Timestamp: 2026-03-31T15:37:38.626Z
Learning: When validating/constructing Anthropic API model IDs in Significant-Gravitas/AutoGPT, allow the hyphen-separated Claude Opus 4.6 model ID `claude-opus-4-6` (it corresponds to `LlmModel.CLAUDE_4_6_OPUS` in `autogpt_platform/backend/backend/blocks/llm.py`). Do NOT require the dot-separated form in Anthropic contexts. Only OpenRouter routing variants should use the dot separator (e.g., `anthropic/claude-opus-4.6`); `claude-opus-4-6` should be treated as correct when passed to Anthropic, and flagged only if it’s used in the OpenRouter path where the dot form is expected.

Applied to files:

  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-04-15T02:43:36.890Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12780
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:0-0
Timestamp: 2026-04-15T02:43:36.890Z
Learning: When reviewing Python exception handlers, do not flag `isinstance(e, X)` checks as dead/unreachable if the caught exception `X` is a subclass of the exception type being handled. For example, if `X` (e.g., `VirusScanError`) inherits from `ValueError` (directly or via an intermediate class) and it can be raised within an `except ValueError:` block, then `isinstance(e, X)` inside that handler is reachable and should not be treated as dead code.

Applied to files:

  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-04-22T11:46:04.431Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/config.py:0-0
Timestamp: 2026-04-22T11:46:04.431Z
Learning: Do not flag the Claude Sonnet 4.6 model ID as incorrect when it uses the project’s established hyphenated convention: `anthropic/claude-sonnet-4-6`. This hyphen form is the intentional, production convention and should be treated as valid (including in files like llm.py, blocks tests, reasoning.py, `_is_anthropic_model` tests, and config defaults). Note that OpenRouter also accepts the dot variant `anthropic/claude-sonnet-4.6`, so either form may be tolerated, but `anthropic/claude-sonnet-4-6` should be considered the standard to match project usage.

Applied to files:

  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-04-22T11:46:12.892Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/baseline/service.py:322-332
Timestamp: 2026-04-22T11:46:12.892Z
Learning: In this codebase (Significant-Gravitas/AutoGPT), OpenRouter-routed Anthropic model IDs should use the hyphen-separated convention (e.g., `anthropic/claude-sonnet-4-6`, `anthropic/claude-opus-4-6`). Although OpenRouter may accept both hyphen and dot variants, treat the hyphen-separated form as the intended, correct codebase-wide convention and do not flag it as an error. Only flag the dot-separated variant (e.g., `anthropic/claude-sonnet-4.6`) as incorrect when reviewing/validating model ID strings for OpenRouter-routed Anthropic models.

Applied to files:

  • autogpt_platform/backend/backend/integrations/oauth/reddit.py
  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Inherit from 'Block' base class with input/output schemas when adding new blocks in backend

Applied to files:

  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Write tests alongside block implementation when adding new blocks in backend

Applied to files:

  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-04-08T17:28:23.439Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/AGENTS.md:0-0
Timestamp: 2026-04-08T17:28:23.439Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : When creating new blocks, inherit from `Block` base class, define input/output schemas using `BlockSchema`, implement async `run` method, and generate unique block ID using `uuid.uuid4()`

Applied to files:

  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-02-05T04:11:00.596Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11796
File: autogpt_platform/backend/backend/blocks/video/concat.py:3-4
Timestamp: 2026-02-05T04:11:00.596Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, when creating a new block, generate a UUID once with uuid.uuid4() and hard-code the resulting string as the block's id parameter. Do not call uuid.uuid4() at runtime; IDs must be constant across all imports and runs to ensure stability.

Applied to files:

  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-03-16T16:32:21.686Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/pods.py:62-74
Timestamp: 2026-03-16T16:32:21.686Z
Learning: In autogpt_platform/backend/backend/blocks/, the Block base class execute() already wraps run() in a try/except to convert uncaught exceptions into BlockExecutionError/BlockUnknownError. Do not add per-block try/except in individual block run() methods, as this is not the established pattern (e.g., Gmail, Slack, Todoist blocks omit it). Only use explicit try/except within blocks that need to distinguish between success and error yield paths inside a generator (e.g., attachment blocks). This guidance applies to all Python files under autogpt_platform/backend/backend/blocks/ and similar block implementations; avoid duplicating error handling in run() unless a block requires generator-based branching.

Applied to files:

  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-04-23T12:55:26.122Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12893
File: autogpt_platform/backend/backend/blocks/ayrshare/post_to_tiktok.py:24-24
Timestamp: 2026-04-23T12:55:26.122Z
Learning: Cost billing via the cost(*costs) decorator is applied at input-evaluation time (before a block’s run() executes). Therefore, mutating input_data inside run() will not change billing. When a block’s billing depends on a field plus URL/sniff-derived signals, treat the explicitly declared billing field (e.g., is_video) as the only billing source—set it correctly before run() (or in the code path that occurs before the decorator evaluates input_data). This should be checked for all blocks under autogpt_platform/backend/backend/blocks/ so billing signals are not mistakenly assumed to update during run().

Applied to files:

  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-03-16T16:30:11.452Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:11.452Z
Learning: In autogpt_platform/backend/backend/blocks/ (and related blocks under autogpt_platform/backend/backend/blocks/), do not add try/except blocks around a block's run() method for standard error propagation. The block executor framework (backend/executor/manager.py) catches uncaught exceptions from run() and emits them on the 'error' output. Only add explicit try/except blocks when you need to control partial outputs in failure cases (e.g., certain outputs must not be yielded on error, as in attachment blocks). This is the standard pattern across the codebase; apply it broadly to blocks' run() implementations.

Applied to files:

  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-03-16T16:30:23.196Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/pods.py:62-74
Timestamp: 2026-03-16T16:30:23.196Z
Learning: In any Python file under autogpt_platform/backend/backend/blocks, do not add a try/except around run() solely for standard error handling. The block framework’s _execute() in _base.py already catches unhandled exceptions and re-raises as BlockExecutionError or BlockUnknownError. If you yield ("error", message), _execute() raises BlockExecutionError immediately, so the error port will not propagate downstream. Reserve explicit try/except for scenarios where you must control partial output (e.g., attachment blocks that must skip yielding content_base64 on failure).

Applied to files:

  • autogpt_platform/backend/backend/blocks/reddit.py
📚 Learning: 2026-03-16T16:30:11.452Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:11.452Z
Learning: Do not wrap synchronous AgentMail SDK calls with asyncio.to_thread() in blocks under autogpt_platform/backend/backend/blocks (and across the codebase). The block executor runs node execution in dedicated threads via asyncio.run_coroutine_threadsafe (see manager.py around lines ~745-752 and ~1079). The existing pattern avoids using asyncio.to_thread for SDK calls inside async run() methods, so maintain that approach and do not add to_thread usage in these code paths.

Applied to files:

  • autogpt_platform/backend/backend/blocks/reddit.py
🔇 Additional comments (1)
autogpt_platform/backend/backend/blocks/reddit.py (1)

2567-2573: No review comment was provided within <review_comment> tags. Please provide the review comment that needs to be rewritten.

Comment thread autogpt_platform/backend/backend/blocks/reddit.py Outdated
Comment thread autogpt_platform/backend/backend/blocks/reddit.py Outdated
Comment thread autogpt_platform/backend/backend/integrations/oauth/reddit.py Outdated
ntindle and others added 2 commits April 29, 2026 15:18
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Apr 29, 2026
@github-actions

github-actions Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

🔍 PR Overlap Detection

This check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early.

⚠️ This PR has conflicts with the base branch

Conflicts will need to be resolved before merging:

🟢 Low Risk — File Overlap Only

These PRs touch the same files but different sections (click to expand)

Summary: 1 conflict(s), 0 medium risk, 4 low risk (out of 5 PRs with file overlap)


Auto-generated on push. Ignores: openapi.json, lock files.

Comment thread autogpt_platform/backend/backend/integrations/oauth/reddit.py Outdated

@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.

Actionable comments posted: 14

🧹 Nitpick comments (1)
docs/integrations/block-integrations/misc.md (1)

855-858: Minor wording/style nit in Mod Queue input description (“only” repetition).

Static analysis flags adverb repetition: “Filter to only submissions or only comments.” Consider simplifying to something like “Filter to submissions or comments; leave blank for both.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/integrations/block-integrations/misc.md` around lines 855 - 858, Update
the description for the "only" parameter in the Mod Queue table to remove the
adverb repetition; replace "Filter to only submissions or only comments. Leave
blank for both." with a concise phrasing such as "Filter to submissions or
comments; leave blank for both." Ensure you modify the row for the "only" field
in the Mod Queue inputs so the table reflects the new text.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/integrations/block-integrations/misc.md`:
- Around line 1394-1398: Replace the placeholder between the use_case manual
tags with exactly three bold, one-sentence examples describing practical uses of
"Unban Subreddit User"; update the content inside <!-- MANUAL: use_case --> ...
<!-- END MANUAL --> to contain three lines each starting with ** and ending with
**, each a single sentence (no extra headings or bullets) that illustrate
distinct scenarios for unbanning a subreddit user.
- Around line 1057-1061: Replace the placeholder comment <!-- MANUAL: use_case
--> with exactly three bold, one-sentence use-case entries for "Remove Reddit
Post" (each entry should be a bold heading followed by a single sentence
description); ensure there are exactly three lines, each starting with bold text
(e.g., **Remove Reddit Post — ...**) and no additional paragraphs, markup, or
extra sentences beyond those three one-sentence descriptions.
- Around line 1245-1249: Replace the placeholder MANUAL block labeled use_case
under the "Send Mod Mail" section with exactly three bold, one-sentence use-case
lines; each line should be a bold heading (e.g., **Use Case 1: ...**) followed
by a single sentence describing the scenario, ensuring there are exactly three
such bold one-sentence examples and no additional text or formatting.
- Around line 872-875: Replace the placeholder manual block labeled use_case
under the "Mod Queue" section with exactly three bold, one-sentence examples;
locate the <!-- MANUAL: use_case --> ... <!-- END MANUAL --> block and replace
the single-line "_Add practical use case examples here._" with three separate
bold sentences (each sentence should be one line, wrapped in markdown bold
markers) that are concrete Mod Queue use cases.
- Around line 834-837: Replace the placeholder MANUAL block named use_case with
exactly three bold, one-sentence use case lines for "Lock Reddit Post": create
three separate bold headings (e.g., **Prevent comment spam:**) each followed by
a single sentence describing the scenario and outcome (no extra sentences or
bullets), ensuring the content replaces the <!-- MANUAL: use_case --> ... <!--
END MANUAL --> block exactly and uses the phrase "Lock Reddit Post" as the
subject in at least one of the examples.
- Around line 66-68: Replace the placeholder inside the <!-- MANUAL: use_case
--> block for the "Approve Reddit Post" integration with exactly three bold,
one-sentence use-case entries; each entry must be a bold heading (e.g., **Use
case title.**) followed immediately by one sentence describing the workflow, no
additional lines or paragraphs, and no extra formatting or commentary beyond the
three bold one-sentence examples.
- Around line 151-154: Replace the placeholder block between <!-- MANUAL:
use_case --> and <!-- END MANUAL --> under the "Possible use case" heading with
exactly three bold, one-sentence examples for "Ban Subreddit User" (each example
must be a single sentence and formatted as a bold heading), e.g., cover a
temporary ban workflow, a permanent ban workflow, and a ban with an optional
moderator note; ensure there are exactly three bold lines and no additional
paragraphs or placeholders.
- Around line 1373-1377: Replace the placeholder under the "How it works"
section for "Unban Subreddit User" (the <!-- MANUAL: how_it_works --> block)
with 1–2 concise paragraphs explaining the workflow: describe that the action
calls Reddit's unban endpoint, verifies moderator permissions and subreddit
existence, and updates subreddit ban lists; include validation/error handling
and edge cases (e.g., user not found, user not banned, insufficient moderator
permissions, rate limits, API failures, and idempotency). Add a short
backtick-enclosed code example showing the expected request/response pattern (no
implementation code, just request payload and sample response) and ensure the
text references validation steps (validate subreddit and moderator, check user
ban status) and what errors are returned for each edge case.
- Around line 1223-1227: Replace the placeholder in the `how_it_works` manual
block for the "Send Mod Mail" integration with 1–2 concise paragraphs describing
the processing logic (how incoming mod-mail requests are parsed, routed to
moderators, stored, and threaded), list validation/error-handling/edge cases
(e.g., missing subject/body, invalid recipient/moderator IDs, rate limits, spam
detection, message delivery failures and retry behavior), and include at least
one inline code example using backticks showing the request payload or calling
pattern (for example: `POST /modmail { "subject": "...", "body": "..." }`).
Ensure the block between `<!-- MANUAL: how_it_works -->` and `<!-- END MANUAL
-->` is updated and references "Send Mod Mail" explicitly.
- Around line 1036-1040: Replace the placeholder under the "How it works"
section for the "Remove Reddit Post" block with 1–2 concise paragraphs
describing the processing flow: locate the post by id, call Reddit's removal
API, and update moderation metadata; explicitly document how the `spam` boolean
toggles removal type (spam vs normal remove) and how `mod_note` is recorded in
the moderation history/metadata. Also include validation/error-handling details
and edge cases: validate required inputs (post id), handle permission/API
failures, rate limits, already-removed posts, and state what the block returns
on success vs failure (e.g., success metadata and a populated `error` object on
failure with HTTP/status and message). Finally add a short backtick code example
showing input JSON/parameters and expected success/failure response structure
that includes `error`, `spam`, and `mod_note`.
- Around line 846-849: Replace the placeholder between <!-- MANUAL: how_it_works
--> and <!-- END MANUAL --> for the "Mod Queue" section with 1–2 concise
paragraphs that describe the processing logic (how items are queued,
prioritized, and marked resolved), validation and error handling (e.g., input
schema checks, responses on malformed requests, retry/poison‑queue behavior),
and edge cases such as pagination/limit semantics and whether filters are
applied as "only" vs "both" (AND vs OR). Also include a short backtick code
example showing how to fetch a paginated page (e.g., request with limit and
cursor) and note expected responses for empty pages or invalid cursors; update
the manual block content in place (the <!-- MANUAL: how_it_works --> block) for
"Mod Queue".
- Around line 125-128: Replace the placeholder between <!-- MANUAL: how_it_works
--> and <!-- END MANUAL --> with 1–2 paragraphs that describe the Ban Subreddit
User flow: validate incoming parameters (target user id, moderator scope,
subreddit id, optional duration), call the ban operation (mention the operation
name "Ban Subreddit User" or integration block if present), and persist/emit
events; explicitly state that duration = None means a permanent ban while a
provided duration creates a temporary ban that will be unbanned after expiry;
add a short “Validation and errors” section listing common failures
(missing/invalid scope or moderator permissions -> return 403/insufficient_scope
error, missing subreddit id or user id -> 400/invalid_request, invalid duration
format -> 400, backend failures -> 5xx) and note edge cases (user already
banned, concurrent unban/ban races); include a minimal backtick code example
demonstrating calling the ban with and without duration (one example showing
duration=None for permanent ban and one showing a numeric/time duration) and
show expected success and error responses.
- Around line 47-49: Replace the `<!-- MANUAL: how_it_works -->` placeholder in
the "Approve Reddit Post" block with 1–2 concise technical paragraphs explaining
the processing logic (mention the modposts behavior: fetching the post,
verifying mod permissions, approving via API, and updating state), explicitly
document validation, error handling and edge cases (e.g., missing/404 posts,
insufficient mod scope, rate-limits, API failures, idempotency and retries), and
include at least one inline code example wrapped in backticks showing the core
operation (for example `reddit.mod.approve(postId)` or the request/response
shape) to meet docs guidelines.
- Around line 814-817: Replace the placeholder in the how_it_works manual block
for "Lock Reddit Post" with a 1–2 paragraph technical explanation describing the
action (call to Reddit API endpoint to set post.locked=true via /api/lock or
PRAW equivalent), include required request flow (authentication, subreddit
moderation scope, ID/thing_id vs fullname), and expected side effects (prevents
new comments but preserves existing ones). Add a validation and error-handling
section that lists edge cases and checks: verify moderator scope/permissions,
ensure the target is a post (not comment), handle rate-limit (429), 401/403 auth
failures, 404 missing post, and include retry/backoff or user-facing error
messages. Finally include a short backtick-enclosed code example showing the
minimal request or PRAW call (e.g., reddit.submission(id).mod.lock())
demonstrating required parameters and basic try/catch handling.

---

Nitpick comments:
In `@docs/integrations/block-integrations/misc.md`:
- Around line 855-858: Update the description for the "only" parameter in the
Mod Queue table to remove the adverb repetition; replace "Filter to only
submissions or only comments. Leave blank for both." with a concise phrasing
such as "Filter to submissions or comments; leave blank for both." Ensure you
modify the row for the "only" field in the Mod Queue inputs so the table
reflects the new text.
🪄 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

Run ID: 8772be04-d5ff-4378-8efa-5f2b796e4dfa

📥 Commits

Reviewing files that changed from the base of the PR and between 34608a2 and da120dd.

📒 Files selected for processing (2)
  • docs/integrations/README.md
  • docs/integrations/block-integrations/misc.md
✅ Files skipped from review due to trivial changes (1)
  • docs/integrations/README.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: end-to-end tests
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.13)
  • GitHub Check: Check PR Status
  • GitHub Check: Cursor Bugbot
🧰 Additional context used
📓 Path-based instructions (1)
docs/integrations/**/*.md

📄 CodeRabbit inference engine (docs/AGENTS.md)

docs/integrations/**/*.md: Block documentation how_it_works manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks
Block documentation use_case manual section should provide exactly 3 practical use cases in bold heading format with short one-sentence descriptions
Documentation descriptions should be concise and action-oriented, focusing on practical real-world scenarios with consistent terminology and avoiding overly technical jargon

Files:

  • docs/integrations/block-integrations/misc.md
🧠 Learnings (2)
📚 Learning: 2026-03-08T23:28:21.675Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12334
File: docs/integrations/block-integrations/github/repo.md:11-40
Timestamp: 2026-03-08T23:28:21.675Z
Learning: In Significant-Gravitas/AutoGPT, new GitHub block documentation stubs in `docs/integrations/block-integrations/github/` are auto-generated by a docs script with placeholder text (`_Add technical explanation here._` / `_Add practical use case examples here._`) inside `<!-- MANUAL: how_it_works

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-04-08T17:29:01.000Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: docs/AGENTS.md:0-0
Timestamp: 2026-04-08T17:29:01.000Z
Learning: Applies to docs/integrations/**/*.md : Block documentation `how_it_works` manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks

Applied to files:

  • docs/integrations/block-integrations/misc.md
🪛 LanguageTool
docs/integrations/block-integrations/misc.md

[style] ~857-~857: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...d queue | int | No | | only | Filter to only submissions or only comments. Leave bla...

(ADVERB_REPETITION_PREMIUM)

Comment thread docs/integrations/block-integrations/misc.md
Comment thread docs/integrations/block-integrations/misc.md
Comment thread docs/integrations/block-integrations/misc.md
Comment thread docs/integrations/block-integrations/misc.md
Comment thread docs/integrations/block-integrations/misc.md
Comment thread docs/integrations/block-integrations/misc.md
Comment thread docs/integrations/block-integrations/misc.md
Comment thread docs/integrations/block-integrations/misc.md
Comment thread docs/integrations/block-integrations/misc.md
Comment thread docs/integrations/block-integrations/misc.md
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the platform/frontend AutoGPT Platform - Front end label Apr 29, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@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.

Actionable comments posted: 1

♻️ Duplicate comments (5)
docs/integrations/block-integrations/misc.md (5)

47-51: 🛠️ Refactor suggestion | 🟠 Major

Add validation/error handling documentation and code examples to meet coding guidelines.

The how_it_works section explains the processing flow but is missing required elements per coding guidelines:

  • Validation/error handling/edge cases: Document what happens when the post is not found, insufficient moderator permissions, already approved posts, rate limits, or API failures.
  • Code examples with backticks: Include at least one inline code example showing the core operation, e.g., thing.mod.approve() or a sample request/response pattern.

As per coding guidelines: Block documentation how_it_works manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/integrations/block-integrations/misc.md` around lines 47 - 51, Expand
the "how_it_works" section to two concise paragraphs: first describe the flow
(normalize `post_id` to a Reddit fullname, load PRAW object for
submission/comment and call the moderator `approve()` action using credentials
with the `modposts` scope, e.g. `thing.mod.approve()`), and second list
validation and error-handling/edge cases (post not found, insufficient moderator
permissions, already approved items, API rate limits, network/API failures) and
describe returned values (`post_id` and `success=True` on success) and error
behavior (what error object or status is returned or exceptions raised). Also
add one inline code example and one sample request/response pattern using
backticks (for example `thing.mod.approve()` and a brief
`{"post_id":"t3_...","success":true}` response) to comply with coding
guidelines.

865-869: 🛠️ Refactor suggestion | 🟠 Major

Add validation/error handling documentation and code examples to meet coding guidelines.

The how_it_works section should include:

  • Validation/error handling/edge cases: Document what happens with invalid subreddits, permission failures, empty queues, pagination limits, rate limits, and invalid only filter values.
  • Code examples with backticks: Include a short example showing sub.mod.modqueue(limit=..., only=...) or the request/response pattern.

As per coding guidelines: Block documentation how_it_works manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/integrations/block-integrations/misc.md` around lines 865 - 869, Update
the "how_it_works" manual to add 1–2 technical paragraphs describing processing,
validation and error-handling: state that the block calls
sub.mod.modqueue(limit=..., only=...) via PRAW, normalizes each returned item
into a dict with fullname ID, detected type, title fallback, author, permalink,
moderator reason, emits each item individually and the full items list, and
preserves post_id as the Reddit fullname; then explicitly document edge cases
and validation: behavior for invalid subreddit names, permission failures (API
403), empty queues, pagination/rate-limit handling and retry/backoff, invalid
only filter values (validation + error response), and how limit is respected;
finally add a short inline code example using backticks showing the call pattern
`sub.mod.modqueue(limit=10, only="modqueue")` and a brief example response shape
mentioning `post_id` and `items` so readers can see expected inputs/outputs.

827-831: 🛠️ Refactor suggestion | 🟠 Major

Add validation/error handling documentation and code examples to meet coding guidelines.

The how_it_works section needs:

  • Validation/error handling/edge cases: Document permission failures, post not found errors, rate limits, API failures, and what happens when locking an already locked post or unlocking an unlocked post.
  • Code examples with backticks: Include an inline example showing thing.lock() or thing.unlock() with the required scope.

As per coding guidelines: Block documentation how_it_works manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/integrations/block-integrations/misc.md` around lines 827 - 831, Update
the `how_it_works` manual block to be 1–2 technical paragraphs that explain how
the block resolves `post_id` to a Reddit object (submission or comment), then
calls `lock()` when `lock=True` or `unlock()` when `lock=False` using moderator
credentials with the `modposts` scope, and that it returns the original
`post_id` plus the resulting `locked` state. Add a short "Validation / error
handling / edge cases" subsection that documents permission failures
(insufficient `modposts` scope), post-not-found errors, rate-limit responses,
generic API failures, and idempotent behavior when trying to lock an
already-locked post or unlock an already-unlocked post. Finally include inline
code examples using backticks (e.g., `thing.lock()` / `thing.unlock()` and
mention `modposts`) demonstrating expected usage and how errors are surfaced.

132-136: 🛠️ Refactor suggestion | 🟠 Major

Expand validation documentation and add code examples to meet coding guidelines.

While the section mentions duration validation and truncation limits, it's missing:

  • Error handling: Document what happens on permission failures, invalid usernames, API errors, or when the user is already banned.
  • Edge cases: Cover rate limits, concurrent ban/unban operations, and invalid duration values.
  • Code examples with backticks: Include a short example showing sub.banned.add(...) with sample parameters.

As per coding guidelines: Block documentation how_it_works manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/integrations/block-integrations/misc.md` around lines 132 - 136, Expand
the MANUAL `how_it_works` block into 1-2 concise paragraphs that explain the
block's processing: validate `duration` (reject non-positive/invalid values),
truncate `reason` and `mod_note` to Reddit limits, and call
`sub.banned.add(...)` optionally with a temporary `duration` and `ban_message`;
mention outputs `success` and derived `permanent`. Add a short paragraph
describing error handling and edge cases: permission failures, invalid
usernames, API errors, already-banned users, rate limits, and concurrent
ban/unban races and how the block surfaces or retries errors. Finally, include a
small inline code example using backticks that shows a sample
`sub.banned.add(...)` call with `duration`, `reason`, `mod_note`, and
`ban_message` parameters.

1061-1065: 🛠️ Refactor suggestion | 🟠 Major

Add comprehensive error handling documentation and code examples to meet coding guidelines.

While the section mentions mod_note truncation, it needs:

  • Error handling/edge cases: Document permission failures, post not found errors, already removed posts, rate limits, API failures, and idempotency behavior.
  • Code examples with backticks: Include an inline example showing thing.mod.remove(spam=..., mod_note=...) with sample parameters.

As per coding guidelines: Block documentation how_it_works manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/integrations/block-integrations/misc.md` around lines 1061 - 1065,
Expand the "how_it_works" manual to 1–2 concise paragraphs that describe
processing: resolve bare IDs or full Reddit thing IDs to submission/comment
objects, call thing.mod.remove(...) forwarding the spam flag, truncate mod_note
to 250 chars, and return post_id plus success flag; add explicit validation and
error-handling/edge-case notes covering permission failures, post-not-found,
already-removed (idempotency), rate limits and API failures, and how failures
are surfaced; and include an inline code example using backticks such as
`thing.mod.remove(spam=True, mod_note="...")` showing sample parameters and
expected return shape (post_id, success).
🧹 Nitpick comments (2)
docs/integrations/block-integrations/misc.md (2)

1254-1258: Consider adding validation and edge case details.

The section includes a code example and mentions error handling, which is good. To fully meet coding guidelines, consider explicitly documenting:

  • Validation: What happens with empty subject/body, invalid usernames, or non-existent subreddits.
  • Edge cases: Rate limits, users who have blocked modmail, permission failures, and concurrent modmail operations.

As per coding guidelines: Block documentation how_it_works manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/integrations/block-integrations/misc.md` around lines 1254 - 1258,
Update the `how_it_works` manual paragraph for the block that calls
`sub.modmail.create(...)` to explicitly document input validation and edge
cases: state behavior when subject/body are empty, when recipient usernames are
invalid or blocked, and when the target subreddit does not exist or the
credential lacks moderator/modmail scope; explain how API errors are surfaced
via the `error` output and that on success the block returns the conversation ID
and `success=True`; mention operational edge cases (rate limits, permission
failures, users who have blocked modmail, and concurrent modmail operations) and
how the block responds to them (retry/backoff or immediate error); keep content
to 1–2 paragraphs and include short inline code examples in backticks for the
`sub.modmail.create(...)` call and the `success=True`/`error` outputs.

877-877: Rephrase to avoid awkward repetition.

The description "Filter to only submissions or only comments" repeats "only" twice. Consider rephrasing to "Limit to submissions or comments only" or "Filter by submissions or comments."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/integrations/block-integrations/misc.md` at line 877, Replace the table
cell text "Filter to only submissions or only comments." with a clearer phrasing
such as "Filter by submissions or comments" or "Limit to submissions or comments
only" (i.e., update the string present in the table row labeled "only" that
currently contains "Filter to only submissions or only comments."). Ensure the
new wording keeps the meaning and fits the existing markdown table formatting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/integrations/block-integrations/misc.md`:
- Around line 1410-1414: Update the "how_it_works" manual for the block to add
1–2 concise technical paragraphs explaining processing: that the block opens the
subreddit with moderator credentials and calls sub.banned.remove(username) to
unban, and that it returns username, subreddit, and success=True on success;
then explicitly document validation and error handling for invalid or malformed
username, user-not-banned, nonexistent subreddit, and insufficient permissions
(include expected error types/messages to surface), and enumerate edge cases
such as API rate limits, transient API failures/retries, concurrent unban
attempts and idempotency (calling remove on an already-unbanned user should be a
no-op/success), and suggest recommended retry/backoff behavior and
logging/notification points for auditability.

---

Duplicate comments:
In `@docs/integrations/block-integrations/misc.md`:
- Around line 47-51: Expand the "how_it_works" section to two concise
paragraphs: first describe the flow (normalize `post_id` to a Reddit fullname,
load PRAW object for submission/comment and call the moderator `approve()`
action using credentials with the `modposts` scope, e.g. `thing.mod.approve()`),
and second list validation and error-handling/edge cases (post not found,
insufficient moderator permissions, already approved items, API rate limits,
network/API failures) and describe returned values (`post_id` and `success=True`
on success) and error behavior (what error object or status is returned or
exceptions raised). Also add one inline code example and one sample
request/response pattern using backticks (for example `thing.mod.approve()` and
a brief `{"post_id":"t3_...","success":true}` response) to comply with coding
guidelines.
- Around line 865-869: Update the "how_it_works" manual to add 1–2 technical
paragraphs describing processing, validation and error-handling: state that the
block calls sub.mod.modqueue(limit=..., only=...) via PRAW, normalizes each
returned item into a dict with fullname ID, detected type, title fallback,
author, permalink, moderator reason, emits each item individually and the full
items list, and preserves post_id as the Reddit fullname; then explicitly
document edge cases and validation: behavior for invalid subreddit names,
permission failures (API 403), empty queues, pagination/rate-limit handling and
retry/backoff, invalid only filter values (validation + error response), and how
limit is respected; finally add a short inline code example using backticks
showing the call pattern `sub.mod.modqueue(limit=10, only="modqueue")` and a
brief example response shape mentioning `post_id` and `items` so readers can see
expected inputs/outputs.
- Around line 827-831: Update the `how_it_works` manual block to be 1–2
technical paragraphs that explain how the block resolves `post_id` to a Reddit
object (submission or comment), then calls `lock()` when `lock=True` or
`unlock()` when `lock=False` using moderator credentials with the `modposts`
scope, and that it returns the original `post_id` plus the resulting `locked`
state. Add a short "Validation / error handling / edge cases" subsection that
documents permission failures (insufficient `modposts` scope), post-not-found
errors, rate-limit responses, generic API failures, and idempotent behavior when
trying to lock an already-locked post or unlock an already-unlocked post.
Finally include inline code examples using backticks (e.g., `thing.lock()` /
`thing.unlock()` and mention `modposts`) demonstrating expected usage and how
errors are surfaced.
- Around line 132-136: Expand the MANUAL `how_it_works` block into 1-2 concise
paragraphs that explain the block's processing: validate `duration` (reject
non-positive/invalid values), truncate `reason` and `mod_note` to Reddit limits,
and call `sub.banned.add(...)` optionally with a temporary `duration` and
`ban_message`; mention outputs `success` and derived `permanent`. Add a short
paragraph describing error handling and edge cases: permission failures, invalid
usernames, API errors, already-banned users, rate limits, and concurrent
ban/unban races and how the block surfaces or retries errors. Finally, include a
small inline code example using backticks that shows a sample
`sub.banned.add(...)` call with `duration`, `reason`, `mod_note`, and
`ban_message` parameters.
- Around line 1061-1065: Expand the "how_it_works" manual to 1–2 concise
paragraphs that describe processing: resolve bare IDs or full Reddit thing IDs
to submission/comment objects, call thing.mod.remove(...) forwarding the spam
flag, truncate mod_note to 250 chars, and return post_id plus success flag; add
explicit validation and error-handling/edge-case notes covering permission
failures, post-not-found, already-removed (idempotency), rate limits and API
failures, and how failures are surfaced; and include an inline code example
using backticks such as `thing.mod.remove(spam=True, mod_note="...")` showing
sample parameters and expected return shape (post_id, success).

---

Nitpick comments:
In `@docs/integrations/block-integrations/misc.md`:
- Around line 1254-1258: Update the `how_it_works` manual paragraph for the
block that calls `sub.modmail.create(...)` to explicitly document input
validation and edge cases: state behavior when subject/body are empty, when
recipient usernames are invalid or blocked, and when the target subreddit does
not exist or the credential lacks moderator/modmail scope; explain how API
errors are surfaced via the `error` output and that on success the block returns
the conversation ID and `success=True`; mention operational edge cases (rate
limits, permission failures, users who have blocked modmail, and concurrent
modmail operations) and how the block responds to them (retry/backoff or
immediate error); keep content to 1–2 paragraphs and include short inline code
examples in backticks for the `sub.modmail.create(...)` call and the
`success=True`/`error` outputs.
- Line 877: Replace the table cell text "Filter to only submissions or only
comments." with a clearer phrasing such as "Filter by submissions or comments"
or "Limit to submissions or comments only" (i.e., update the string present in
the table row labeled "only" that currently contains "Filter to only submissions
or only comments."). Ensure the new wording keeps the meaning and fits the
existing markdown table formatting.
🪄 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

Run ID: f729ad12-fd3e-4634-a86a-f20a4f4fb0f7

📥 Commits

Reviewing files that changed from the base of the PR and between 750abdf and 6849c68.

📒 Files selected for processing (1)
  • docs/integrations/block-integrations/misc.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: check API types
  • GitHub Check: integration_test
  • GitHub Check: lint
  • GitHub Check: end-to-end tests
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.13)
  • GitHub Check: type-check (3.11)
  • GitHub Check: type-check (3.12)
  • GitHub Check: type-check (3.13)
  • GitHub Check: test (3.11)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (1)
docs/integrations/**/*.md

📄 CodeRabbit inference engine (docs/AGENTS.md)

docs/integrations/**/*.md: Block documentation how_it_works manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks
Block documentation use_case manual section should provide exactly 3 practical use cases in bold heading format with short one-sentence descriptions
Documentation descriptions should be concise and action-oriented, focusing on practical real-world scenarios with consistent terminology and avoiding overly technical jargon

Files:

  • docs/integrations/block-integrations/misc.md
🧠 Learnings (13)
📚 Learning: 2026-03-08T23:28:21.675Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12334
File: docs/integrations/block-integrations/github/repo.md:11-40
Timestamp: 2026-03-08T23:28:21.675Z
Learning: In Significant-Gravitas/AutoGPT, new GitHub block documentation stubs in `docs/integrations/block-integrations/github/` are auto-generated by a docs script with placeholder text (`_Add technical explanation here._` / `_Add practical use case examples here._`) inside `<!-- MANUAL: how_it_works

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-04-08T17:29:01.000Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: docs/AGENTS.md:0-0
Timestamp: 2026-04-08T17:29:01.000Z
Learning: Applies to docs/integrations/**/*.md : Block documentation `how_it_works` manual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-04-08T17:29:01.000Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: docs/AGENTS.md:0-0
Timestamp: 2026-04-08T17:29:01.000Z
Learning: Applies to docs/integrations/**/*.md : Block documentation `use_case` manual section should provide exactly 3 practical use cases in bold heading format with short one-sentence descriptions

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-04-08T17:26:28.252Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/frontend/src/tests/CLAUDE.md:0-0
Timestamp: 2026-04-08T17:26:28.252Z
Learning: Applies to autogpt_platform/frontend/src/tests/**/AGENTS.md : Include clear usage examples in AGENTS.md for each agent to facilitate integration and reduce onboarding time

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-04-08T17:29:01.000Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: docs/AGENTS.md:0-0
Timestamp: 2026-04-08T17:29:01.000Z
Learning: Applies to docs/integrations/**/*.md : Documentation descriptions should be concise and action-oriented, focusing on practical real-world scenarios with consistent terminology and avoiding overly technical jargon

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-04-07T10:12:18.517Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12691
File: .claude/skills/orchestrate/SKILL.md:0-0
Timestamp: 2026-04-07T10:12:18.517Z
Learning: In Significant-Gravitas/AutoGPT's Claude skill markdown files under `.claude/skills/orchestrate/`, fenced code blocks in `SKILL.md`-style skill documents may intentionally omit a fenced code language (no `text`, `bash`, etc.). These blocks are used for Claude Code inline pseudocode/conceptual helpers rather than runnable scripts. During reviews, avoid treating MD040 (fenced-code-language) as an issue for these specific skill-format blocks, even if the language identifier is missing, since this omission is expected and has been accepted as a false positive for this skill format.

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-03-17T10:57:12.953Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/copilot/workflow_import/converter.py:0-0
Timestamp: 2026-03-17T10:57:12.953Z
Learning: In Significant-Gravitas/AutoGPT PR `#12440`, `autogpt_platform/backend/backend/copilot/workflow_import/converter.py` was fully rewritten (commit 732960e2d) to no longer make direct LLM/OpenAI API calls. The converter now builds a structured text prompt for AutoPilot/CoPilot instead. There is no `response.choices` access or any direct LLM client usage in this file. Do not flag `response.choices` access or LLM client initialization patterns as issues in this file.

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-04-22T05:58:31.684Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12879
File: autogpt_platform/frontend/src/app/api/openapi.json:14576-14577
Timestamp: 2026-04-22T05:58:31.684Z
Learning: Repo: Significant-Gravitas/AutoGPT — autogpt_platform
Process convention: When adding new CoPilot tool response models and updating ToolResponseUnion in backend/api/features/chat/routes.py, regenerate the frontend OpenAPI schema via `poetry run export-api-schema` (do not hand-edit autogpt_platform/frontend/src/app/api/openapi.json).

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-03-27T09:36:59.358Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12591
File: .claude/skills/setup-repo/SKILL.md:32-33
Timestamp: 2026-03-27T09:36:59.358Z
Learning: In the Significant-Gravitas/AutoGPT repository, bash code blocks inside `.claude/skills/*/SKILL.md` files are illustrative guidance patterns for AI agents to adapt, not directly executable scripts. Code correctness standards (e.g., regex safety, error handling) for these snippets should be evaluated against their role as intent-communicating documentation rather than production code.

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-03-04T23:58:18.476Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12284
File: autogpt_platform/frontend/src/app/api/openapi.json:11897-11900
Timestamp: 2026-03-04T23:58:18.476Z
Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12284`
Backend/frontend OpenAPI codegen convention: In backend/api/features/store/model.py, the StoreSubmission and StoreSubmissionAdminView models define submitted_at: datetime | None, changes_summary: str | None, and instructions: str | None with no default. This is intentional to produce “required but nullable” fields in OpenAPI (properties appear in required[] and use anyOf [type, null]). This matches Prisma’s submittedAt DateTime? and changesSummary String?. Do not flag this as a required/nullable mismatch.

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-03-24T21:25:15.983Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12536
File: autogpt_platform/frontend/src/app/api/openapi.json:5770-5790
Timestamp: 2026-03-24T21:25:15.983Z
Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12536`
File: autogpt_platform/frontend/src/app/api/openapi.json
Learning: The OpenAPI spec file is auto-generated; per established convention, endpoints generally declare only 200/201, 401, and 422 responses. Do not suggest adding explicit 403/404 response entries for single operations unless planning a repo-wide spec update. Prefer clarifying such behaviors in endpoint descriptions/docstrings instead of altering response maps.

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-02-27T15:59:00.370Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/api/openapi.json:9983-9995
Timestamp: 2026-02-27T15:59:00.370Z
Learning: Repo: Significant-Gravitas/AutoGPT PR: 12213 — Backend/frontend OpenAPI codegen
Learning: For MCP schema models, required OpenAPI fields must have no defaults in Pydantic. Specifically, MCPToolInfo.input_schema must be required (no Field(default_factory=dict)) so openapi.json emits it in "required", ensuring generated TS types treat input_schema as non-optional.

Applied to files:

  • docs/integrations/block-integrations/misc.md
📚 Learning: 2026-02-27T15:59:00.370Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/api/openapi.json:9983-9995
Timestamp: 2026-02-27T15:59:00.370Z
Learning: Repo: Significant-Gravitas/AutoGPT PR: 12213 — OpenAPI/codegen
Learning: Ensuring a field is required in generated TS types needs two sides: (1) no default value on the Pydantic field, and (2) the OpenAPI model's "required" array must list it. For MCPToolInfo, making input_schema required in OpenAPI and removing Field(default_factory=dict) in the backend prevents optional typing drift.

Applied to files:

  • docs/integrations/block-integrations/misc.md
🪛 LanguageTool
docs/integrations/block-integrations/misc.md

[style] ~877-~877: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...d queue | int | No | | only | Filter to only submissions or only comments. Leave bla...

(ADVERB_REPETITION_PREMIUM)

Comment thread docs/integrations/block-integrations/misc.md
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ntindle

ntindle commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

Copy link
Copy Markdown

Queued a review for PR #12945 at 2e87cb8.

@autogpt-pr-reviewer autogpt-pr-reviewer 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.

INCONCLUSIVE

You've hit your session limit · resets 9am (UTC)

Risk level: medium | Human review: recommended | Duration: 518s | Reviewed: 2e87cb85

Specialist Reports

Specialist Status Summary
security ✅ PASS Security-conscious moderation-block PR with correct scope persistence, sensitive-action flagging, and hardened target resolution; only minor least-privilege and robustness notes.
architect ✅ PASS Well-architected least-privilege moderation blocks with clean layering and a single scope source-of-truth; only minor readability/coupling polish remains.
performance ✅ PASS Well-bounded PR with schema-capped inputs and no DB risk; the only performance concern is a potential PRAW lazy-attribute N+1 when iterating up to 100 mod-queue items.
testing ✅ PASS Strong, skeptical-grade test coverage of moderation actions and OAuth scope handling with meaningful assertions; only minor fallback/edge-case paths are untested.
quality ✅ PASS High-quality, well-documented moderation blocks with only minor readability and DRY polish opportunities.
product ✅ PASS Seven Reddit moderation blocks match the PR description with excellent least-privilege scoping and actionable errors; only minor terminology/empty-state UX polish is suggested.
discussion ✅ PASS All review concerns and inline threads are resolved; PR is blocked only by a stale bot CHANGES_REQUESTED predating the least-privilege fix commit and by the absence of a human approval on an auth-boundary change.
ui-reviewer (local) ❌ FAIL I'll start with the mandatory Bash setup — auth token and service verification. Token retrieval failed. Let me debug the auth flow. Better Auth endpoint returns HTML — this deployment uses Supabase/GoTrue. Let me try that directly.
ui-reviewer (hosted) ❌ FAIL I'll start with the mandatory environment setup and auth. Token came back empty. Let me try the sign-up fallback then re-auth. Better Auth endpoints return HTML (not present). Let me use the Supabase GoTrue fallback.

Findings: 🔴 0 critical | 🟠 0 high | 🟡 2 medium | 🟢 15 low

Should Fix

  • 🟢 autogpt_platform/backend/backend/blocks/reddit.py:64 Every moderation block requests the full baseline scope set (submit, edit, privatemessages, flair) in addition to its elevated mod scope, when most only need identity + the mod scope; the token is broader than least-privilege requires.
    Suggestion: Document that baseline over-provisioning is an accepted constraint of handle_default_scopes replacing DEFAULT_SCOPES, or trim the baseline merged into mod blocks to the minimum required (e.g. identity) if the OAuth handler can be adjusted to union scopes.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit.py:64 The scope-merge ternary keys off truthiness of required_scopes, so passing an explicit empty set returns set() and silently drops the baseline scopes, producing a credential that cannot even call client.user.me().
    Suggestion: Use required_scopes is not None instead of truthiness and union explicitly, so an empty-but-present set still yields the baseline.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit.py:66 required_scopes uses conditional-expression precedence: set(REDDIT_BASE_SCOPES) | required_scopes if required_scopes else set() parses as (base | required_scopes) if required_scopes else set(). Correct today but fragile — reformatting or added parens could silently change semantics, and the empty-set (base-block) branch is non-obvious.
    Suggestion: Use an explicit form, e.g. set(REDDIT_BASE_SCOPES) | required_scopes if required_scopes else set() rewritten as a clear if/else, or set(REDDIT_BASE_SCOPES) | (required_scopes or set()) if the baseline should always be present.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:19 settings and strip_reddit_prefix are imported transitively through backend.blocks.reddit, coupling the moderation module to reddit.py's import surface. settings in particular originates in backend.util.settings.
    Suggestion: Import settings from backend.util.settings directly; keep only Reddit-block-specific symbols coming from backend.blocks.reddit.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:108 The disabled=(not settings.secrets.reddit_client_id or not settings.secrets.reddit_client_secret) guard is copy-pasted across all 7 block constructors.
    Suggestion: Extract a shared helper (e.g. _reddit_disabled()) to centralize the enablement check and avoid drift.
  • 🟡 autogpt_platform/backend/backend/blocks/reddit_moderation.py:235 In ModQueueBlock.get_mod_queue's to_item(), each of up to 100 queued items reads item.author and item.permalink. PRAW objects are lazily loaded, and Comment.permalink can trigger a per-item network fetch to resolve the parent submission, producing up to 100 extra rate-limited Reddit API calls per run. Tests only use SimpleNamespace mocks so this lazy-fetch behavior is never exercised.
    Suggestion: Confirm modqueue listings arrive fully hydrated for the accessed fields; if not, limit attribute access to fields guaranteed present in the listing payload (or explicitly resolve permalink from ids) to avoid per-item round trips.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:268 ModQueueBlock.run yields six individual outputs per item for up to 100 items (~600 yields), multiplying downstream node executions by up to 100x when chained directly into destructive blocks like remove/ban.
    Suggestion: Document the fan-out scaling characteristic; the default limit=25 is a reasonable guardrail but users should understand the multiplier before wiring Mod Queue directly into sensitive actions at limit=100.
  • 🟡 autogpt_platform/backend/backend/blocks/reddit_moderation.py:66 The _get_thing_id fallback branch (when fullname is absent, synthesizing the prefix via isinstance(item, Comment)) is never exercised — all mod-queue tests supply fullname on the SimpleNamespace, so a bug in the fallback prefix logic would pass tests.
    Suggestion: Add a get_mod_queue test with a queued item that has no fullname attribute and assert the t1_/t3_ id is correctly derived from item.id and type.
  • 🟢 autogpt_platform/backend/backend/integrations/oauth/reddit.py:24 _granted_scopes normalizes commas via raw_scope.replace(',', ' ').split(), but every OAuth test passes space-separated scopes, leaving the comma-separated branch untested.
    Suggestion: Add an exchange/refresh test with "scope": "identity,read" and assert scopes == ['identity', 'read'].
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:200 ModQueueBlock.run() yields per-item scalar outputs in a loop, but only single-item flows are tested (test_output and helper tests). A regression in the per-item yield loop with multiple queue items would go uncaught.
    Suggestion: Mock get_mod_queue to return >=2 items and assert the full yielded output sequence.
  • 🟢 autogpt_platform/backend/backend/blocks/test/test_reddit_moderation.py:379 Length-bound tests cover mod_note, ban_message, and modmail subject, but omit ban reason (BAN_REASON_MAX_LENGTH) and modmail body (MODMAIL_BODY_MAX_LENGTH).
    Suggestion: Extend test_moderator_free_text_inputs_are_length_bounded with over-limit reason and modmail body cases.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit.py:67 The merged-scope expression set(REDDIT_BASE_SCOPES) | required_scopes if required_scopes else set() relies on non-obvious ternary/| precedence, making it hard to parse at a glance.
    Suggestion: Rewrite as an explicit conditional: assign merged = set(REDDIT_BASE_SCOPES) | required_scopes if required_scopes else set() on its own or use an if/else block so the grouping is unambiguous.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:230 ModQueueBlock.run mixes per-item scalar outputs yielded inside a loop with a single aggregate items output, which is non-obvious without knowledge of the block fan-out semantics.
    Suggestion: Add a short comment noting that scalar outputs fan out per queue item while items emits the full batch once.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:189 The disabled=(not settings.secrets.reddit_client_id or not settings.secrets.reddit_client_secret) check is copy-pasted verbatim across all 7 block init methods.
    Suggestion: Extract a shared helper (e.g. reddit_block_disabled()) and reuse it in each block to remove the duplication.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:73 _get_thing_type treats any non-t1_ value as a submission, while _get_moderated_thing strictly rejects unprefixed IDs — the two helpers apply inconsistent prefix logic.
    Suggestion: Make _get_thing_type explicitly branch on both t1_ and t3_ (raising or defaulting deliberately) so the prefix handling matches _get_moderated_thing.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:218 Blocks named 'Remove/Approve/Lock Reddit Post' and their post_id/post_title outputs are post-centric, but each block also operates on comments (Mod Queue even returns item_type=comment). Users searching the block picker for 'comment' moderation may not discover these blocks.
    Suggestion: Rename toward 'post or comment' (e.g. 'Remove Reddit Content') or add 'comment' to block descriptions/keywords so comment-moderation use cases are discoverable.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:208 When the mod queue is empty, no per-item outputs are yielded and only items=[] is emitted, giving downstream fan-out no signal distinguishing an empty queue from a no-op run.
    Suggestion: Emit an explicit signal (e.g. a count or is_empty output) so workflows can branch on an empty queue without ambiguity.

Quality Checks

  • lint: cd autogpt_platform/frontend && pnpm lint: cd autogpt_platform/frontend && pnpm lint (0s)
  • lint: cd autogpt_platform/backend && poetry run lint: cd autogpt_platform/backend && poetry run lint (92s)
  • typecheck: cd autogpt_platform/frontend && pnpm types: cd autogpt_platform/frontend && pnpm types (0s)
  • test: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc (0s)
  • build: cd autogpt_platform/frontend && pnpm build: cd autogpt_platform/frontend && pnpm build (0s)

Comment thread autogpt_platform/backend/backend/blocks/reddit.py
Comment thread autogpt_platform/backend/backend/blocks/reddit.py
Comment thread autogpt_platform/backend/backend/blocks/reddit.py
Comment thread autogpt_platform/backend/backend/blocks/reddit_moderation.py
Comment thread autogpt_platform/backend/backend/blocks/reddit_moderation.py
Comment thread autogpt_platform/backend/backend/blocks/reddit_moderation.py
Comment thread autogpt_platform/backend/backend/blocks/reddit_moderation.py
Comment thread autogpt_platform/backend/backend/blocks/reddit_moderation.py Outdated
Comment thread autogpt_platform/backend/backend/blocks/reddit_moderation.py
Comment thread autogpt_platform/backend/backend/blocks/reddit_moderation.py
@autogpt-pr-reviewer
autogpt-pr-reviewer Bot dismissed their stale review August 6, 2026 06:57

Superseded by a newer automated review.

@ntindle

ntindle commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

Copy link
Copy Markdown

Queued a review for PR #12945 at 2e87cb8.

@ntindle

ntindle commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

Copy link
Copy Markdown

A review is already queued or running for this commit (2e87cb8).

@ntindle

ntindle commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

Copy link
Copy Markdown

A review is already queued or running for this commit (2e87cb8).

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🔄 Auto-redeploying: new commits pushed to a PR with an active deployment. Refreshing development environment for PR #12945.

Comment thread autogpt_platform/backend/backend/blocks/reddit.py
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🔄 Auto-redeploying: new commits pushed to a PR with an active deployment. Refreshing development environment for PR #12945.

@ntindle

ntindle commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

Copy link
Copy Markdown

Queued a review for PR #12945 at 7ee2385.

@autogpt-pr-reviewer autogpt-pr-reviewer 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.

INCONCLUSIVE

Synthesis produced no output.

Risk level: high | Human review: recommended | Duration: 583s | Reviewed: 7ee2385e

Specialist Reports

Specialist Status Summary
security ✅ PASS Security-conscious PR with least-privilege scopes, sensitive-action gating, and fail-closed authorization; one medium note on the granted-scope fallback over-claiming when Reddit omits the scope field.
architect ✅ PASS Well-architected moderation blocks with correct least-privilege scoping and clean coupling; only minor maintainability polish (API tri-state, weak output typing, duplicated helper) worth addressing.
performance ✅ PASS Performance is sound (inputs bounded, no per-item refetch N+1); remaining notes are pre-existing async-blocking I/O and mod-queue fan-out rate-limit amplification.
testing ⚠️ WARN Thorough test suite with strong assertions, but the ModQueue only filter value is mock-blind, and the ban permanent=True branch plus the is_sensitive_action contract on destructive blocks are untested.
quality ✅ PASS High-quality, consistent PR; only minor naming/consistency polish items in the new moderation blocks.
product ✅ PASS Well-scoped moderation blocks with strong least-privilege and error-message UX; one likely-invalid Reddit filter value and a couple of safety-framing gaps to address.
discussion ⚠️ WARN All reviewer/bot feedback was addressed, but two CI checks are failing (Pyright dangling chat_db reference and Mod Queue docs out of sync) and no human review has occurred yet.
ui-reviewer (local) ✅ PASS All 7 Reddit moderation blocks register and behave exactly as described — least-privilege scopes, sensitive-action flags, bounded inputs, ambiguous-ID rejection, and granted-scope OAuth resolution all verified live with 44/44 tests passing; no PR-specific defects found.
ui-reviewer (hosted) ✅ PASS Backend-only Reddit moderation blocks pass all 44 tests re-run independently; least-privilege scopes, sensitive-action flags, ambiguous-ID rejection, OAuth granted-scope persistence, and input bounds all verified live with no defects.

Findings: 🔴 0 critical | 🟠 2 high | 🟡 7 medium | 🟢 13 low

Blockers

  • 🟠 autogpt_platform/backend/backend/blocks/reddit_moderation.py:90 ModQueueBlock exposes the only filter values 'submissions'/'comments', but Reddit's about/modqueue endpoint (which PRAW forwards only to) expects 'links'/'comments'. Selecting 'submissions' likely results in no filtering (both types returned), a silent UX failure where the user's chosen filter does nothing.
    Suggestion: Verify against PRAW/Reddit; if confirmed, map the user-facing 'submissions' value to 'links' before calling sub.mod.modqueue(only=...), keeping the friendly label.
  • 🟠 autogpt_platform/backend/backend/copilot/sdk/service.py:2807 This PR removed 'from backend.data.db_accessors import chat_db' from sdk/service.py, but 'chat_db' is still referenced at line 2807, causing Pyright to fail with 'chat_db is not defined (reportUndefinedVariable)' on type-check (3.11/3.12/3.13) and a runtime NameError. This is an out-of-scope import cleanup that broke the build.
    Suggestion: Restore the 'chat_db' import (or replace the line 2807 usage with the correct db accessor). Re-run 'poetry run pyright' before merge. Consider dropping the unrelated copilot import changes from this Reddit PR.

Should Fix

  • 🟡 autogpt_platform/backend/backend/integrations/oauth/reddit.py:20 When a token response omits or blanks the scope field, _granted_scopes falls back to requested_scopes, causing the persisted credential to claim scopes (including elevated moderator scopes) that may not have actually been granted. This is the unsafe direction and contradicts the PR's stated invariant that a non-moderator credential cannot silently claim mod scopes; it reintroduces the opaque-403-at-runtime failure mode.
    Suggestion: On a present but scope-less token response, fall back to a minimal/empty scope set or emit a warning rather than assuming the full requested set was granted. Only use requested_scopes for the genuine wildcard case.
  • 🟢 autogpt_platform/backend/backend/integrations/oauth/reddit.py:26 Reddit's * wildcard means 'every scope this app may request', which can be broader than requested_scopes. Mapping it to requested_scopes under-claims (safe direction) but may trigger unnecessary re-consent prompts when the actual grant is broader.
    Suggestion: Document the intent, or resolve * to the app's full requestable scope set if consistent re-consent behavior is desired.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit.py:66 RedditCredentialsField has subtle tri-state semantics: required_scopes=None takes the legacy implicit-scope path (no credentials_scopes metadata) while required_scopes=set() materializes the baseline explicitly. Two 'empty' inputs diverge in credential contract, which is an easy footgun for future callers.
    Suggestion: Either default to frozenset() and always emit explicit credentials_scopes, or add a call-site-visible note; at minimum keep the None-vs-empty distinction covered by the existing tests.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:108 ModQueueBlock.Output.items is typed list[dict[str, Any]], a weak contract for a payload consumed by downstream blocks. Consumers get no schema guarantees on the id/type/title/author/permalink/reason shape.
    Suggestion: Define a TypedDict/model for the queue-item shape and use it for both to_item() and the items output to harden the cross-block boundary and self-document fields.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:57 _reddit_disabled() is re-declared here and likely duplicates the disabled-check logic already used by blocks in reddit.py, risking drift if the client-id/secret gating changes.
    Suggestion: Export a single shared helper from reddit.py and reuse it in reddit_moderation.py.
  • 🟡 autogpt_platform/backend/backend/blocks/reddit_moderation.py:235 run() methods are async but call synchronous blocking PRAW network methods (modqueue, mod.remove, banned.add) directly, stalling the event loop for the full request latency plus PRAW's internal rate-limit sleep. Replicated across all seven new blocks.
    Suggestion: Offload blocking PRAW calls with await asyncio.to_thread(...) so network I/O and rate-limit backoff don't block the coroutine/event loop.
  • 🟡 autogpt_platform/backend/backend/blocks/reddit_moderation.py:240 ModQueueBlock fans out post_id once per queued item (up to 100). Wiring this to a destructive block produces up to 100 individual moderation API calls in one execution, which can exceed Reddit's ~100 req/min OAuth quota and trigger PRAW's blocking rate-limit sleep with no batching or backoff strategy.
    Suggestion: Document the rate-limit behavior on ModQueueBlock and/or guide users toward smaller limits; consider surfacing that large-queue fan-out will serialize under Reddit's per-account quota.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:48 get_praw(creds) instantiates a fresh praw.Reddit client (and requests/prawcore session) on every block invocation, so in a Mod Queue -> per-item action pipeline each of N downstream calls pays fresh connection/TLS setup with no keep-alive pooling reuse.
    Suggestion: Consider caching/reusing a PRAW client per credential within an execution (shared helper change) to enable HTTP connection pooling across chained moderation calls.
  • 🟡 autogpt_platform/backend/backend/blocks/reddit_moderation.py:197 get_mod_queue forwards only ('submissions'/'comments') straight to sub.mod.modqueue(). Reddit's listing API documents the filter values as 'links'/'comments'. The test asserts the call was made with only='submissions', but because sub.mod.modqueue is mocked it passes regardless of whether Reddit accepts that value — a wrong value would silently return unfiltered results in production.
    Suggestion: Confirm PRAW/Reddit accepts 'submissions' (vs 'links'); if it maps internally, document it. Consider mapping to Reddit's documented values explicitly so the intent is verifiable, and add a comment in the test noting the value is API-contract-dependent.
  • 🟡 autogpt_platform/backend/backend/blocks/reddit_moderation.py:210 is_sensitive_action=True is set on seven destructive moderation blocks (ban, remove, lock, modmail, etc.) but no test asserts it. A refactor could silently drop the flag—removing the confirmation gate on irreversible actions—while the suite stays green.
    Suggestion: Add a parametrized test asserting block().is_sensitive_action is True for each state-changing block (and False for ModQueue).
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:445 BanSubredditUserBlock yields permanent = input_data.duration is None, but every test (including test_input) uses duration=7, so the permanent-ban branch (permanent=True) is never exercised at the run() level.
    Suggestion: Add a run()-level test with duration=None asserting the block yields ('permanent', True) and that ban_user is called without a duration kwarg.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:200 No test covers the failure path for destructive blocks (e.g., PRAW raising 403/insufficient-scope or unknown-user). There is no assertion that a failed remove/ban surfaces an error rather than reporting success.
    Suggestion: Add a test where the mocked PRAW call raises and assert the exception propagates (surfaces via the block error output) rather than yielding success=True.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:219 RemoveRedditPostBlock (and Approve/Lock blocks) name the input post_id, but they explicitly accept comments (t1_) as well as posts (t3_), making the name misleading.
    Suggestion: Rename to thing_id to match Reddit terminology and the internal helper naming; these are new blocks so there is no back-compat cost.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:118 ModQueueBlock.Output.post_title emits the literal '[comment]' for comment items, so a field named post_title can carry a non-title placeholder.
    Suggestion: Rename the output to title (or a comment-aware name) to reflect that it covers both posts and comments.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:76 _get_thing_id is a trivial one-line wrapper (return item.fullname) used in a single place, adding indirection without abstraction value.
    Suggestion: Inline item.fullname at the call site in to_item.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:80 get_thing_type and get_moderated_thing independently re-implement the same t1/t3 prefix dispatch and raise differently-worded errors for the same bad-input class, risking drift.
    Suggestion: Extract a single prefix->kind resolver shared by both helpers with a consistent error message.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:658 SendModMailBlock.run hardcodes yield "success", True, unlike sibling blocks that return success from their static method.
    Suggestion: Return success from send_modmail (e.g. (conversation_id, True)) or add a short comment noting success is unconditional because failures raise.
  • 🟡 autogpt_platform/backend/backend/blocks/reddit_moderation.py:330 BanSubredditUserBlock reason silently defaults to 'Violation of subreddit rules'. For an irreversible, audit-logged action, a generic default may be applied without the moderator's awareness.
    Suggestion: Consider making reason required (no default) or documenting prominently that this value is written to the subreddit mod log.
  • 🟢 autogpt_platform/backend/backend/blocks/reddit_moderation.py:150 ModQueueBlock's per-item scalar fan-out means a downstream sensitive block (e.g. Remove/Ban) wired to post_id will auto-fire once per queued item. This bulk-action risk is documented for correctness but not framed as a safety caution.
    Suggestion: Add a caution to the block description noting that wiring scalar outputs into destructive blocks executes the action for every queued item.
  • 🟡 docs/integrations/block-integrations/misc.md:890 check-docs-sync fails: the Mod Queue 'items' output description is out of sync. Code declares 'All queued items as a list. Emitted exactly once; an empty list signals that the queue was checked and had no items.' but misc.md only has 'All queued items as a list'. The PR checklist claims 'generate_block_docs.py --check' passed, which contradicts CI.
    Suggestion: Run 'cd autogpt_platform/backend && poetry run python scripts/generate_block_docs.py' to regenerate docs, commit the result, and confirm docs-sync passes.

Quality Checks

  • lint: cd autogpt_platform/frontend && pnpm lint: cd autogpt_platform/frontend && pnpm lint (0s)
  • lint: cd autogpt_platform/backend && poetry run lint: cd autogpt_platform/backend && poetry run lint (73s)
  • typecheck: cd autogpt_platform/frontend && pnpm types: cd autogpt_platform/frontend && pnpm types (0s)
  • test: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc (0s)
  • build: cd autogpt_platform/frontend && pnpm build: cd autogpt_platform/frontend && pnpm build (0s)

@github-actions github-actions Bot added cla: pending CLA not yet signed by all contributors and removed cla: signed CLA signed by all contributors labels Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🔄 Auto-redeploying: new commits pushed to a PR with an active deployment. Refreshing development environment for PR #12945.

@ntindle

ntindle commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

/review

@github-actions github-actions Bot added cla: signed CLA signed by all contributors and removed cla: pending CLA not yet signed by all contributors labels Aug 7, 2026
@autogpt-pr-reviewer

Copy link
Copy Markdown

Queued a review for PR #12945 at b9ecb28.

@ntindle

ntindle commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

Follow-up on the latest review: the ModQueue filter is already using PRAW's public contract. SubredditModeration.modqueue explicitly accepts only="submissions", and PRAW's _handle_only maps that value to Reddit's "links" API parameter internally. No filter change is needed. The current head also restores the chat_db import and regenerates the Mod Queue docs that the review flagged.

Comment on lines 208 to +209
refresh_token_expires_at=None,
scopes=credentials.scopes,
scopes=_granted_scopes(tokens.get("scope"), credentials.scopes),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The new scope normalization in _refresh_tokens can narrow scopes, which causes a ValueError in update_creds because its guard prevents storing credentials with fewer scopes.
Severity: HIGH

Suggested Fix

The guard in credentials_store.py that prevents scope narrowing should be re-evaluated or removed. The system should trust the scopes returned by the OAuth provider during a refresh and update the stored credentials accordingly, even if the scope set is narrower.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: autogpt_platform/backend/backend/integrations/oauth/reddit.py#L208-L209

Potential issue: The `_refresh_tokens` method in `reddit.py` uses `_granted_scopes` to
normalize scopes returned by Reddit during a token refresh. This can produce a
credential with a narrower set of scopes than what is currently stored. This new
credential is then passed to `update_creds` in `credentials_store.py`. However,
`update_creds` has a guard that explicitly raises a `ValueError` if an update attempts
to narrow the scope set by checking `not
set(updated.scopes).issuperset(current.scopes)`. This conflict will cause any token
refresh that results in narrower scopes to fail with a `ValueError`, preventing the
user's credentials from being updated.

Also affects:

  • autogpt_platform/backend/backend/core/credentials/manager.py:222~223
  • autogpt_platform/backend/backend/core/credentials/store.py:464~471

@autogpt-pr-reviewer autogpt-pr-reviewer 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.

📋 Automated Review — PR #12945

PR #12945 — feat(reddit): add moderation blocks
Author: ntindle | Files: 8

🎯 Verdict: REQUEST_CHANGES

PR Description Quality

✅ Has Why + What + How — the description details the seven blocks, the least-privilege scope model, prefixed thing-ID targeting, and testing/docs sync. The only gap is the unrelated executor/utils_test.py edits, which aren't mentioned in the Changes section (see 🟠 Should Fix).

What This PR Does

Adds seven moderator-focused Reddit blocks — Mod Queue, Remove, Approve, Lock, Ban, Unban, and Send Mod Mail — to the AutoGPT block library. Crucially, it does this with an opt-in least-privilege OAuth model: elevated moderator scopes (modposts/modcontributors/modmail) are kept out of the default scope set and requested only per-block, every destructive action is flagged is_sensitive_action=True, and moderation targets must carry a t1_/t3_ prefix so an action can never silently land on the wrong object. It also switches OAuth to persist the scopes Reddit actually granted rather than the ones requested.

Prior Issues — Status

  • Addressedchat_db undefined in copilot/sdk/service.py:2807 (prior build-breaker): backend poetry run lint and frontend pnpm types both pass on this head, so the reference resolves.
  • Settled — ModQueue only filter values: @cursor raised the invalid-links variant and the author converged on Literal["submissions","comments"]; the thread is resolved. Not re-raised here absent new evidence (rule 14).

Specialist Findings

🛡️ Security ✅ — Confirmed least-privilege scoping done right: mod scopes excluded from DEFAULT_SCOPES, modlog never requested, all state-changers marked sensitive, and mandatory ID prefixing rejects ambiguous targets before any Reddit call. No cross-tenant escalation (blocks act on the connecting user's own credential).
🟡 Free-text subreddit/username inputs (reddit_moderation.py) reach PRAW unvalidated — not injectable, but a fail-fast regex would help.

🏗️ Architecture ✅ — Clean layering: per-block required_scopes merged centrally, and REDDIT_BASE_SCOPES = frozenset(RedditOAuthHandler.DEFAULT_SCOPES) (reddit.py:41) removes a previously drift-prone hardcoded scope list — this PR reduces debt.
🟠 Out-of-scope executor/utils_test.py changes (:611, :2020) unrelated to Reddit.
🟡 Block module now imports the concrete OAuth handler (reddit.py:22) — no cycle today, worth watching.

Performance ✅ — Network-bound integration; no N+1 DB queries, no unbounded loops. ModQueue limit is capped 1–100, the key scalability safeguard. All state-changers are O(1), one PRAW mutation each.
🟡 to_item() (reddit_moderation.py:249) is O(1)/item only if PRAW returns hydrated modqueue objects; a lazy attribute would trigger per-item _fetch(). The test test_get_mod_queue_uses_hydrated_praw_fields_without_fetching already asserts no fetch — good.

🧪 Testing ⚠️ — Strong suite overall (44 tests pass): scope declarations, ambiguous-ID rejection, PRAW call shapes, and OAuth normalization all have meaningful assertions. But two derived-output branches on destructive blocks lack run-level coverage.
🟠 BanSubredditUserBlock.run permanent-ban (duration=None) path never asserts permanent=True; SendModMailBlock.run hardcodes success=True regardless of result, untested.

📖 Quality ✅ — Readability A-: clear naming, extracted constants, docstrings on tricky helpers, thorough type hints.
🟡 _get_thing_type/_get_moderated_thing duplicate prefix-dispatch logic; _get_thing_id is a trivial wrapper; merged_scopes ternary is dense (reddit.py:68).

📦 Product ✅ — Implementation faithfully matches a detailed description; happy path, error handling, and edge cases all sound. Opt-in scopes genuinely protect read/post-only users from over-granting.
🟡 "Mod Queue" and "Send Mod Mail" lack the "Reddit" brand other blocks carry, hurting picker discoverability; "…Reddit Post" blocks also act on comments.

📬 Discussion ⚠️ — 44/45 review threads resolved; author responded actively over two rounds. One HIGH-severity Sentry thread (newest comment, unanswered) remains open and is code-verified — see Blocker. No human approval yet (REVIEW_REQUIRED).

🔎 QA ✅ — Exercised the blocks in the live rest_server container: all 7 register in /api/blocks (354→381 blocks) with correct per-block least-privilege scope metadata (no modlog); ambiguous IDs (abc123, ``, T1_XYZ, `t5_x`) rejected before any Reddit call; input bounds enforced at the schema layer; `_granted_scopes` correctly normalizes narrower/`*`/comma/missing grants; unauth and bad-token requests return 401; 44 bundled tests pass on independent re-run. Live PRAW mutations couldn't be exercised (no real Reddit OAuth in sandbox).

🔴 Blockers

  1. Refresh-time scope narrowing can break token refresh (autogpt_platform/backend/backend/integrations/oauth/reddit.py:209) — _refresh_tokens now stores scopes=_granted_scopes(tokens.get("scope"), credentials.scopes) instead of the previous scopes=credentials.scopes (which never narrowed). The specialist traced the full path: if Reddit's refresh response returns a scope field narrower than the stored set, _granted_scopes returns that narrower set, and update_creds raises ValueError at the verified guard credentials_store.py:466 (issuperset check), failing the refresh and silently breaking the user's Reddit integration. This is a new failure path on the credential-refresh (security) boundary, introduced by this PR, on an open/unanswered HIGH Sentry thread. Fix: never narrow on refresh — union granted scopes with the stored set (or fall back to credentials.scopes unless the grant is a strict superset) — and add a test where the refresh scope response is narrower than stored. (Flagged by: discussion — code-verified)

🟠 Should Fix

  1. Out-of-scope test-fixture changes (autogpt_platform/backend/backend/executor/utils_test.py:611, :2020) — mock_graph_exec.expert_id = None and the onboarding_db.increment_onboarding_runs mock are unrelated to Reddit moderation and undocumented. Split them out or call them out in the description (AGENTS.md: keep out-of-scope changes <20%). (Flagged by: architect, quality — 2 specialists)
  2. Untested derived outputs on destructive blocks (reddit_moderation.py:525, :659) — BanSubredditUserBlock.run's permanent=True branch (duration=None) is never asserted at the run level, and SendModMailBlock.run hardcodes ("success", True) independent of the send result with no run-level test. A boolean regression on the permanent-ban path — the higher-impact one — would ship undetected. Add run-level tests and consider deriving modmail success from a truthy conversation_id. (Flagged by: testing)

🟡 Nice to Have

  1. Block discoverability naming (reddit_moderation.py:92, :559) — rename "Mod Queue" → "Reddit Mod Queue" and "Send Mod Mail" → "Send Reddit Mod Mail" to match the branded pattern of other Reddit blocks. (product)
  2. DRY prefix-classification (reddit_moderation.py:73) — factor a single _classify_thing_id() helper shared by _get_moderated_thing/_get_thing_type; inline the one-line _get_thing_id. (quality)
  3. Input format validation (reddit_moderation.py) — add a light [A-Za-z0-9_]{3,21} bound on subreddit/username to fail fast. (security)
  4. Terminology on Remove/Approve/Lock blocks — names/labels say "post" but accept t1_ comment IDs; consider "post or comment" wording. (product, quality)
  5. Confirm ModQueue hydration (reddit_moderation.py:249) — verify PRAW keeps modqueue listings hydrated across versions so to_item never degrades to per-item fetch (bounded ≤100). (performance)

🔵 Nits

  1. merged_scopes readability (reddit.py:68) — the |-plus-ternary one-liner would read better as an explicit if/else. (quality)
  2. Layering note (reddit.py:22) — block module importing the concrete OAuth handler; keep DEFAULT_SCOPES a stable public attr and ensure the handler never imports from blocks. (architect)

Human Review Needed

YES — The blocker changes how OAuth credential scopes are computed and persisted on token refresh (the credential-storage / security boundary), and it carries an open, unresolved HIGH-severity thread on exactly that code. A maintainer should confirm the intended refresh-scope semantics before merge.

Risk Assessment

Merge risk: MEDIUM | Rollback: EASY (isolated new module + a scoped OAuth handler change; revert is clean)

CI Status

  • Local harness: ✅ all 5 checks pass (backend lint 91s, frontend lint/types/test/build).
  • GitHub CI (per discussion specialist): ~40/43 green, none failing (type-check 3.11–3.13, test 3.12/3.13, CodeQL, e2e, check-docs-sync all pass); test (3.11) + Check PR Status still running. Review decision REVIEW_REQUIRED — no human approval yet.

UI Testing — Variant Results

✅ local: All 7 Reddit moderation blocks register in the live API with correct least-privilege scopes, ID-prefix safety guards, input bounds, and OAuth granted-scope persistence; 44 bundled tests pass and negative auth returns 401.

✅ hosted: All 7 Reddit moderation blocks register with correct least-privilege scopes and input bounds; 44 unit tests pass, docs in sync, negative tests clean, and blocks render in the builder UI — QA PASS.

the wildcard `*` to mean "every scope this app may request". Falling back to
the requested scopes keeps behaviour sane if Reddit omits the field entirely.
"""
if not isinstance(raw_scope, str) or not raw_scope.strip():

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (security/oauth-scope-integrity)

When Reddit's token response omits or returns an empty 'scope' field, _granted_scopes falls back to requested_scopes, which includes the elevated moderator scopes. This can cause the persisted credential to claim mod authority (modposts/modcontributors/modmail) it may not actually hold — the exact over-claim this PR aims to prevent.

Suggestion: Log when the fallback path is taken so a silently-narrowed or over-claimed grant is observable, and consider defaulting to the baseline scopes rather than the full requested set when Reddit returns no scope field.

test_output=[
("post_id", "t3_abc123"),
("success", True),
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (security/input-validation)

subreddit and username inputs on the ban/unban/modmail/mod-queue blocks are unvalidated free text passed directly into PRAW. Not injectable (PRAW/Reddit validate and encode), but there is no fail-fast format check.

Suggestion: Add a lightweight pattern constraint (e.g. Reddit's [A-Za-z0-9_]{3,21}) via SchemaField to reject malformed subreddit/username values before any API call.


mock_graph_exec = mocker.MagicMock(spec=GraphExecutionWithNodes)
mock_graph_exec.organization_id = "org-rpc"
mock_graph_exec.expert_id = 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.

🤖 🟡 medium (architect/out-of-scope change)

Added mock_graph_exec.expert_id = None is unrelated to Reddit moderation and appears to be a rebase/merge artifact bundled into this PR.

Suggestion: Move this change to its own PR or explicitly document why it belongs here (AGENTS.md: keep out-of-scope changes under 20%).

)
mock_edb.update_node_execution_status_batch = mocker.AsyncMock()

mock_odb = mocker.patch("backend.executor.utils.onboarding_db")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟡 medium (architect/out-of-scope change)

New onboarding_db.increment_onboarding_runs mock and expert_id = None in the create-path helper are unrelated to the Reddit moderation feature.

Suggestion: Split these executor test changes into a separate, appropriately-scoped PR.

OAuth2Credentials,
SchemaField,
)
from backend.integrations.oauth.reddit import RedditOAuthHandler

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (architect/coupling / layering)

The block-definition module now imports the concrete RedditOAuthHandler to source DEFAULT_SCOPES, coupling the blocks layer to an integration internal. No cycle exists today, but the dependency direction is worth watching.

Suggestion: Keep DEFAULT_SCOPES a stable public attribute of the handler and ensure the OAuth handler never imports from backend.blocks; optionally note the cross-module dependency.

call `client.user.me()`.
"""
merged_scopes = (
set(REDDIT_BASE_SCOPES) | required_scopes

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (quality/readability)

merged_scopes combines a set union and a conditional expression on one statement, making operator precedence non-obvious on first read.

Suggestion: Rewrite as an explicit if/else block.


class ModQueueBlock(Block):
class Input(BlockSchemaInput):
credentials: RedditCredentialsInput = RedditCredentialsField(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (product/discoverability/consistency)

The block renders as 'Mod Queue', unlike every other Reddit block which carries the 'Reddit' brand (e.g. 'Create Reddit Post'). Users searching the block picker for 'reddit' won't find it, and 'Mod Queue' in the SOCIAL category gives no signal it is Reddit-specific.

Suggestion: Rename to 'Reddit Mod Queue' (e.g. add an explicit display name) so it matches the naming pattern of the other Reddit blocks and is discoverable by search.

is_sensitive_action=True,
)

@staticmethod

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (product/discoverability/consistency)

SendModMailBlock renders as 'Send Mod Mail', which lacks the 'Reddit' brand used across the other Reddit blocks; modmail is a Reddit-specific concept but the name doesn't scope it, hurting search/browse discoverability.

Suggestion: Rename to 'Send Reddit Mod Mail' for consistency with the Reddit block naming convention.

yield "item_type", item["type"]
yield "post_title", item["title"]
yield "author", item["author"]
yield "permalink", item["permalink"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (product/terminology)

Blocks named 'Remove/Approve/Lock Reddit Post' (and their pass-through output labels like 'ID of the removed post') act on comments too. The name/label say 'post' while the input accepts t1_ comment IDs, which may make moderators hesitate to route comment IDs through these blocks.

Suggestion: Rename to reference 'post or comment' (e.g. 'Remove Reddit Content') or update the output field descriptions to 'ID of the removed post or comment' to match the input semantics.

access_token_expires_at=int(time.time()) + tokens.get("expires_in", 3600),
refresh_token_expires_at=None,
scopes=credentials.scopes,
scopes=_granted_scopes(tokens.get("scope"), credentials.scopes),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟠 high (discussion/unresolved-review-thread)

Open, unanswered Sentry HIGH thread (newest comment on the PR): _refresh_tokens now stores _granted_scopes(tokens.get('scope'), credentials.scopes) instead of credentials.scopes. If Reddit's refresh response returns a narrower scope set, update_creds raises ValueError (credentials_store.py:466 guards against scope narrowing via issuperset), which would break the token refresh. Verified the guard exists; this is a new failure path introduced by the PR.

Suggestion: Respond to the thread and either (a) never narrow on refresh — union granted scopes with the stored set, or fall back to credentials.scopes unless the grant is a strict superset; or (b) relax/handle the update_creds narrowing guard for provider-driven refresh. Add a test where the refresh scope response is narrower than the stored scopes.

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

Labels

cla: signed CLA signed by all contributors documentation Improvements or additions to documentation platform/backend AutoGPT Platform - Back end platform/blocks size/xl

Projects

Status: 🚧 Needs work
Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants