feat(copilot): add tool/block capability filtering to AutoPilotBlock - #12482
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a CopilotPermissions model and permission plumbing: validation, inheritance/merge, context propagation, SDK/service/collect support, AutoPilot input fields and runtime enforcement in RunBlockTool, plus unit and integration tests and docs updates. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant AutoPilot as AutoPilotBlock
participant Validator as PermValidation
participant Context as ExecutionContext
participant SDK as SDKService
participant Runner as RunBlockTool
User->>AutoPilot: run(input with tools/blocks)
AutoPilot->>Validator: _build_and_validate_permissions()
alt validation fails
Validator-->>AutoPilot: error string
AutoPilot-->>User: yield("error", ...)
else validation succeeds
Validator-->>AutoPilot: CopilotPermissions
AutoPilot->>Context: set_execution_context(permissions=perms)
AutoPilot->>SDK: stream_chat_completion_sdk(permissions=perms)
SDK->>SDK: apply_tool_permissions(permissions)
loop tool/block calls
SDK->>Runner: execute(block_id)
Runner->>Context: get_current_permissions()
alt block disallowed
Runner-->>SDK: ErrorResponse
else allowed
Runner-->>SDK: success result
end
end
AutoPilot-->>User: yield(response, ...)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
🔍 PR Overlap DetectionThis check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early. 🔴 Merge Conflicts DetectedThe following PRs have been tested and will have merge conflicts if merged after this PR. Consider coordinating with the authors.
🟢 Low Risk — File Overlap OnlyThese PRs touch the same files but different sections (click to expand)
Summary: 5 conflict(s), 0 medium risk, 4 low risk (out of 9 PRs with file overlap) Auto-generated on push. Ignores: |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
autogpt_platform/backend/backend/copilot/permissions.py (2)
59-60: Remove emptyTYPE_CHECKINGblock.The
if TYPE_CHECKING: passblock serves no purpose since there are no type-only imports needed here.🧹 Suggested fix
-if TYPE_CHECKING: - pass🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@autogpt_platform/backend/backend/copilot/permissions.py` around lines 59 - 60, Remove the no-op TYPE_CHECKING block and any now-unused import: delete the lines containing "if TYPE_CHECKING: pass" in permissions.py, and also remove the TYPE_CHECKING name from the typing import (or the entire import) if it becomes unused so there are no dead/no-op constructs remaining.
256-268: Consider caching block instances during validation.The current implementation instantiates
block_cls()for each(identifier, block)pair. While block instantiation is lightweight, this could be optimized for large identifier lists by building a lookup map once.♻️ Suggested optimization
async def validate_block_identifiers( identifiers: list[str], ) -> list[str]: from backend.blocks import get_blocks - # get_blocks() returns dict[block_id_str, BlockClass]; instantiate to get id/name. block_registry = get_blocks() + # Build lookup once: [(block_id, block_name), ...] + block_info = [(block_id, block_cls().name) for block_id, block_cls in block_registry.items()] + invalid: list[str] = [] for ident in identifiers: matched = any( - _block_matches(ident, block_id, block_cls().name) - for block_id, block_cls in block_registry.items() + _block_matches(ident, block_id, block_name) + for block_id, block_name in block_info ) if not matched: invalid.append(ident) return invalid🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@autogpt_platform/backend/backend/copilot/permissions.py` around lines 256 - 268, The loop repeatedly calls block_cls() for each (identifier, block) pair; instead, build a one-time lookup of instantiated blocks or their names from block_registry (e.g., create block_instances or block_names by iterating block_registry and calling block_cls() once per entry), then use that lookup in the validation loop when calling _block_matches(ident, block_id, ...). Update the code around get_blocks(), block_registry, and the validation loop so matched uses the prebuilt map rather than instantiating block_cls() repeatedly.autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py (2)
125-129: Avoid identity-coupling in no-parent merge test.This assertion couples the test to object reuse (
is) rather than contract behavior. Prefer semantic checks (e.g., equality/effective permissions) so refactors that return copies don’t break tests unnecessarily.Proposed test adjustment
def test_permissions_no_parent_returned_unchanged(self): perms = CopilotPermissions(tools=["bash_exec"], tools_exclude=True) result = _merge_inherited_permissions(perms) - assert result is perms + assert result is not None + assert result.tools == ["bash_exec"] + assert result.tools_exclude is True🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py` around lines 125 - 129, The test test_permissions_no_parent_returned_unchanged should not assert identity; change the assertion so it verifies semantic equivalence of permissions instead of object reuse: call _merge_inherited_permissions(perms) and assert the returned CopilotPermissions has the same effective attributes/values (e.g., tools list, tools_exclude flag, and any other relevant fields) as the original perms (or use equality if CopilotPermissions implements __eq__) rather than using "is". This keeps the test focused on behavior for CopilotPermissions and _merge_inherited_permissions and avoids breaking on harmless copy/refactor changes.
64-71: Consider extracting a shared block-registry mock fixture.The same
get_blocksmock setup is repeated in several tests; a small fixture/helper would reduce duplication and make intent clearer.Also applies to: 76-83, 89-94, 217-223
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py` around lines 64 - 71, Extract the repeated get_blocks mock into a reusable test fixture or helper function to reduce duplication and clarify intent: create a fixture/helper (e.g., make_mock_block_registry or fixture named mock_block_registry) that constructs the MagicMock block class with return_value.name = "HTTP Request" and patches backend.blocks.get_blocks to return the mapping used in tests, then replace inline patch usage in tests that call _make_input and _build_and_validate_permissions (and the other occurrences around lines 76-83, 89-94, 217-223) to use the new fixture/helper instead of duplicating mock_block_cls and patch logic.
🤖 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/autopilot.py`:
- Around line 501-531: The function _merge_inherited_permissions currently calls
_inherited_permissions.set(merged) but never resets it, causing sequential
AutoPilot invocations to inherit stale permissions; change
_merge_inherited_permissions to perform the contextvar set and return the
ContextVar token (i.e., token = _inherited_permissions.set(merged); return
merged, token or just return token depending on your API), then update
execute_copilot to call _merge_inherited_permissions before running the copilot
block and ensure you call _inherited_permissions.reset(token) in a finally block
(mirroring the recursion depth token pattern used around lines 434-445) so the
inherited permissions are restored after each non-nested execution.
---
Nitpick comments:
In `@autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py`:
- Around line 125-129: The test test_permissions_no_parent_returned_unchanged
should not assert identity; change the assertion so it verifies semantic
equivalence of permissions instead of object reuse: call
_merge_inherited_permissions(perms) and assert the returned CopilotPermissions
has the same effective attributes/values (e.g., tools list, tools_exclude flag,
and any other relevant fields) as the original perms (or use equality if
CopilotPermissions implements __eq__) rather than using "is". This keeps the
test focused on behavior for CopilotPermissions and _merge_inherited_permissions
and avoids breaking on harmless copy/refactor changes.
- Around line 64-71: Extract the repeated get_blocks mock into a reusable test
fixture or helper function to reduce duplication and clarify intent: create a
fixture/helper (e.g., make_mock_block_registry or fixture named
mock_block_registry) that constructs the MagicMock block class with
return_value.name = "HTTP Request" and patches backend.blocks.get_blocks to
return the mapping used in tests, then replace inline patch usage in tests that
call _make_input and _build_and_validate_permissions (and the other occurrences
around lines 76-83, 89-94, 217-223) to use the new fixture/helper instead of
duplicating mock_block_cls and patch logic.
In `@autogpt_platform/backend/backend/copilot/permissions.py`:
- Around line 59-60: Remove the no-op TYPE_CHECKING block and any now-unused
import: delete the lines containing "if TYPE_CHECKING: pass" in permissions.py,
and also remove the TYPE_CHECKING name from the typing import (or the entire
import) if it becomes unused so there are no dead/no-op constructs remaining.
- Around line 256-268: The loop repeatedly calls block_cls() for each
(identifier, block) pair; instead, build a one-time lookup of instantiated
blocks or their names from block_registry (e.g., create block_instances or
block_names by iterating block_registry and calling block_cls() once per entry),
then use that lookup in the validation loop when calling _block_matches(ident,
block_id, ...). Update the code around get_blocks(), block_registry, and the
validation loop so matched uses the prebuilt map rather than instantiating
block_cls() repeatedly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 474a0a42-0b6b-416e-8b8b-6911d74da8fe
📒 Files selected for processing (9)
autogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/copilot/sdk/tool_adapter.pyautogpt_platform/backend/backend/copilot/tools/run_block.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). (10)
- GitHub Check: check API types
- GitHub Check: Seer Code Review
- GitHub Check: end-to-end tests
- GitHub Check: Analyze (python)
- GitHub Check: type-check (3.12)
- GitHub Check: test (3.13)
- GitHub Check: type-check (3.13)
- GitHub Check: Check PR Status
- GitHub Check: test (3.12)
- GitHub Check: test (3.11)
🧰 Additional context used
📓 Path-based instructions (8)
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
Files:
autogpt_platform/backend/backend/copilot/tools/run_block.pyautogpt_platform/backend/backend/copilot/sdk/tool_adapter.pyautogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
autogpt_platform/backend/**/*.{py,txt}
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use
poetry runprefix for all Python commands, including testing, linting, formatting, and migrations
Files:
autogpt_platform/backend/backend/copilot/tools/run_block.pyautogpt_platform/backend/backend/copilot/sdk/tool_adapter.pyautogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
autogpt_platform/backend/backend/**/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings
Files:
autogpt_platform/backend/backend/copilot/tools/run_block.pyautogpt_platform/backend/backend/copilot/sdk/tool_adapter.pyautogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
autogpt_platform/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/copilot/tools/run_block.pyautogpt_platform/backend/backend/copilot/sdk/tool_adapter.pyautogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.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
Files:
autogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
autogpt_platform/backend/backend/blocks/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
autogpt_platform/backend/backend/blocks/*.py: When creating new blocks, inherit from theBlockbase class and define input/output schemas usingBlockSchema
Implement blocks with an asyncrunmethod and generate unique block IDs usinguuid.uuid4()
When working with files in blocks, usestore_media_file()frombackend.util.filewith appropriatereturn_formatparameter:for_local_processingfor local tools,for_external_apifor external APIs,for_block_outputfor block outputs
Always usefor_block_outputformat instore_media_file()for block outputs unless there is a specific reason not to
Never hardcode workspace checks when usingstore_media_file()- letfor_block_outputhandle context adaptation automatically
When adding new blocks, analyze block interfaces to ensure inputs and outputs tie well together for productive graph-based editor connections
Files:
autogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
autogpt_platform/backend/**/*_test.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
autogpt_platform/backend/**/*_test.py: Always review snapshot changes withgit diffbefore committing when updating snapshots withpoetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the*_test.pynaming convention
Files:
autogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
autogpt_platform/backend/**/*test*.py
📄 CodeRabbit inference engine (AGENTS.md)
Run
poetry run testfor backend testing (runs pytest with docker based postgres + prisma)
Files:
autogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
🧠 Learnings (34)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
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:10.126Z
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.
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.
📚 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 : Implement 'run' method with proper error handling in backend blocks
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-03-10T08:38:29.078Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:29.078Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review is session-scoped: it uses graph_exec_id (copilot-session-{session_id}) combined with node_id (copilot-node-{block_id}). If the user enables the auto-approve toggle for a CoPilot session, approving a block type in that session automatically approves all future invocations of that same block type within the same session. If the user does not toggle auto-approve (default), each individual invocation requires its own approval. This behavior should be clearly documented in code and comments, and tested to ensure the toggle reliably toggles between session-scoped auto-approval and per-invocation approval.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-15T15:30:09.706Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/tools/helpers.py:149-185
Timestamp: 2026-03-15T15:30:09.706Z
Learning: In autogpt_platform/backend/backend/copilot/tools/helpers.py, within execute_block, when InsufficientBalanceError occurs after post-execution credit charging (concurrent balance drain after pre-check passed), this is treated as a non-fatal billing leak: log at ERROR level with structured JSON fields `{"billing_leak": True, "user_id": ..., "cost": ...}` for monitoring/alerting, then return BlockOutputResponse normally. Discarding the output would worsen UX since the block already executed with potential side effects. Reuse the credit_model obtained during the pre-execution balance check (guarded by `if cost > 0 and credit_model:`) for the post-execution charge; do not perform a second get_user_credit_model call.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-16T16:30:30.764Z
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:30.764Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, explicit try/except in the `run()` method is NOT required for standard error handling. The block framework's `_execute()` method in `_base.py` catches unhandled exceptions and re-raises them as `BlockExecutionError` or `BlockUnknownError`. Additionally, when a block yields `("error", message)`, `_execute()` immediately raises `BlockExecutionError` — so the `error` output port never propagates downstream. Explicit try/except is only needed when partial output must be controlled (e.g., attachment blocks that must skip yielding `content_base64` on failure).
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-16T16:32:29.430Z
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:29.430Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, the Block base class `execute()` method in `backend/blocks/_base.py` already wraps `run()` in a try/except that converts uncaught exceptions into `BlockExecutionError`/`BlockUnknownError`. Therefore, explicit try/except in individual block `run()` methods is redundant and not the established pattern (e.g., Gmail, Slack, Todoist blocks omit it). Exception: blocks like attachment blocks that need to distinguish between success and error yield paths within the generator use explicit try/except for branching control, not for the framework's error routing.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-10T08:39:22.025Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 Learning: 2026-03-16T16:30:20.657Z
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:20.657Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ (and other blocks under autogpt_platform/backend/backend/blocks/), the block executor framework (backend/executor/manager.py lines ~708-733) automatically catches all uncaught exceptions from a block's `run()` method and emits them on the `"error"` output. Explicit try/except blocks within `run()` are therefore not required for standard error propagation — they are only needed when partial output behaviour must be controlled (e.g., preventing some outputs from being yielded on failure, as in attachment blocks). This is the standard pattern across the codebase.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 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/copilot/tools/run_block.pyautogpt_platform/backend/backend/copilot/sdk/tool_adapter.pyautogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.pyautogpt_platform/backend/backend/copilot/sdk/tool_adapter.pyautogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 Learning: 2026-03-04T12:19:39.243Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12279
File: autogpt_platform/backend/backend/copilot/tools/base.py:184-188
Timestamp: 2026-03-04T12:19:39.243Z
Learning: In autogpt_platform/backend/backend/copilot/tools/, ensure that anonymous users always pass user_id=None to tool execution methods. The anon_ prefix (e.g., anon_123) is used only for PostHog/analytics distinct_id and must not be used as an actual user_id. Use a simple truthiness check on user_id (e.g., if user_id: ... else: ... or a dedicated is_authenticated flag) to distinguish anonymous from authenticated users, and review all tool execution call sites within this directory to prevent accidentally forwarding an anon_ user_id to tools.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.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/copilot/tools/run_block.pyautogpt_platform/backend/backend/copilot/sdk/tool_adapter.pyautogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 Learning: 2026-03-10T08:38:30.834Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:349-370
Timestamp: 2026-03-10T08:38:30.834Z
Learning: In the AutoGPT CoPilot HITL flow, the review card presents with editable: false, so the input payload cannot be modified. Therefore credentials resolved before is_block_exec_need_review() remain valid and do not need to be recomputed after the review step. Ensure run_block.py uses the original input_data for credential validation and that any credential caching relies on the pre-review input. If there is any logic that would recompute credentials post-review, guard it against input_data mutations and rely on the UI to enforce immutability. This guideline is specific to autogpt_platform/backend/backend/copilot/tools/run_block.py.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block.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/copilot/tools/run_block.pyautogpt_platform/backend/backend/copilot/sdk/tool_adapter.pyautogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 Learning: 2026-02-20T03:28:06.619Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12173
File: autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py:153-179
Timestamp: 2026-02-20T03:28:06.619Z
Learning: The copilot executor (`backend.copilot.executor`) runs in its own Docker container with Python 3.13, so Python 3.11+ features like `asyncio.timeout()` are available in copilot code even though the general backend pyproject.toml specifies `python = ">=3.10,<3.14"`.
Applied to files:
autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
📚 Learning: 2026-03-17T10:57:10.126Z
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:10.126Z
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:
autogpt_platform/backend/backend/copilot/sdk/collect.pyautogpt_platform/backend/backend/copilot/sdk/service.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 Learning: 2026-03-16T17:00:02.827Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Applied to files:
autogpt_platform/backend/backend/copilot/context.pyautogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 Learning: 2026-03-15T16:52:15.463Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12426
File: autogpt_platform/backend/backend/copilot/sdk/service.py:0-0
Timestamp: 2026-03-15T16:52:15.463Z
Learning: In Significant-Gravitas/AutoGPT (copilot backend), GitHub tokens (GH_TOKEN / GITHUB_TOKEN) for the `gh` CLI are injected lazily per-command in `autogpt_platform/backend/backend/copilot/tools/bash_exec._execute_on_e2b()` by calling `integration_creds.get_integration_env_vars(user_id)`, not on the global SDK subprocess environment in `sdk/service.py`. This scopes credentials to individual E2B sandbox command invocations and prevents token leakage into tool output streams or uploaded transcripts.
Applied to files:
autogpt_platform/backend/backend/copilot/context.py
📚 Learning: 2026-03-10T08:38:33.249Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-03-10T08:38:36.655Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:349-370
Timestamp: 2026-03-10T08:38:36.655Z
Learning: In the AutoGPT CoPilot HITL (Human-In-The-Loop) flow (`autogpt_platform/backend/backend/copilot/tools/run_block.py`), the review card presented to users sets `editable: false`, meaning reviewers cannot modify the input payload. Therefore, credentials resolved before `is_block_exec_need_review()` remain valid and do not need to be recomputed after the review step — the original `input_data` is unchanged through the review lifecycle.
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot.py
📚 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:
autogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 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:
autogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 Learning: 2026-02-04T16:50:51.495Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-04T16:50:51.495Z
Learning: Applies to autogpt_platform/**/data/*.py : For changes touching `data/*.py`, validate user ID checks or explain why not needed
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/backend/blocks/*.py : When adding new blocks, analyze block interfaces to ensure inputs and outputs tie well together for productive graph-based editor connections
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot.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/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/**/test/**/*.py : Use snapshot testing with '--snapshot-update' flag in backend tests when output changes; always review with 'git diff'
Applied to files:
autogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Always review snapshot changes with `git diff` before committing when updating snapshots with `poetry run pytest --snapshot-update`
Applied to files:
autogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Colocate test files with source files using the `*_test.py` naming convention
Applied to files:
autogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/data/**/*.py : All data access in backend requires user ID checks; verify this for any 'data/*.py' changes
Applied to files:
autogpt_platform/backend/backend/copilot/permissions_test.py
🔇 Additional comments (20)
autogpt_platform/backend/backend/copilot/permissions.py (4)
67-86: LGTM!The constants are well-defined with appropriate immutability (frozenset) and pre-compiled regex patterns for efficient UUID matching.
93-107: LGTM!The
_block_matchesfunction correctly implements the documented resolution order with proper case-insensitive matching.
114-214: LGTM!The
CopilotPermissionsmodel correctly implements whitelist/blacklist semantics with proper parent inheritance viamerged_with_parent. The use ofPrivateAttrfor_parentappropriately hides the internal recursion state from the block input schema.
276-327: LGTM!The
apply_tool_permissionsfunction correctly maps short tool names to SDK format and ensures the internalread_filetool remains available for SDK operations.autogpt_platform/backend/backend/copilot/permissions_test.py (4)
1-16: LGTM!The test file is correctly colocated with the source module and imports all the necessary components for comprehensive testing.
22-268: LGTM!Comprehensive test coverage for block matching logic and
CopilotPermissionsmethods including edge cases for inheritance and merging semantics.
275-322: LGTM!The async validation tests properly mock the block registry and cover valid/invalid identifier scenarios. The empty list test works correctly since the loop doesn't iterate.
329-439: LGTM!The
apply_tool_permissionstests properly verify blacklist/whitelist behavior with appropriate mocking. The SDK builtin sanity checks ensure the constant stays in sync with expected tool names.autogpt_platform/backend/backend/copilot/tools/run_block.py (1)
166-188: LGTM!The permission check is correctly placed before execution with clear error messaging. The conditional hint construction properly distinguishes between allow-list and deny-list modes to help users understand why the block was rejected.
autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (1)
73-99: LGTM!The
set_execution_contextfunction is correctly extended to accept and store the permissions contextvar alongside existing context values. The backward-compatible signature withpermissions=Nonedefault is appropriate.autogpt_platform/backend/backend/copilot/sdk/collect.py (1)
39-90: LGTM!The
collect_copilot_responsefunction correctly accepts and forwards the optionalpermissionsparameter to the SDK streaming layer with proper documentation.autogpt_platform/backend/backend/copilot/sdk/service.py (2)
1616-1622: LGTM!The execution context is correctly set with permissions before the SDK stream begins, ensuring tool handlers can access the permission filter via
get_current_permissions().
1648-1654: LGTM!The conditional application of tool permissions correctly uses
apply_tool_permissionswhen a filter is provided, falling back to the standard tool lists otherwise. This maintains backward compatibility while enabling capability restriction.autogpt_platform/backend/backend/copilot/context.py (3)
49-53: LGTM!The new
_current_permissionsContextVar is correctly defined with a default ofNone(unrestricted) and properly typed with a forward reference to avoid import cycles.
70-83: LGTM!The
set_execution_contextfunction is correctly extended to accept and store the optional permissions parameter.
91-94: LGTM!The
get_current_permissionsaccessor provides a clean API for retrieving the active permissions from the execution context.autogpt_platform/backend/backend/blocks/autopilot.py (3)
102-153: LGTM!The new Input fields for capability filtering (
tools,tools_exclude,blocks,blocks_exclude) are well-documented with clear descriptions of the whitelist/blacklist semantics.
359-364: LGTM!Permission validation is correctly performed before session creation, preventing orphaned sessions when invalid tool/block identifiers are provided.
459-498: LGTM!The
_build_and_validate_permissionsfunction properly validates tool names against the known registry and block identifiers against the live block registry before constructing the permissions object.autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py (1)
41-113: Strong coverage for permission validation and inheritance paths.Nice test surface here: you cover allow/deny semantics, block identifier forms, contextvar inheritance behavior, and run-path integration with permission forwarding.
Also applies to: 120-182, 189-259
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/copilot/permissions.py`:
- Around line 315-316: Replace the hardcoded tool name "read_file" with the READ
tool constant so the internal SDK read tool is always included; specifically,
update the code that modifies permitted_sdk (the line with
permitted_sdk.add(f"{MCP_TOOL_PREFIX}read_file")) to use the same symbol used in
tool_adapter.py (i.e., _READ_TOOL_NAME) so the added name is
f"{MCP_TOOL_PREFIX}{_READ_TOOL_NAME}", ensuring MCP_TOOL_PREFIX, _READ_TOOL_NAME
and permitted_sdk are referenced correctly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 71cecda1-acee-42ee-bc7f-8837c44d054f
📒 Files selected for processing (4)
autogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/copilot/tools/run_block.py
✅ Files skipped from review due to trivial changes (2)
- autogpt_platform/backend/backend/copilot/tools/run_block.py
- autogpt_platform/backend/backend/blocks/autopilot.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). (13)
- GitHub Check: check API types
- GitHub Check: end-to-end tests
- GitHub Check: Seer Code Review
- GitHub Check: check-docs-sync
- GitHub Check: Check PR Status
- GitHub Check: test (3.13)
- GitHub Check: test (3.12)
- GitHub Check: type-check (3.13)
- GitHub Check: type-check (3.12)
- GitHub Check: test (3.11)
- GitHub Check: Analyze (python)
- GitHub Check: check-overlaps
- GitHub Check: conflicts
🧰 Additional context used
📓 Path-based instructions (8)
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
Files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
autogpt_platform/backend/**/*.{py,txt}
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use
poetry runprefix for all Python commands, including testing, linting, formatting, and migrations
Files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
autogpt_platform/backend/backend/**/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings
Files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
autogpt_platform/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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
Files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
autogpt_platform/backend/**/*_test.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
autogpt_platform/backend/**/*_test.py: Always review snapshot changes withgit diffbefore committing when updating snapshots withpoetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the*_test.pynaming convention
Files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
autogpt_platform/backend/backend/blocks/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
autogpt_platform/backend/backend/blocks/*.py: When creating new blocks, inherit from theBlockbase class and define input/output schemas usingBlockSchema
Implement blocks with an asyncrunmethod and generate unique block IDs usinguuid.uuid4()
When working with files in blocks, usestore_media_file()frombackend.util.filewith appropriatereturn_formatparameter:for_local_processingfor local tools,for_external_apifor external APIs,for_block_outputfor block outputs
Always usefor_block_outputformat instore_media_file()for block outputs unless there is a specific reason not to
Never hardcode workspace checks when usingstore_media_file()- letfor_block_outputhandle context adaptation automatically
When adding new blocks, analyze block interfaces to ensure inputs and outputs tie well together for productive graph-based editor connections
Files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
autogpt_platform/backend/**/*test*.py
📄 CodeRabbit inference engine (AGENTS.md)
Run
poetry run testfor backend testing (runs pytest with docker based postgres + prisma)
Files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
🧠 Learnings (21)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
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:10.126Z
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.
📚 Learning: 2026-03-16T17:00:02.827Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Applied to files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-03-10T08:39:22.025Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Applied to files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-03-17T10:57:10.126Z
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:10.126Z
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:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-03-10T08:38:33.249Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
Applied to files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 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/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.
Applied to files:
autogpt_platform/backend/backend/copilot/permissions.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/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/autopilot_permissions_test.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/**/test/**/*.py : Use snapshot testing with '--snapshot-update' flag in backend tests when output changes; always review with 'git diff'
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Always review snapshot changes with `git diff` before committing when updating snapshots with `poetry run pytest --snapshot-update`
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Colocate test files with source files using the `*_test.py` naming convention
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-02-04T16:50:51.495Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-04T16:50:51.495Z
Learning: Applies to autogpt_platform/**/data/*.py : For changes touching `data/*.py`, validate user ID checks or explain why not needed
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Use pytest with snapshot testing for API responses in test files
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/autopilot_permissions_test.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/autopilot_permissions_test.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 : Implement 'run' method with proper error handling in backend blocks
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot_permissions_test.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/autopilot_permissions_test.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/autopilot_permissions_test.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/autopilot_permissions_test.py
🔇 Additional comments (9)
autogpt_platform/backend/backend/copilot/permissions.py (5)
1-56: LGTM!Clear and comprehensive module documentation explaining the permission semantics, tool naming conventions, and recursion inheritance pattern.
58-81: LGTM!Constants are appropriately defined as immutable
frozensetand regex patterns are compiled at module level for efficiency.
89-103: LGTM!Clean implementation with proper resolution order (full UUID → partial UUID → name) and case-insensitive matching throughout.
110-210: LGTM!Well-designed model with clean separation between local filtering (
_check_block_locally) and parent inheritance (is_block_allowed). Themerged_with_parentimplementation correctly uses whitelist semantics after intersection to ensure children can only narrow permissions.
217-264: LGTM!Validation helpers are well-structured with lazy imports to avoid circular dependencies. The
validate_block_identifiersinstantiation overhead is acceptable since it only runs during block setup, not in the hot path.autogpt_platform/backend/backend/blocks/autopilot_permissions_test.py (4)
1-34: LGTM!Clean test setup with a well-designed
_make_inputhelper that provides sensible defaults while allowing specific field overrides.
41-112: LGTM!Comprehensive test coverage for
_build_and_validate_permissionsincluding valid/invalid tool names, block identifiers (by name and partial UUID), SDK built-ins, and the optimization to skip block validation when empty.
120-201: LGTM!Thorough coverage of permission inheritance semantics with proper contextvar token cleanup in
finallyblocks. The tests correctly verify that children cannot expand parent permissions.
209-279: LGTM!Well-designed integration tests that verify error handling order (empty prompt before permission validation) and that valid permissions are correctly forwarded to
execute_copilot. The_collect_outputshelper is appropriately simple for these single-yield scenarios.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/integrations/block-integrations/misc.md (1)
46-49: 🛠️ Refactor suggestion | 🟠 MajorAdd technical explanation of the new permission filtering capability.
The "How It Works" section currently omits the new tool and block filtering feature introduced in this PR. Per coding guidelines, this section should include 1-2 paragraphs describing processing logic, validation, and error handling.
Consider adding content that covers:
- How tool and block identifiers are validated at block-run time
- How permissions are enforced during copilot tool invocation
- Parent-child permission inheritance for sub-agent patterns
- Error handling when invalid tool or block names are provided
As per coding guidelines, the "How It Works" section should "Provide a technical explanation of how the block functions, including 1-2 paragraphs describing processing logic, validation, error handling, or edge cases."
🤖 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 46 - 49, Update the "How it works" section (the paragraph describing the block that invokes the copilot via `stream_chat_completion_sdk`) to add 1–2 technical paragraphs explaining the new tool/block permission filtering: describe that tool and block identifiers are validated at block-run time (reject unknown IDs), explain that permissions are enforced when invoking copilot tools (only allowed tools/blocks are passed to the copilot runtime), note parent→child permission inheritance for sub-agent calls (sub-agents inherit and are intersection-limited by parent permissions), and detail error handling and responses for invalid or unauthorized tool/block names (clear validation errors returned and streaming aborted). Ensure the text explicitly references the runtime validation and enforcement steps and the failure behavior so readers understand processing logic, validation, and error handling.
🤖 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`:
- Line 59: The tools list in misc.md is incomplete; update the tools column to
either include the missing tool names (add_understanding, continue_run_block,
create_feature_request, create_folder, delete_folder, get_agent_building_guide,
get_doc_page, get_mcp_guide, list_folders, move_agents_to_folder, move_folder,
search_feature_requests, update_folder) so the table matches the registry, or
replace the hardcoded list with a short note and a link/reference to the
authoritative all_known_tool_names() function in backend.copilot.permissions so
the documentation stays accurate as tools are added; adjust the description text
to remove “(and others)” if you choose the full list or add the reference
callout if you choose the dynamic source.
---
Outside diff comments:
In `@docs/integrations/block-integrations/misc.md`:
- Around line 46-49: Update the "How it works" section (the paragraph describing
the block that invokes the copilot via `stream_chat_completion_sdk`) to add 1–2
technical paragraphs explaining the new tool/block permission filtering:
describe that tool and block identifiers are validated at block-run time (reject
unknown IDs), explain that permissions are enforced when invoking copilot tools
(only allowed tools/blocks are passed to the copilot runtime), note parent→child
permission inheritance for sub-agent calls (sub-agents inherit and are
intersection-limited by parent permissions), and detail error handling and
responses for invalid or unauthorized tool/block names (clear validation errors
returned and streaming aborted). Ensure the text explicitly references the
runtime validation and enforcement steps and the failure behavior so readers
understand processing logic, validation, and error handling.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 20a8f2d8-462d-4af0-9acf-4c1d3663c9f7
📒 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). (5)
- GitHub Check: end-to-end tests
- GitHub Check: test (3.13)
- GitHub Check: test (3.11)
- GitHub Check: test (3.12)
- GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (2)
docs/integrations/**/*.md
📄 CodeRabbit inference engine (docs/CLAUDE.md)
docs/integrations/**/*.md: Provide a technical explanation of how the block functions in the 'How It Works' section, including 1-2 paragraphs describing processing logic, validation, error handling, or edge cases, with code examples in backticks when helpful
Provide exactly 3 practical use cases in the 'Use Case' section, formatted with bold headings followed by short one-sentence descriptions
Files:
docs/integrations/block-integrations/misc.md
docs/**/*.md
📄 CodeRabbit inference engine (docs/CLAUDE.md)
docs/**/*.md: Keep documentation descriptions concise and action-oriented, focusing on practical, real-world scenarios
Use consistent terminology with other blocks and avoid overly technical jargon unless necessary in documentation
Files:
docs/integrations/block-integrations/misc.md
🧠 Learnings (2)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
📚 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
🔇 Additional comments (1)
docs/integrations/block-integrations/misc.md (1)
60-62: Accurate documentation of permission filtering semantics.The documentation for
tools_exclude,blocks, andblocks_excludeaccurately reflects the implementation:
- Default values (True for both exclude flags) match the code
- Blacklist/whitelist semantics are correctly described for both modes
- Empty list behavior (allow everything) is correctly documented
- Block identifier formats (name, full UUID, 8-char prefix) match the implementation
The descriptions are clear, technically precise, and will help users understand how to configure tool and block filtering correctly.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
autogpt_platform/backend/backend/blocks/autopilot.py (1)
280-339:⚠️ Potential issue | 🟠 MajorMove
_merge_inherited_permissions()under the cleanuptry/finally.
_check_recursion()mutates the task-local depth/limit before thetrystarts. If_merge_inherited_permissions()or one of its lazy imports throws,_reset_recursion(tokens)never runs, and later executions in the same task inherit a stale recursion state.🔧 Suggested fix
from backend.copilot.sdk.collect import collect_copilot_response tokens = _check_recursion(max_recursion_depth) - effective_permissions, perm_token = _merge_inherited_permissions(permissions) + perm_token = None try: + effective_permissions, perm_token = _merge_inherited_permissions( + permissions + ) effective_prompt = prompt if system_context: effective_prompt = f"[System Context: {system_context}]\n\n{prompt}"Based on learnings, the approved recursion-guard pattern stores
ContextVartokens and resets them in afinallyblock for every execution path.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@autogpt_platform/backend/backend/blocks/autopilot.py` around lines 280 - 339, Move the call to _merge_inherited_permissions(permissions) so that both _check_recursion(max_recursion_depth) and _merge_inherited_permissions(...) happen inside the same try block, ensuring their ContextVar tokens (tokens and perm_token) are always reset in the finally; specifically, call tokens = _check_recursion(...) and then effective_permissions, perm_token = _merge_inherited_permissions(...) after entering the try, keep the rest of the logic (building effective_prompt, await collect_copilot_response, building tool_calls/usage, and returning) inside that try, and in the finally call _reset_recursion(tokens) and if perm_token is not None: _inherited_permissions.reset(perm_token) so no early exception leaves recursion state mutated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@autogpt_platform/backend/backend/blocks/autopilot.py`:
- Around line 280-339: Move the call to
_merge_inherited_permissions(permissions) so that both
_check_recursion(max_recursion_depth) and _merge_inherited_permissions(...)
happen inside the same try block, ensuring their ContextVar tokens (tokens and
perm_token) are always reset in the finally; specifically, call tokens =
_check_recursion(...) and then effective_permissions, perm_token =
_merge_inherited_permissions(...) after entering the try, keep the rest of the
logic (building effective_prompt, await collect_copilot_response, building
tool_calls/usage, and returning) inside that try, and in the finally call
_reset_recursion(tokens) and if perm_token is not None:
_inherited_permissions.reset(perm_token) so no early exception leaves recursion
state mutated.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f5b9895d-f3b8-4d4c-8e93-5fcca4b8c32d
📒 Files selected for processing (3)
autogpt_platform/backend/backend/blocks/autopilot.pyautogpt_platform/backend/backend/copilot/permissions.pydocs/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). (11)
- GitHub Check: check API types
- GitHub Check: Seer Code Review
- GitHub Check: Analyze (python)
- GitHub Check: Analyze (typescript)
- GitHub Check: Check PR Status
- GitHub Check: end-to-end tests
- GitHub Check: type-check (3.12)
- GitHub Check: test (3.11)
- GitHub Check: test (3.12)
- GitHub Check: test (3.13)
- GitHub Check: conflicts
🧰 Additional context used
📓 Path-based instructions (8)
docs/integrations/**/*.md
📄 CodeRabbit inference engine (docs/CLAUDE.md)
docs/integrations/**/*.md: Provide a technical explanation of how the block functions in the 'How It Works' section, including 1-2 paragraphs describing processing logic, validation, error handling, or edge cases, with code examples in backticks when helpful
Provide exactly 3 practical use cases in the 'Use Case' section, formatted with bold headings followed by short one-sentence descriptions
Files:
docs/integrations/block-integrations/misc.md
docs/**/*.md
📄 CodeRabbit inference engine (docs/CLAUDE.md)
docs/**/*.md: Keep documentation descriptions concise and action-oriented, focusing on practical, real-world scenarios
Use consistent terminology with other blocks and avoid overly technical jargon unless necessary in documentation
Files:
docs/integrations/block-integrations/misc.md
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
Files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
autogpt_platform/backend/**/*.{py,txt}
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use
poetry runprefix for all Python commands, including testing, linting, formatting, and migrations
Files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
autogpt_platform/backend/backend/**/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings
Files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
autogpt_platform/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.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
Files:
autogpt_platform/backend/backend/blocks/autopilot.py
autogpt_platform/backend/backend/blocks/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
autogpt_platform/backend/backend/blocks/*.py: When creating new blocks, inherit from theBlockbase class and define input/output schemas usingBlockSchema
Implement blocks with an asyncrunmethod and generate unique block IDs usinguuid.uuid4()
When working with files in blocks, usestore_media_file()frombackend.util.filewith appropriatereturn_formatparameter:for_local_processingfor local tools,for_external_apifor external APIs,for_block_outputfor block outputs
Always usefor_block_outputformat instore_media_file()for block outputs unless there is a specific reason not to
Never hardcode workspace checks when usingstore_media_file()- letfor_block_outputhandle context adaptation automatically
When adding new blocks, analyze block interfaces to ensure inputs and outputs tie well together for productive graph-based editor connections
Files:
autogpt_platform/backend/backend/blocks/autopilot.py
🧠 Learnings (21)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
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:10.126Z
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.
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.
📚 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-03-10T08:39:22.025Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Applied to files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
📚 Learning: 2026-03-16T17:00:02.827Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Applied to files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
📚 Learning: 2026-03-17T10:57:10.126Z
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:10.126Z
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:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
📚 Learning: 2026-03-10T08:38:33.249Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
Applied to files:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
📚 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:
autogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
📚 Learning: 2026-02-04T16:50:51.495Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-04T16:50:51.495Z
Learning: Applies to autogpt_platform/**/data/*.py : For changes touching `data/*.py`, validate user ID checks or explain why not needed
Applied to files:
autogpt_platform/backend/backend/copilot/permissions.py
📚 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/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.
Applied to files:
autogpt_platform/backend/backend/copilot/permissions.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/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.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/copilot/permissions.pyautogpt_platform/backend/backend/blocks/autopilot.py
📚 Learning: 2026-03-10T08:38:36.655Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:349-370
Timestamp: 2026-03-10T08:38:36.655Z
Learning: In the AutoGPT CoPilot HITL (Human-In-The-Loop) flow (`autogpt_platform/backend/backend/copilot/tools/run_block.py`), the review card presented to users sets `editable: false`, meaning reviewers cannot modify the input payload. Therefore, credentials resolved before `is_block_exec_need_review()` remain valid and do not need to be recomputed after the review step — the original `input_data` is unchanged through the review lifecycle.
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot.py
📚 Learning: 2026-03-15T15:30:09.706Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/tools/helpers.py:149-185
Timestamp: 2026-03-15T15:30:09.706Z
Learning: In autogpt_platform/backend/backend/copilot/tools/helpers.py, within execute_block, when InsufficientBalanceError occurs after post-execution credit charging (concurrent balance drain after pre-check passed), this is treated as a non-fatal billing leak: log at ERROR level with structured JSON fields `{"billing_leak": True, "user_id": ..., "cost": ...}` for monitoring/alerting, then return BlockOutputResponse normally. Discarding the output would worsen UX since the block already executed with potential side effects. Reuse the credit_model obtained during the pre-execution balance check (guarded by `if cost > 0 and credit_model:`) for the post-execution charge; do not perform a second get_user_credit_model call.
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot.py
📚 Learning: 2026-03-15T16:52:15.463Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12426
File: autogpt_platform/backend/backend/copilot/sdk/service.py:0-0
Timestamp: 2026-03-15T16:52:15.463Z
Learning: In Significant-Gravitas/AutoGPT (copilot backend), GitHub tokens (GH_TOKEN / GITHUB_TOKEN) for the `gh` CLI are injected lazily per-command in `autogpt_platform/backend/backend/copilot/tools/bash_exec._execute_on_e2b()` by calling `integration_creds.get_integration_env_vars(user_id)`, not on the global SDK subprocess environment in `sdk/service.py`. This scopes credentials to individual E2B sandbox command invocations and prevents token leakage into tool output streams or uploaded transcripts.
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot.py
📚 Learning: 2026-03-12T14:42:40.552Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/rate_limit.py:141-170
Timestamp: 2026-03-12T14:42:40.552Z
Learning: In Significant-Gravitas/AutoGPT, `check_rate_limit` in `autogpt_platform/backend/backend/copilot/rate_limit.py` is intentionally a "pre-turn soft check" (not a hard atomic reservation). Because LLM token counts are unknown before generation completes, a strict check-and-reserve is impractical. The TOCTOU race (two concurrent turns both passing the pre-check and both committing via `record_token_usage`) is an accepted trade-off. If stricter enforcement is ever needed, the approach is a Lua script doing GET+INCRBY atomically in Redis.
Applied to files:
autogpt_platform/backend/backend/blocks/autopilot.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/autopilot.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/autopilot.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/autopilot.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/autopilot.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/autopilot.py
🔇 Additional comments (2)
autogpt_platform/backend/backend/copilot/permissions.py (1)
180-201:merged_with_parent()keeps the permission ceiling monotonic.Intersecting effective tool sets while delegating block checks through
_parentis a clean way to preserve the “sub-agents can only get stricter” rule without flattening the original block filters.docs/integrations/block-integrations/misc.md (1)
59-62: The new input rows make the filter semantics explicit.Spelling out both the allow-list/deny-list behavior and the accepted block identifier formats should make these advanced controls much easier to discover and use correctly.
There was a problem hiding this comment.
🧹 Nitpick comments (3)
autogpt_platform/backend/backend/copilot/permissions_test.py (2)
330-332: Consider removing the emptysetup_method.The empty
setup_methodwith justpassserves no purpose and can be removed for cleaner code.♻️ Proposed fix
class TestApplyToolPermissions: - def setup_method(self): - # Patch get_copilot_tool_names and get_sdk_disallowed_tools - pass - def test_empty_permissions_returns_base_unchanged(self, mocker):🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@autogpt_platform/backend/backend/copilot/permissions_test.py` around lines 330 - 332, Remove the no-op setup_method defined in permissions_test.py (the empty def setup_method(self): pass) since it adds no behavior; delete the entire method definition from the test class and run tests to verify nothing depended on it (no additional changes to get_copilot_tool_names/get_sdk_disallowed_tools patching are required).
334-354: The conditional patch path may be fragile.The conditional logic checking
hasattr(apply_tool_permissions, "__wrapped__")to determine the patch target is unusual. Ifapply_tool_permissionsis decorated (e.g., with@functools.wraps), the patch target changes. This could lead to test brittleness if the decoration changes.Consider documenting why this conditional is needed or simplifying to a consistent patch target.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@autogpt_platform/backend/backend/copilot/permissions_test.py` around lines 334 - 354, The test's conditional patch path around apply_tool_permissions is fragile; update test_empty_permissions_returns_base_unchanged to patch the consistent module-level symbol "backend.copilot.permissions.apply_tool_permissions" (rather than checking for __wrapped__) so the mock target doesn't change if the function is decorated, and adjust any other mocker.patch calls in the test to reference the stable module-level names (e.g., apply_tool_permissions, get_sdk_disallowed_tools, TOOL_REGISTRY) to keep the test deterministic.autogpt_platform/backend/backend/copilot/tools/run_block_test.py (1)
165-200: Consider strengthening the success assertion.The test verifies that permission-allowed blocks pass the guard, but the assertion at lines 198-200 only checks that if the response is an
ErrorResponse, it doesn't contain "not permitted". This could pass even if the block fails for unrelated reasons.Consider adding a positive assertion to confirm the expected response type (e.g.,
BlockDetailsResponseorBlockOutputResponse) when the block passes all guards, similar totest_non_excluded_block_passes_guardbelow.♻️ Suggested improvement
# Must NOT be blocked by permissions - if isinstance(response, ErrorResponse): - assert "not permitted" not in response.message + assert not isinstance(response, ErrorResponse) or "not permitted" not in response.message + # Optionally, add a stronger assertion for expected success path: + # assert isinstance(response, (BlockDetailsResponse, BlockOutputResponse))🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@autogpt_platform/backend/backend/copilot/tools/run_block_test.py` around lines 165 - 200, The test test_allowed_by_permissions_passes_guard currently only asserts the absence of "not permitted" in an ErrorResponse, which can miss unrelated failures; update the assertion after calling RunBlockTool._execute to positively assert the successful response type (e.g., assert that response is an instance of BlockDetailsResponse or BlockOutputResponse) or otherwise assert that response is not an ErrorResponse, using the concrete response classes used by RunBlockTool._execute to confirm the block actually passed the guard and executed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@autogpt_platform/backend/backend/copilot/permissions_test.py`:
- Around line 330-332: Remove the no-op setup_method defined in
permissions_test.py (the empty def setup_method(self): pass) since it adds no
behavior; delete the entire method definition from the test class and run tests
to verify nothing depended on it (no additional changes to
get_copilot_tool_names/get_sdk_disallowed_tools patching are required).
- Around line 334-354: The test's conditional patch path around
apply_tool_permissions is fragile; update
test_empty_permissions_returns_base_unchanged to patch the consistent
module-level symbol "backend.copilot.permissions.apply_tool_permissions" (rather
than checking for __wrapped__) so the mock target doesn't change if the function
is decorated, and adjust any other mocker.patch calls in the test to reference
the stable module-level names (e.g., apply_tool_permissions,
get_sdk_disallowed_tools, TOOL_REGISTRY) to keep the test deterministic.
In `@autogpt_platform/backend/backend/copilot/tools/run_block_test.py`:
- Around line 165-200: The test test_allowed_by_permissions_passes_guard
currently only asserts the absence of "not permitted" in an ErrorResponse, which
can miss unrelated failures; update the assertion after calling
RunBlockTool._execute to positively assert the successful response type (e.g.,
assert that response is an instance of BlockDetailsResponse or
BlockOutputResponse) or otherwise assert that response is not an ErrorResponse,
using the concrete response classes used by RunBlockTool._execute to confirm the
block actually passed the guard and executed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ec6f8e59-910b-4ef3-a409-9b8f6a24c159
📒 Files selected for processing (2)
autogpt_platform/backend/backend/copilot/permissions_test.pyautogpt_platform/backend/backend/copilot/tools/run_block_test.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). (13)
- GitHub Check: check API types
- GitHub Check: Seer Code Review
- GitHub Check: end-to-end tests
- GitHub Check: Check PR Status
- GitHub Check: test (3.11)
- GitHub Check: type-check (3.13)
- GitHub Check: type-check (3.12)
- GitHub Check: test (3.13)
- GitHub Check: type-check (3.11)
- GitHub Check: test (3.12)
- GitHub Check: Analyze (python)
- GitHub Check: Analyze (typescript)
- GitHub Check: check-docs-sync
🧰 Additional context used
📓 Path-based instructions (6)
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
Files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
autogpt_platform/backend/**/*.{py,txt}
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use
poetry runprefix for all Python commands, including testing, linting, formatting, and migrations
Files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
autogpt_platform/backend/**/*_test.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
autogpt_platform/backend/**/*_test.py: Always review snapshot changes withgit diffbefore committing when updating snapshots withpoetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the*_test.pynaming convention
Files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
autogpt_platform/backend/backend/**/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)
Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings
Files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
autogpt_platform/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
autogpt_platform/backend/**/*test*.py
📄 CodeRabbit inference engine (AGENTS.md)
Run
poetry run testfor backend testing (runs pytest with docker based postgres + prisma)
Files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
🧠 Learnings (19)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
📚 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/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
📚 Learning: 2026-03-16T17:00:02.827Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
📚 Learning: 2026-03-10T08:38:33.249Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.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 : Implement 'run' method with proper error handling in backend blocks
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.py
📚 Learning: 2026-03-10T08:39:22.025Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.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/**/test/**/*.py : Use snapshot testing with '--snapshot-update' flag in backend tests when output changes; always review with 'git diff'
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Always review snapshot changes with `git diff` before committing when updating snapshots with `poetry run pytest --snapshot-update`
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
📚 Learning: 2026-03-16T16:32:29.430Z
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:29.430Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, the Block base class `execute()` method in `backend/blocks/_base.py` already wraps `run()` in a try/except that converts uncaught exceptions into `BlockExecutionError`/`BlockUnknownError`. Therefore, explicit try/except in individual block `run()` methods is redundant and not the established pattern (e.g., Gmail, Slack, Todoist blocks omit it). Exception: blocks like attachment blocks that need to distinguish between success and error yield paths within the generator use explicit try/except for branching control, not for the framework's error routing.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.py
📚 Learning: 2026-03-16T16:30:30.764Z
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:30.764Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, explicit try/except in the `run()` method is NOT required for standard error handling. The block framework's `_execute()` method in `_base.py` catches unhandled exceptions and re-raises them as `BlockExecutionError` or `BlockUnknownError`. Additionally, when a block yields `("error", message)`, `_execute()` immediately raises `BlockExecutionError` — so the `error` output port never propagates downstream. Explicit try/except is only needed when partial output must be controlled (e.g., attachment blocks that must skip yielding `content_base64` on failure).
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.py
📚 Learning: 2026-03-19T15:16:37.702Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12483
File: autogpt_platform/backend/backend/copilot/tools/helpers.py:81-103
Timestamp: 2026-03-19T15:16:37.702Z
Learning: In `autogpt_platform/backend/backend/copilot/tools/helpers.py`, `execute_block()` calls `block.execute()` directly (NOT `block._execute()`). Because of this, a real block CAN yield `("error", "some message")` alongside other output pins, and all outputs are collected. A non-empty `error` pin does NOT mean the block run failed from the caller's perspective — callers see all outputs. Only `[SIMULATOR ERROR ...]` (the dry-run sentinel, distinct from a simulated block logic failure) should map to `ErrorResponse`. Treating any non-empty `error` pin as `ErrorResponse` in dry-run would diverge from real `block.execute()` semantics.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.py
📚 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/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
📚 Learning: 2026-03-04T12:19:39.243Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12279
File: autogpt_platform/backend/backend/copilot/tools/base.py:184-188
Timestamp: 2026-03-04T12:19:39.243Z
Learning: In autogpt_platform/backend/backend/copilot/tools/, ensure that anonymous users always pass user_id=None to tool execution methods. The anon_ prefix (e.g., anon_123) is used only for PostHog/analytics distinct_id and must not be used as an actual user_id. Use a simple truthiness check on user_id (e.g., if user_id: ... else: ... or a dedicated is_authenticated flag) to distinguish anonymous from authenticated users, and review all tool execution call sites within this directory to prevent accidentally forwarding an anon_ user_id to tools.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/run_block_test.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/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.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/copilot/tools/run_block_test.pyautogpt_platform/backend/backend/copilot/permissions_test.py
📚 Learning: 2026-02-04T16:50:51.495Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-04T16:50:51.495Z
Learning: Applies to autogpt_platform/**/data/*.py : For changes touching `data/*.py`, validate user ID checks or explain why not needed
Applied to files:
autogpt_platform/backend/backend/copilot/permissions_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Colocate test files with source files using the `*_test.py` naming convention
Applied to files:
autogpt_platform/backend/backend/copilot/permissions_test.py
📚 Learning: 2026-03-17T10:57:10.126Z
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:10.126Z
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:
autogpt_platform/backend/backend/copilot/permissions_test.py
🔇 Additional comments (11)
autogpt_platform/backend/backend/copilot/permissions_test.py (10)
1-15: LGTM!Clean imports with proper organization. The test file is correctly colocated with the source file following the
*_test.pynaming convention as per coding guidelines.
22-59: LGTM!Comprehensive tests for
_block_matchescovering all identifier matching semantics: full UUID, partial UUID (8-char prefix), and name matching, all with case-insensitivity. The disambiguation test at lines 55-59 is particularly valuable for documenting the expected behavior when an 8-hex string could ambiguously be either a partial UUID or a block name.
72-103: LGTM!Well-structured tests for
effective_allowed_toolscovering both blacklist and whitelist modes, including the important edge case where an empty whitelist allows all tools (lines 77-80). Good coverage of unknown tool handling in both modes.
115-168: LGTM!Excellent coverage of
is_block_allowedincluding the critical parent-child permission inheritance tests (lines 144-168). The tests correctly verify that parent restrictions propagate down the chain and that both parent and child must allow a block for it to be permitted. The grandparent propagation test at lines 162-168 is valuable for ensuring multi-level inheritance works correctly.
176-221: LGTM!Critical tests for
merged_with_parentverifying the security invariant that child permissions cannot expand parent capabilities. The test at lines 195-205 is particularly important for ensuring sub-agents cannot escalate privileges. Good coverage of how merged permissions are stored internally.
229-242: LGTM!Good coverage of
is_emptyincluding the edge case where having a parent with restrictions makes the permissions non-empty (lines 239-242).
250-267: LGTM!Comprehensive tests for synchronous
validate_tool_namescovering registry tools, SDK builtins, invalid tools, mixed inputs, and empty lists. The assertion at line 264 correctly verifies that valid tools don't appear in the error list.
275-321: LGTM!Well-structured async tests for
validate_block_identifierswith consistent mocking ofget_blocks. Good coverage of full UUID, partial UUID, and name-based identifier resolution.
415-470: LGTM! — Addresses past review concern.These two tests (
test_read_tool_always_included_even_when_blacklistedandtest_read_tool_always_included_with_narrow_whitelist) verify the critical invariant thatmcp__copilot__Readis always preserved in the allowed tools list for SDK internals, even when explicitly blacklisted or omitted from a whitelist. This addresses the past review concern about missing coverage for this behavior.
478-495: LGTM!Good sanity check tests verifying that expected SDK builtin tools are present in
SDK_BUILTIN_TOOL_NAMESand thatall_known_tool_names()correctly combines registry tools with builtins.autogpt_platform/backend/backend/copilot/tools/run_block_test.py (1)
135-163: LGTM!Well-structured test for the permission denial path. Good use of try/finally to ensure the contextvar is properly reset regardless of test outcome. The test correctly verifies that a block blacklisted by
CopilotPermissionsreturns anErrorResponsewith "not permitted" in the message.
|
🤖 Fixed in 586ea04: moved |
|
🤖 Fixed in 586ea04: removed the no-op |
|
🤖 Fixed in 586ea04: expanded the AutoPilot "How it works" section to explain tool/block validation at run time, SDK-level enforcement, and parent→child permission inheritance for sub-agent patterns. |
majdyz
left a comment
There was a problem hiding this comment.
🤖 Automated review pass — PR #12482 (AutoPilotBlock tool/block permissions)
Summary
CI is fully green (all 26 checks pass). All previously raised inline threads are resolved.
Findings
No new issues found. The implementation is correct:
- Contextvar hygiene —
_merge_inherited_permissionsreturns a reset token;execute_copilotresets infinally. Prevents permission leakage between sequential autopilot calls. - Read tool always included —
apply_tool_permissionsunconditionally addsmcp__copilot__Readso the SDK's large-output tool is never blocked by permissions. - Inheritance tightening —
merged_with_parentintersects effective-allowed sets so children can only narrow, never widen, the parent's permissions. - Block permission gate —
run_block._executereadsget_current_permissions()and returnsErrorResponsebefore execution when a block is denied. - Validation before session creation — permissions are validated before
create_session, so invalid inputs fail fast without orphaned sessions. - Empty-tools-list semantics —
effective_allowed_toolsreturns the full universe whentools=[]regardless oftools_exclude(allow-all default).
Verdict: LGTM
- Replace hardcoded "read_file" with _READ_TOOL_NAME from tool_adapter so the SDK Read tool is correctly preserved when permissions are applied - Update AutoPilotBlock.Input.tools description to include the complete set of platform tools and SDK built-ins (was missing 13 tools) - Regenerate block docs
- Test that mcp__copilot__Read is always preserved in allowed_tools even when Read is explicitly blacklisted or absent from a whitelist - Test that run_block returns ErrorResponse when CopilotPermissions deny the block, and passes guard when block is explicitly allowed
…y, clean up test nits - Move `_merge_inherited_permissions()` call inside the `try` block so `_reset_recursion()` is always called even if the merge step throws. - Remove the no-op `setup_method` from `TestApplyToolPermissions`. - Replace fragile `__wrapped__` conditional patch path with a direct `get_copilot_tool_names` patch target. - Expand the AutoPilot "How it works" docs section to describe the new tool/block permission filtering, validation, enforcement, and parent→child inheritance for sub-agents.
- Materialize block name map before loop in validate_block_identifiers to avoid N*M block instantiations - Remove dead validate_tool_names call (Pydantic ToolName Literal validates at model construction time) - Add cross-reference comments between PLATFORM_TOOL_NAMES and ToolName Literal declarations
…p-level - Make ToolName Literal the single source of truth; derive PLATFORM_TOOL_NAMES and SDK_BUILTIN_TOOL_NAMES from it instead of maintaining duplicate lists - Move internal imports to top-level where safe (collect.py, service.py, autopilot.py) - Keep circular-import-prone imports (create_chat_session, collect_copilot_response) as local imports with explanatory comments - Add unit tests guarding PLATFORM_TOOL_NAMES == TOOL_REGISTRY keys
Blocks denied by CopilotPermissions are now filtered out of find_block search results and UUID lookups, so the AI never discovers them. This reduces unnecessary back-and-forth where the AI would find a block via search, attempt to run it, and get a permission error.
Move imports from inside test method bodies to the top of the file for consistency with project conventions. Lazy imports in non-test code for circular dependency avoidance are left unchanged.
…sion filtering In E2B mode, SDK built-in file tools (Read, Write, Edit, Glob, Grep) are replaced by MCP equivalents (read_file, write_file, ...). When a user whitelists "Read", the E2B read_file tool must also be included in the permitted set, and vice versa for blacklisting.
1db24df to
a1572ae
Compare
Use a single assert expression instead of conditional check so the test cannot silently pass when the block fails for unrelated reasons.
|
🤖 Addressed remaining review feedback from coderabbitai in 3a83caa:
|
Integrate block-level permission checking from #12482 into the refactored run_block that uses prepare_block_for_execution helper.
#12507) ## Summary - Adds `/pr-test` skill for automated E2E testing of PRs using docker compose, agent-browser, and API calls - Covers full environment setup (copy .env, configure copilot auth, ARM64 Docker fix) - Includes browser UI testing, direct API testing, screenshot capture, and test report generation - Has `--fix` mode for auto-fixing bugs found during testing (similar to `/pr-address`) - **Screenshot uploads use GitHub Git API** (blobs → tree → commit → ref) — no local git operations, safe for worktrees - **Subscription mode improvements:** - Extract subscription auth logic to `sdk/subscription.py` — uses SDK's bundled CLI binary instead of requiring `npm install -g @anthropic-ai/claude-code` - Auto-provision `~/.claude/.credentials.json` from `CLAUDE_CODE_OAUTH_TOKEN` env var on container startup — no `claude login` needed in Docker - Add `scripts/refresh_claude_token.sh` — cross-platform helper (macOS/Linux/Windows) to extract OAuth tokens from host and update `backend/.env` ## Test plan - [x] Validated skill on multiple PRs (#12482, #12483, #12499, #12500, #12501, #12440, #12472) — all test scenarios passed - [x] Confirmed screenshot upload via GitHub Git API renders correctly on all 7 PRs - [x] Verified subscription mode E2E in Docker: `refresh_claude_token.sh` → `docker compose up` → copilot chat responds correctly with no API keys (pure OAuth subscription) - [x] Verified auto-provisioning of credentials file inside container from `CLAUDE_CODE_OAUTH_TOKEN` env var - [x] Confirmed bundled CLI detection (`claude_agent_sdk._bundled/claude`) works without system-installed `claude` - [x] `poetry run pytest backend/copilot/sdk/service_test.py` — 24/24 tests pass
Summary
CopilotPermissionsmodel (copilot/permissions.py) — a capability filter that restricts which tools and blocks the AutoPilot/Copilot may use during a single executionadvanced=Truefields onAutoPilotBlock:tools,tools_exclude,blocks,blocks_excludeAutoPilotBlock→collect_copilot_response→stream_chat_completion_sdk→run_blockDesign
Tool filtering (
tools+tools_exclude):tools_exclude=True(default):toolsis a blacklist — listed tools denied, all others allowed. Empty list = allow all.tools_exclude=False:toolsis a whitelist — only listed tools are allowed.run_block,web_fetch,Read,Task, …) — mapped to full SDK format internally.Block filtering (
blocks+blocks_exclude):run_blockvia contextvar.Recursion inheritance:
_inherited_permissionscontextvar stores the parent execution's permissions.AutoPilotBlock.run(), the child's permissions are merged with the parent viamerged_with_parent()— effective allowed sets are intersected (tools) and the parent chain is kept for block checks.Test plan
copilot/permissions_test.pyandblocks/autopilot_permissions_test.pyvalidate_tool_names/validate_block_identifierswith mock block registryapply_tool_permissionsSDK tool-list integrationAutoPilotBlock.run()— invalid tool/block yields error before session creationAutoPilotBlock.run()— valid permissions forwarded toexecute_copilotAutoPilotBlockblock tests still pass (2/2)