feat(backend): add workspace file move/copy and workspace folder tools - #13700
feat(backend): add workspace file move/copy and workspace folder tools#13700Abhi1992002 wants to merge 4 commits into
Conversation
Add server-side move/copy primitives and folder-management CoPilot tools for the workspace file API. Previously the only way to relocate a workspace file was a 3-call read -> write -> delete workaround that streamed the entire file (base64 for binaries) through the agent context, was non-atomic, and needed a documented skill to execute reliably. New CoPilot tools: - move_workspace_file / copy_workspace_file - create_workspace_folder / delete_workspace_folder / list_workspace_folders - move_workspace_files_to_folder Move is metadata-only (no bytes move); copy uses a server-side blob copy (GCS server-side copy / shutil.copyfile off the event loop), is quota-enforced, and skips the redundant virus scan since the bytes were already scanned on entry.
|
/review |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📜 Recent review details⏰ Context from checks skipped due to timeout. (18)
WalkthroughAdds server-side workspace file move/copy operations and Copilot tools for workspace folder management. The change updates database access, storage backends, tool registration, permissions, API routes, response models, validation, tests, OpenAPI metadata, and integration documentation. ChangesWorkspace organization
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Copilot
participant TransferTool
participant WorkspaceManager
participant Storage
participant Database
Copilot->>TransferTool: request move or copy
TransferTool->>WorkspaceManager: execute file operation
WorkspaceManager->>Storage: copy object when duplicating
WorkspaceManager->>Database: update or create file metadata
Database-->>TransferTool: return WorkspaceFile
TransferTool-->>Copilot: return structured response
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 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 |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev #13700 +/- ##
==========================================
+ Coverage 76.64% 76.71% +0.07%
==========================================
Files 2715 2722 +7
Lines 207923 208929 +1006
Branches 19947 19991 +44
==========================================
+ Hits 159370 160288 +918
- Misses 44153 44284 +131
+ Partials 4400 4357 -43
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
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/data/workspace.py (1)
125-185: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winValidate
folder_idownership before persisting folder membership.
create_workspace_file(...)andupdate_workspace_file_location(...)writefolderIddirectly;folder_idsupplied by callers such asmove_file/copy_fileis forwarded unchanged and is not required to belong toworkspace_id. The same folder-write pattern already guards ownership with_get_folder_record(folder_id, workspace_id), so mirror that check here before creating/updating the file record.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/backend/backend/data/workspace.py` around lines 125 - 185, Validate non-null folder_id belongs to workspace_id before persisting it in create_workspace_file and update_workspace_file_location, using the existing _get_folder_record(folder_id, workspace_id) ownership check. Ensure callers such as move_file and copy_file cannot attach a file to a folder from another workspace, while preserving root-folder behavior when folder_id is None.Source: Path instructions
🧹 Nitpick comments (2)
autogpt_platform/backend/backend/copilot/tools/workspace_folders.py (1)
1-453: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffFile exceeds the ~300-line guideline.
This new file is ~454 lines. Consider splitting by responsibility — e.g., move the response models (
WorkspaceFolderCreatedResponse,WorkspaceFolderDeletedResponse,WorkspaceFolderListResponse,WorkspaceFilesMovedToFolderResponse) and_to_info/_resolve_folderhelpers into a separate module, or split the single-folder tools (create/delete/list) from the bulk-move tool into two files.Based on path instructions: "Keep files under ~300 lines; if a file grows beyond this, split by responsibility (extract helpers, models, or a sub-module into a new file)."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/backend/backend/copilot/tools/workspace_folders.py` around lines 1 - 453, Split workspace_folders.py to keep it under the ~300-line guideline, separating the bulk-move responsibility from the single-folder tools. Move MoveWorkspaceFilesToFolderTool into a dedicated module and update imports/registration as needed, while keeping the shared WorkspaceFolder response models and helpers (_to_info and _resolve_folder) reusable without duplicating them.Source: Path instructions
autogpt_platform/backend/backend/data/workspace_folder_test.py (1)
29-137: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider a direct unit test for
bulk_move_files_to_folder.The renamed tests here cover create/update/delete but not the new
bulk_move_files_to_foldertransaction (scope-building, cross-workspace ID dropping, move+read-back in one tx). It's only exercised via mocks in higher layers; a direct test against the Prisma call args (similar totest_delete_folder_reparents_files_then_soft_deletes) would catch regressions in the transaction/scope logic itself.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/backend/backend/data/workspace_folder_test.py` around lines 29 - 137, Add a direct unit test for bulk_move_files_to_folder, covering transaction-scoped file updates and read-back. Assert workspace scoping, removal of IDs from other workspaces, the move operation’s target folder, and that both Prisma calls use the same transaction client; follow the call-argument and ordering assertions used by test_delete_folder_reparents_files_then_soft_deletes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@autogpt_platform/backend/backend/copilot/tools/workspace_files.py`:
- Around line 845-848: Update the argument-presence check in the workspace file
tool around has_any_content to use is not None rather than truthiness, so
explicitly supplied empty strings count as provided. Include path and mime_type
in the check, along with the other non-default bound inputs relevant to
identifying a truly empty tool call, while preserving the existing truncation
behavior.
In `@autogpt_platform/backend/backend/util/workspace_transfer.py`:
- Around line 34-35: Update move_file and copy_file to validate any supplied
folder_id through a workspace-scoped folder lookup before calling
db.update_workspace_file_location or creating the copied file. Require
UserWorkspaceFolder.workspaceId to match the UserWorkspaceFile.workspaceId, and
reject or fail the operation when the folder is missing or belongs to another
workspace. Apply this validation to every folderId write path identified in
these functions.
---
Outside diff comments:
In `@autogpt_platform/backend/backend/data/workspace.py`:
- Around line 125-185: Validate non-null folder_id belongs to workspace_id
before persisting it in create_workspace_file and
update_workspace_file_location, using the existing _get_folder_record(folder_id,
workspace_id) ownership check. Ensure callers such as move_file and copy_file
cannot attach a file to a folder from another workspace, while preserving
root-folder behavior when folder_id is None.
---
Nitpick comments:
In `@autogpt_platform/backend/backend/copilot/tools/workspace_folders.py`:
- Around line 1-453: Split workspace_folders.py to keep it under the ~300-line
guideline, separating the bulk-move responsibility from the single-folder tools.
Move MoveWorkspaceFilesToFolderTool into a dedicated module and update
imports/registration as needed, while keeping the shared WorkspaceFolder
response models and helpers (_to_info and _resolve_folder) reusable without
duplicating them.
In `@autogpt_platform/backend/backend/data/workspace_folder_test.py`:
- Around line 29-137: Add a direct unit test for bulk_move_files_to_folder,
covering transaction-scoped file updates and read-back. Assert workspace
scoping, removal of IDs from other workspaces, the move operation’s target
folder, and that both Prisma calls use the same transaction client; follow the
call-argument and ordering assertions used by
test_delete_folder_reparents_files_then_soft_deletes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 6efb0012-c757-42a1-b140-29fc5eaa3fe3
📒 Files selected for processing (25)
autogpt_platform/backend/backend/api/features/workspace/folder_routes.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/frontend/src/app/api/openapi.jsondocs/integrations/block-integrations/misc.md
📜 Review details
⏰ Context from checks skipped due to timeout. (14)
- GitHub Check: integration_test
- GitHub Check: lint
- GitHub Check: check API types
- GitHub Check: Seer Code Review
- GitHub Check: Analyze (python)
- GitHub Check: Analyze (typescript)
- GitHub Check: end-to-end tests
- GitHub Check: type-check (3.13)
- GitHub Check: test (3.12)
- GitHub Check: type-check (3.11)
- GitHub Check: type-check (3.12)
- GitHub Check: test (3.13)
- GitHub Check: test (3.11)
- GitHub Check: Check PR Status
🧰 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
autogpt_platform/backend/**/*.py: Usepoetry run ...command for executing Python package dependencies
Use top-level imports only — avoid local/inner imports except for lazy imports of heavy optional dependencies likeopenpyxl
Use absolute imports withfrom backend.module import ...for cross-package imports; single-dot relative imports are acceptable for sibling modules within the same package; avoid double-dot relative imports
Do not use duck typing — avoidhasattr/getattr/isinstancefor type dispatch; use typed interfaces/unions/protocols instead
Use Pydantic models over dataclass/namedtuple/dict for structured data
Do not use linter suppressors — no# type: ignore,# noqa,# pyright: ignore; fix the type/code instead
Prefer list comprehensions over manual loop-and-append patterns
Use early return with guard clauses first to avoid deep nesting
Use%sfor deferred interpolation indebuglog statements for efficiency; use f-strings elsewhere for readability (e.g.,logger.debug("Processing %s items", count)vslogger.info(f"Processing {count} items"))
Sanitize error paths by usingos.path.basename()in error messages to avoid leaking directory structure
Be aware of TOCTOU (Time-Of-Check-Time-Of-Use) issues — avoid check-then-act patterns for file access and credit charging
Usetransaction=Truefor Redis pipelines to ensure atomicity on multi-step operations
Usemax(0, value)guards for computed values that should never be negative
Keep files under ~300 lines; if a file grows beyond this, split by responsibility (extract helpers, models, or a sub-module into a new file)
Keep functions under ~40 lines; extract named helpers when a function grows longer
...
Files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
autogpt_platform/backend/backend/data/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
All data access in backend requires user ID checks; verify this for any 'data/*.py' changes
Files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/data/workspace.py
autogpt_platform/{backend,autogpt_libs}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
autogpt_platform/**/data/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
For changes touching
data/*.py, validate user ID checks or explain why not needed
Files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/data/workspace.py
docs/integrations/**/*.md
📄 CodeRabbit inference engine (docs/AGENTS.md)
docs/integrations/**/*.md: Block documentationhow_it_worksmanual section should provide a technical explanation of the block's processing logic in 1-2 paragraphs, mention validation/error handling/edge cases, and use code examples with backticks
Block documentationuse_casemanual section should provide exactly 3 practical use cases in bold heading format with short one-sentence descriptions
Documentation descriptions should be concise and action-oriented, focusing on practical real-world scenarios with consistent terminology and avoiding overly technical jargon
Files:
docs/integrations/block-integrations/misc.md
autogpt_platform/backend/**/*_test.py
📄 CodeRabbit inference engine (autogpt_platform/backend/AGENTS.md)
autogpt_platform/backend/**/*_test.py: Use pytest with snapshot testing for API responses
Colocate test files with source files using*_test.pynaming convention
Mock at boundaries — mock where the symbol is used, not where it's defined; after refactoring, update mock targets to match new module paths
UseAsyncMockfromunittest.mockfor async functions in tests
When writing tests, use Test-Driven Development (TDD): write failing tests marked with@pytest.mark.xfailbefore implementation, then remove the marker once the implementation is complete
When creating snapshots in tests, usepoetry run pytest path/to/test.py --snapshot-update; always review snapshot changes withgit diffbefore committing
Files:
autogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.py
autogpt_platform/backend/backend/api/features/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Update routes in '/backend/backend/api/features/' and add/update Pydantic models in the same directory for API development
Files:
autogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
autogpt_platform/backend/**/api/**/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/AGENTS.md)
autogpt_platform/backend/**/api/**/*.py: UseSecurity()instead ofDepends()for authentication dependencies to get proper OpenAPI security specification
Follow SSE (Server-Sent Events) protocol: usedata:lines for frontend-parsed events (must match Zod schema) and: commentlines for heartbeats/status
Files:
autogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
🧠 Learnings (22)
📚 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/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.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/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.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/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
📚 Learning: 2026-03-31T15:37:38.626Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12623
File: autogpt_platform/backend/backend/copilot/tools/agent_generator/fixer.py:37-47
Timestamp: 2026-03-31T15:37:38.626Z
Learning: When validating/constructing Anthropic API model IDs in Significant-Gravitas/AutoGPT, allow the hyphen-separated Claude Opus 4.6 model ID `claude-opus-4-6` (it corresponds to `LlmModel.CLAUDE_4_6_OPUS` in `autogpt_platform/backend/backend/blocks/llm.py`). Do NOT require the dot-separated form in Anthropic contexts. Only OpenRouter routing variants should use the dot separator (e.g., `anthropic/claude-opus-4.6`); `claude-opus-4-6` should be treated as correct when passed to Anthropic, and flagged only if it’s used in the OpenRouter path where the dot form is expected.
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
📚 Learning: 2026-04-15T02:43:36.890Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12780
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:0-0
Timestamp: 2026-04-15T02:43:36.890Z
Learning: When reviewing Python exception handlers, do not flag `isinstance(e, X)` checks as dead/unreachable if the caught exception `X` is a subclass of the exception type being handled. For example, if `X` (e.g., `VirusScanError`) inherits from `ValueError` (directly or via an intermediate class) and it can be raised within an `except ValueError:` block, then `isinstance(e, X)` inside that handler is reachable and should not be treated as dead code.
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
📚 Learning: 2026-05-23T05:29:43.085Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13200
File: autogpt_platform/backend/backend/executor/scheduler.py:590-593
Timestamp: 2026-05-23T05:29:43.085Z
Learning: When reviewing Python code that uses Pydantic discriminated/tagged unions (e.g., `Annotated[Union[...], Field(discriminator="kind")]`), recognize that using `isinstance(x, SomeVariantInfo)` to narrow the union is an intentional and correct runtime guard and should also enable static type narrowing in tools like Pyright. Do not recommend replacing such `isinstance`-based narrowing with `cast(...)` when the check already proves the variant at runtime.
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
📚 Learning: 2026-04-21T04:35:34.710Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12865
File: autogpt_platform/backend/backend/data/credit.py:1584-1584
Timestamp: 2026-04-21T04:35:34.710Z
Learning: When reviewing this codebase, don’t flag snake_case attribute names (e.g., `subscription_tier`, `stripe_customer_id`, `top_up_config`) on the app-layer Pydantic `User` model as “wrong” field names. These are correct for the app-layer model and are expected to be mapped from the Prisma-layer camelCase fields (e.g., `subscriptionTier`, `stripeCustomerId`) inside methods like `User.from_db()`. Only Prisma-returned/raw objects would use camelCase, but functions like `get_user_by_id(user_id: str)` are expected to return the Pydantic app-layer model.
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/data/workspace.py
📚 Learning: 2026-05-07T15:32:39.703Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13033
File: autogpt_platform/backend/backend/data/generate_data.py:111-117
Timestamp: 2026-05-07T15:32:39.703Z
Learning: When reviewing the Python data-generation layer, do not treat missing `user_id`/user filtering in calls to graph-metadata resolvers as a security issue if the `graph_id` inputs are already guaranteed to be user-scoped by earlier upstream SQL (e.g., `WHERE "userId" = ...`). In particular, `_resolve_agent_name(graph_id)` in `generate_data.py` correctly calls `get_graph_metadata(graph_id=graph_id)` without a `user_id` parameter by design, because name resolution must also work for user-executed shared/marketplace agents that the user may not own.
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/data/workspace.py
📚 Learning: 2026-04-22T11:46:04.431Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/config.py:0-0
Timestamp: 2026-04-22T11:46:04.431Z
Learning: Do not flag the Claude Sonnet 4.6 model ID as incorrect when it uses the project’s established hyphenated convention: `anthropic/claude-sonnet-4-6`. This hyphen form is the intentional, production convention and should be treated as valid (including in files like llm.py, blocks tests, reasoning.py, `_is_anthropic_model` tests, and config defaults). Note that OpenRouter also accepts the dot variant `anthropic/claude-sonnet-4.6`, so either form may be tolerated, but `anthropic/claude-sonnet-4-6` should be considered the standard to match project usage.
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
📚 Learning: 2026-04-22T11:46:12.892Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/baseline/service.py:322-332
Timestamp: 2026-04-22T11:46:12.892Z
Learning: In this codebase (Significant-Gravitas/AutoGPT), OpenRouter-routed Anthropic model IDs should use the hyphen-separated convention (e.g., `anthropic/claude-sonnet-4-6`, `anthropic/claude-opus-4-6`). Although OpenRouter may accept both hyphen and dot variants, treat the hyphen-separated form as the intended, correct codebase-wide convention and do not flag it as an error. Only flag the dot-separated variant (e.g., `anthropic/claude-sonnet-4.6`) as incorrect when reviewing/validating model ID strings for OpenRouter-routed Anthropic models.
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
📚 Learning: 2026-05-07T18:48:14.242Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13040
File: autogpt_platform/backend/backend/blocks/llm.py:0-0
Timestamp: 2026-05-07T18:48:14.242Z
Learning: In this repository, isort may split imports from the same module into separate blocks when some imports are aliased (e.g., `from module import X as Y`) and others are not. Preserve the two-block layout when it results from isort (such as keeping `from openai.types.chat import ChatCompletion as OpenAIChatCompletion` separate from non-aliased imports from `openai.types.chat`). Do not treat that split as a style issue during review; merging them into a single block can fail CI with `Imports are incorrectly sorted and/or formatted`.
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
📚 Learning: 2026-05-26T14:24:34.866Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13217
File: autogpt_platform/backend/backend/api/features/search/service.py:137-137
Timestamp: 2026-05-26T14:24:34.866Z
Learning: In the Significant-Gravitas/AutoGPT backend, treat `user_id` (an opaque UUID used only for correlation/tracing) as non-PII. Do not flag direct logging of `user_id` in `logger.warning`/`logger.info` statements as a PII exposure issue, as the established convention is to log `user_id` for tracing while reserving PII for fields like email or display name.
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
📚 Learning: 2026-06-11T19:39:10.493Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 13337
File: autogpt_platform/backend/backend/copilot/graphiti/reranker.py:0-0
Timestamp: 2026-06-11T19:39:10.493Z
Learning: In the Significant-Gravitas/AutoGPT Python backend, when calling the OpenAI Python client `chat.completions.create`, construct the `messages` payload using the concrete typed-dict variants from `openai.types.chat` (e.g., `ChatCompletionSystemMessageParam`, `ChatCompletionUserMessageParam`, etc.) rather than trying to instantiate `ChatCompletionMessageParam` directly. `ChatCompletionMessageParam` is a `Union` alias and is not constructible, so `ChatCompletionMessageParam(role=..., content=...)` should fail type checking. Build each message element with the appropriate concrete typed dict and then annotate the resulting list as `list[ChatCompletionMessageParam]` (e.g., `messages: list[ChatCompletionMessageParam] = [ChatCompletionSystemMessageParam(...), ...]`).
Applied to files:
autogpt_platform/backend/backend/data/db_accessors.pyautogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/util/workspace_storage_test.pyautogpt_platform/backend/backend/util/workspace_storage.pyautogpt_platform/backend/backend/data/workspace_folder_test.pyautogpt_platform/backend/backend/util/workspace.pyautogpt_platform/backend/backend/data/db_manager.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/data/workspace_folder.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/util/workspace_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/data/workspace.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/util/workspace_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.pyautogpt_platform/backend/backend/api/features/workspace/folder_routes.py
📚 Learning: 2026-07-21T15:48:34.754Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 13627
File: docs/integrations/block-integrations/llm.md:68-68
Timestamp: 2026-07-21T15:48:34.754Z
Learning: Files under docs/integrations/block-integrations/*.md are generated by autogpt_platform/backend/scripts/generate_block_docs.py. If reviewing a documentation-content change, do it by updating the generator’s authoritative source declarations and regenerate the markdown (or use the generator) rather than making unrelated direct edits to the generated Markdown. CI uses the generator’s --check mode to enforce synchronization, so the generated output must match what the generator produces.
Applied to files:
docs/integrations/block-integrations/misc.md
📚 Learning: 2026-03-01T07:58:56.207Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/api/openapi.json:10030-10037
Timestamp: 2026-03-01T07:58:56.207Z
Learning: When a backend field represents sensitive data, use a secret type (e.g., Pydantic SecretStr with length constraints) so OpenAPI marks it as a password/writeOnly field. Apply this pattern to similar sensitive request fields across API schemas so generated TypeScript clients and docs treat them as secrets and do not mishandle sensitivity. Review all openapi.jsons where sensitive inputs are defined and replace plain strings with SecretStr-like semantics with appropriate minLength constraints.
Applied to files:
autogpt_platform/frontend/src/app/api/openapi.json
📚 Learning: 2026-04-14T06:39:49.111Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12773
File: autogpt_platform/frontend/src/app/api/openapi.json:12803-12806
Timestamp: 2026-04-14T06:39:49.111Z
Learning: In OpenAPI specs, ensure the schema/message length caps for the StreamChatRequest.message and QueuePendingMessageRequest.message fields are set to the intended values: StreamChatRequest.message maxLength must be 64000 and QueuePendingMessageRequest.message maxLength must be 32000. Keep QueuePendingMessageRequest.message consistent with PendingMessage.content, and ensure the pending (queue) ceiling never exceeds the stream ceiling because both ultimately feed the same LLM context window. Update any legacy smaller limits (e.g., 4000/16000) to these newer ceilings.
Applied to files:
autogpt_platform/frontend/src/app/api/openapi.json
📚 Learning: 2026-03-07T07:43:09.871Z
Learnt from: kcze
Repo: Significant-Gravitas/AutoGPT PR: 12328
File: autogpt_platform/frontend/src/app/api/openapi.json:1116-1118
Timestamp: 2026-03-07T07:43:09.871Z
Learning: For autogpt_platform/frontend/src/app/api/openapi.json, preserve the existing behavior: HTTPBearerJWT is declared at the router level with Depends(auth.get_user_id) returning None for unauthenticated users; treat as optional auth. Do not change per-operation security descriptions unless you plan a repo-wide OpenAPI update. If you change this file, prefer clarifying operation descriptions rather than altering security requirements.
Applied to files:
autogpt_platform/frontend/src/app/api/openapi.json
📚 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/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.py
📚 Learning: 2026-04-01T04:17:41.600Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12632
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:0-0
Timestamp: 2026-04-01T04:17:41.600Z
Learning: When reviewing AutoGPT Copilot tool implementations, accept that `readOnlyHint=True` (provided via `ToolAnnotations`) may be applied unconditionally to *all* tools—even tools that have side effects (e.g., `bash_exec`, `write_workspace_file`, or other write/save operations). Do **not** flag these tools for having `readOnlyHint=True`; this is intentional to enable fully-parallel dispatch by the Anthropic SDK/CLI and has been E2E validated. Only flag `readOnlyHint` issues if they conflict with the established `ToolAnnotations` behavior (e.g., missing/incorrect propagation relative to the intended annotation mechanism).
Applied to files:
autogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.py
📚 Learning: 2026-06-06T12:22:37.648Z
Learnt from: anvyle
Repo: Significant-Gravitas/AutoGPT PR: 13302
File: autogpt_platform/backend/backend/copilot/tools/agent_search.py:579-583
Timestamp: 2026-06-06T12:22:37.648Z
Learning: When writing LLM-facing instruction strings that trigger tool calls in this AutoGPT codebase, use the exact registered tool name `view_agent_output` (as defined in `backend/copilot/tools/agent_output.py` via its `name` property and exported via `TOOL_REGISTRY`). Do not reference the bare name `agent_output`, since it is not a valid tool name and will cause tool invocation to fail.
Applied to files:
autogpt_platform/backend/backend/copilot/prompting.pyautogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/copilot/permissions.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_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/tool_schema_test.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.py
📚 Learning: 2026-03-31T14:22:26.566Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12622
File: autogpt_platform/backend/backend/copilot/tools/agent_search.py:223-236
Timestamp: 2026-03-31T14:22:26.566Z
Learning: In files under autogpt_platform/backend/backend/copilot/tools/, ensure agent graph enrichment uses the typed Pydantic model `backend.data.graph.Graph` for `AgentInfo.graph` (i.e., `Graph | None`), not `dict[str, Any]`. When enriching with graph data (e.g., `_enrich_agents_with_graph`), prefer calling `graph_db().get_graph(graph_id, version=None, user_id=user_id)` directly to retrieve the typed `Graph` object rather than routing through JSON conversions like `get_agent_as_json()` / `graph_to_json()`.
Applied to files:
autogpt_platform/backend/backend/copilot/tools/tool_schema_test.pyautogpt_platform/backend/backend/copilot/tools/__init__.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/copilot/tools/workspace_files_test.pyautogpt_platform/backend/backend/copilot/tools/models.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders_test.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.py
🔇 Additional comments (25)
autogpt_platform/backend/backend/copilot/tools/workspace_files.py (1)
864-869: LGTM!autogpt_platform/backend/backend/copilot/tools/workspace_files_test.py (1)
6-13: LGTM!Also applies to: 927-940, 942-986
autogpt_platform/backend/backend/copilot/tools/tool_schema_test.py (1)
100-109: LGTM!autogpt_platform/frontend/src/app/api/openapi.json (1)
20775-20780: LGTM!docs/integrations/block-integrations/misc.md (1)
61-61: 📐 Maintainability & Code QualityVerify this generated documentation was regenerated from its source declaration.
Update the authoritative AutoPilot tool declaration and run the documentation generator’s
--checkmode; otherwise this Markdown change can be overwritten or rejected by CI.Based on learnings, files under
docs/integrations/block-integrations/are generated and must remain synchronized withautogpt_platform/backend/scripts/generate_block_docs.py.Source: Learnings
autogpt_platform/backend/backend/data/db_accessors.py (1)
134-146: LGTM!autogpt_platform/backend/backend/data/db_manager.py (1)
152-160: LGTM!Also applies to: 416-422, 708-714
autogpt_platform/backend/backend/data/workspace_folder.py (1)
103-273: LGTM!autogpt_platform/backend/backend/api/features/workspace/folder_routes.py (1)
17-19: LGTM!Also applies to: 52-57, 67-76, 88-99, 109-117, 125-134
autogpt_platform/backend/backend/api/features/workspace/folder_routes_test.py (1)
85-227: LGTM!autogpt_platform/backend/backend/copilot/tools/models.py (1)
79-86: LGTM!Also applies to: 372-385
autogpt_platform/backend/backend/copilot/tools/workspace_folders_test.py (1)
1-334: LGTM!autogpt_platform/backend/backend/util/workspace_storage.py (3)
88-109: LGTM!
222-254: 🗄️ Data Integrity & IntegrationVerified: GCS server-side copy correctly forwards custom metadata.
Confirmed against the
gcloud-aio-storagelibrary source thatStorage.copy()'smetadatakwarg is treated as the destination object resource body, where custom metadata must be nested under an inner"metadata"key — exactly what this code does. No discrepancy withstore()'s flatmetadata=usage inupload(), since that call takes a different (flatter) shape by design.
392-413: LGTM!autogpt_platform/backend/backend/util/workspace_storage_test.py (1)
48-99: LGTM!autogpt_platform/backend/backend/util/workspace_transfer.py (1)
92-174: LGTM on the rest of copy_file's flow (quota check ordering, blob cleanup on DB failure, self-copy rejection).autogpt_platform/backend/backend/util/workspace.py (1)
445-476: LGTM!autogpt_platform/backend/backend/util/workspace_transfer_test.py (1)
1-335: LGTM!autogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.py (2)
79-139: LGTM!
141-299: LGTM!autogpt_platform/backend/backend/copilot/tools/workspace_file_transfer_test.py (1)
1-264: LGTM!autogpt_platform/backend/backend/copilot/permissions.py (1)
80-92: LGTM!Also applies to: 111-119
autogpt_platform/backend/backend/copilot/tools/__init__.py (1)
60-72: LGTM!Also applies to: 161-167
autogpt_platform/backend/backend/copilot/prompting.py (1)
495-515: LGTM!
move_workspace_file and copy_workspace_file accepted a caller-supplied folder_id and passed it straight through to the write, unlike the sibling move_workspace_files_to_folder tool which verifies the folder belongs to the workspace. A foreign or stale folder_id could mis-file the file or surface as a raw foreign-key error. Validate folder_id against the workspace before writing and return a clean "folder not found" message instead.
There was a problem hiding this comment.
📋 Automated Review — PR #13700
PR #13700 — feat(backend): add workspace file move/copy and workspace folder tools
Author: Abhi1992002 | Files: 25
🎯 Verdict: APPROVE (with Should-Fix items — no traced blockers)
PR Description Quality
✅ Has Why + What + How — the description explains the motivation (replace the read→write→delete relocation anti-pattern), enumerates the six new CoPilot tools, and documents the server-side move (metadata-only) / copy (storage copy()) design plus the truncation-error fix. Author's checklist is fully ticked with a note that DB-backed suites run only in CI.
What This PR Does
Adds six new CoPilot workspace tools — move/copy a file and create/delete/list/bulk-move-to workspace folders — so an agent can relocate or duplicate a file in a single call instead of downloading, re-uploading, and deleting it (which pulled the whole file through model context and process memory). Move is now a pure DB metadata rewrite and copy delegates to native GCS server-side blob copy (or off-loop shutil.copyfile locally), so bytes never transit the process. It also fixes a misleading "truncated" error on write_workspace_file when a filename was simply missing.
Specialist Findings
🛡️ Security ✅ — Skills-registry ACL is solid (raw path and resolved file_info.path are re-checked; get_workspace_manager is always session-scoped so a destination can't resolve to the real registry). Cross-workspace DB writes correctly use update_many guarded on workspaceId + isDeleted, not PK-only update. The one gap it raised — unvalidated folder_id on move/copy (workspace_transfer.py:61,158) — was already fixed in follow-up commit 87c70f33 (_validate_folder now guards both paths), confirmed by the discussion reviewer and a clean CodeRabbit re-review. No active security blocker.
🏗️ Architecture util/workspace_transfer.py, storage-backend copy() abstraction is the right level, RPC folder-function renames are well-motivated.
🟠 FolderAlreadyExistsError (copilot/tools/workspace_folders.py:163) is not in the RPC EXCEPTION_MAPPING (util/service.py:231-234), so on the DatabaseManager RPC path a duplicate-name create is re-raised as HTTPClientError and the actionable "already exists" guidance is lost (still returns an error — graceful degradation, not a crash).
⚡ Performance ✅ — Net win: eliminates full-file transfers in favor of O(1) metadata writes / one blob-copy API call, cost independent of file size in-process. No N+1, no blocking I/O on the event loop (local copy uses asyncio.to_thread). Only minor redundant-query optimizations on non-default paths.
🧪 Testing update_workspace_file_location scoping function (data/workspace.py:370) is fully mocked in every test — its update_many workspace guard is never exercised — and the _check_quota overwrite branch (workspace_transfer.py:213) is untested.
📖 Quality ✅ — Clean, well-documented, good module split. Minor: cross-module private imports (_resolve_file et al. from workspace_files) and a stale docstring referencing a non-existent parentId field (models.py:377).
📦 Product workspace_file_transfer.py:205), and a bulk move where every ID is foreign reports success with "Moved 0 file(s)" (workspace_folders.py:440).
📬 Discussion 87c70f33. Three lower-severity bot findings remain unacknowledged: Sentry MEDIUM (bulk-move defaults to root when no destination given, workspace_folders.py:412), CodeRabbit truncation truthiness (workspace_files.py:848), Sentry LOW TOCTOU quota race.
🔎 QA ✅ — Exercised all six tools against the real backend in Docker: 16/16 scenarios passed, including move-is-metadata-only (storage_unchanged=True), byte-identical copy (CONTENT MATCH: True), collision/overwrite/self-copy/skills-registry guards, foreign-ID reporting, and the truncation fix. 113 tests passed including the DB-backed round-trips the author couldn't run locally. Services logged no errors.
🟠 Should Fix
- RPC exception not reconstructed (
copilot/tools/workspace_folders.py:163) — registerFolderAlreadyExistsErrorinEXCEPTION_MAPPING(or translate at the accessor boundary) so the actionable duplicate-name message survives theDatabaseManagerRPC path; add a test on that path. (Flagged by: architect) - Folder-only move mislabeled as no-op (
workspace_file_transfer.py:205) — the success message branches only on path equality; a same-path move that changesfolder_idis applied but reported as "nothing to do." Include folder change in the no-op check. (Flagged by: product) - Bulk move reports success on zero moves (
workspace_folders.py:440) — return anErrorResponsewhenlen(moved_ids) == 0instead of a success response. Same theme as the Sentry MEDIUM about defaulting to root with no destination (:412). (Flagged by: product, discussion — 2 specialists) - No direct test for
update_workspace_file_location(data/workspace.py:370) — add a mocker-based test (mirroringworkspace_folder_test.py, no Docker needed) asserting theupdate_manywhere-clause includesworkspaceId+isDeleted, that path is leading-slash-normalized, and thatupdated_count==0returnsNone. This is the function carrying the multi-tenant scoping guarantee. (Flagged by: testing) - Quota-overwrite branch untested (
workspace_transfer.py:213) — add a copy test withoverwrite=Truenear the quota ceiling that succeeds only once the occupant's size is subtracted. (Flagged by: testing) - Missing-filename truthiness check (
workspace_files.py:848) — presence should useis not None, else a legitimatecontent=""is misclassified as no-args. (Flagged by: discussion/CodeRabbit)
🟡 Nice to Have
_resolve_folderby-ID does a full list + count aggregation (workspace_folders.py:86) — use the existing targetedget_workspace_folder(folder_id, workspace_id)for the ID branch. (performance)- Redundant destination lookup on overwrite-copy (
workspace_transfer.py:135) — resolve the occupant once, thread into both quota and clear. (performance) - Duplicated
workspace://<id>#<mime>builder (workspace_file_transfer.py:280vsworkspace_files.py:942) — extract one helper. (architect, quality — 2 specialists) format_byteslazy import cycle (workspace_transfer.py:221) — relocate to a lower-level util to break the bidirectional dependency. (architect)- Cross-module private imports (
workspace_file_transfer.py:21) — promote shared_-prefixed symbols to public/shared surface. (quality, architect — 2 specialists) move_workspace_filecannot clear folder to root (workspace_file_transfer.py:195) —Nonemeans "keep" here but "root" elsewhere; clarify or support explicit root. (product)
🔵 Nits
- Stale
parentIddocstring (copilot/tools/models.py:377) —WorkspaceFolderInfoDatahas no such field; drop the clause. (quality) - Vacuous
download.assert_not_called()(workspace_storage_test.py:99) —copy()never calls it, so the assertion is always true; assert against the real client method instead. (testing) - Mime normalization inconsistency —
copyreturns lowercased mime,movereturns raw (workspace_file_transfer.py:291vs:210). (architect)
QA Screenshots
| Screenshot | Description |
|---|---|
![]() |
Artifacts page rendering real tool outputs — renamed.txt (move), copy.txt/dup.txt (copy), and Receipts/Reports folders ✅ |
Human Review Needed
YES — This modifies the multi-tenant authorization boundary (the workspace-scoped update_many guard in update_workspace_file_location), and that scoping function currently has no direct test. A human familiar with the workspace ACL model should confirm the cross-workspace guarantees before merge.
Risk Assessment
Merge risk: LOW | Rollback: EASY — additive tooling behind CoPilot tool registration; move/copy are metadata/storage-API operations with no schema migration in the critical path.
CI Status
Local harness: ✅ frontend lint, ✅ backend lint, ✅ frontend typecheck, ✅ build. test:unit failed in the local sandbox — this is a backend PR with no substantive frontend changes, so this is environment skew, not a code defect (the repo's real suite for these changes is the backend/QA path, where 113 tests passed).
GitHub CI: per discussion reviewer, 20/28 checks green, 6 still running (integration/e2e/py-version matrix), 0 failing, no merge conflicts, Codecov patch 92.98%. Live status not independently re-fetched at synthesis time — treat as in-progress, not final.
UI Testing — Variant Results
✅ local: All six new workspace move/copy/folder tools and the truncation-error fix work end-to-end with correct positive/negative behavior; 113 tests pass and no runtime errors observed.
✅ hosted: All six new workspace move/copy/folder tools and the missing-filename fix work end-to-end against the live DB, storage backend, and UI, with 286 passing tests and correct negative/ACL handling.
- move_workspace_files_to_folder now requires an explicit destination (folder or to_root) instead of silently moving to root, and returns an error when none of the given file IDs were in the workspace. - move_workspace_file no longer reports "nothing to do" when only the folder membership changed (path unchanged). - write_workspace_file detects supplied arguments by presence (is not None) so an explicit empty content="" is no longer misread as a truncated call. - Add direct scoping tests for update_workspace_file_location and a quota test for the overwrite-copy branch.
|
Thanks for the thorough review. Summary of how the feedback was handled: Fixed
Acknowledged / deferred (low-severity, deliberate design or out-of-scope polish; noted inline on each thread):
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@autogpt_platform/backend/backend/data/workspace_test.py`:
- Around line 41-64: Update the test around update_workspace_file_location and
its mocked _file_record to set folderId to "fld-9", then assert the returned
result has folder_id equal to "fld-9" alongside the existing path assertion.
In `@autogpt_platform/backend/backend/util/workspace_transfer_test.py`:
- Around line 343-346: Combine the nested context managers in the test using a
single with statement that manages both _patched and
patch.object(WorkspaceManager, "delete_file", ...), preserving their existing
scopes and mock behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: ab0c205e-b28b-460a-81ca-828ec5fea2f9
📒 Files selected for processing (5)
autogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.pyautogpt_platform/backend/backend/copilot/tools/workspace_files.pyautogpt_platform/backend/backend/copilot/tools/workspace_folders.pyautogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
🚧 Files skipped from review as they are similar to previous changes (3)
- autogpt_platform/backend/backend/copilot/tools/workspace_files.py
- autogpt_platform/backend/backend/copilot/tools/workspace_file_transfer.py
- autogpt_platform/backend/backend/copilot/tools/workspace_folders.py
📜 Review details
⏰ Context from checks skipped due to timeout. (18)
- GitHub Check: check API types
- GitHub Check: lint
- GitHub Check: integration_test
- GitHub Check: Seer Code Review
- GitHub Check: type-check (3.12)
- GitHub Check: test (3.12)
- GitHub Check: type-check (3.13)
- GitHub Check: test (3.13)
- GitHub Check: test (3.11)
- GitHub Check: type-check (3.11)
- GitHub Check: lint
- GitHub Check: end-to-end tests
- GitHub Check: check-docs-sync
- GitHub Check: types
- GitHub Check: lint
- GitHub Check: Analyze (typescript)
- GitHub Check: Analyze (python)
- GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (5)
autogpt_platform/backend/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development
autogpt_platform/backend/**/*.py: Usepoetry run ...command for executing Python package dependencies
Use top-level imports only — avoid local/inner imports except for lazy imports of heavy optional dependencies likeopenpyxl
Use absolute imports withfrom backend.module import ...for cross-package imports; single-dot relative imports are acceptable for sibling modules within the same package; avoid double-dot relative imports
Do not use duck typing — avoidhasattr/getattr/isinstancefor type dispatch; use typed interfaces/unions/protocols instead
Use Pydantic models over dataclass/namedtuple/dict for structured data
Do not use linter suppressors — no# type: ignore,# noqa,# pyright: ignore; fix the type/code instead
Prefer list comprehensions over manual loop-and-append patterns
Use early return with guard clauses first to avoid deep nesting
Use%sfor deferred interpolation indebuglog statements for efficiency; use f-strings elsewhere for readability (e.g.,logger.debug("Processing %s items", count)vslogger.info(f"Processing {count} items"))
Sanitize error paths by usingos.path.basename()in error messages to avoid leaking directory structure
Be aware of TOCTOU (Time-Of-Check-Time-Of-Use) issues — avoid check-then-act patterns for file access and credit charging
Usetransaction=Truefor Redis pipelines to ensure atomicity on multi-step operations
Usemax(0, value)guards for computed values that should never be negative
Keep files under ~300 lines; if a file grows beyond this, split by responsibility (extract helpers, models, or a sub-module into a new file)
Keep functions under ~40 lines; extract named helpers when a function grows longer
...
Files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
autogpt_platform/backend/backend/data/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
All data access in backend requires user ID checks; verify this for any 'data/*.py' changes
Files:
autogpt_platform/backend/backend/data/workspace_test.py
autogpt_platform/{backend,autogpt_libs}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
autogpt_platform/**/data/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
For changes touching
data/*.py, validate user ID checks or explain why not needed
Files:
autogpt_platform/backend/backend/data/workspace_test.py
autogpt_platform/backend/**/*_test.py
📄 CodeRabbit inference engine (autogpt_platform/backend/AGENTS.md)
autogpt_platform/backend/**/*_test.py: Use pytest with snapshot testing for API responses
Colocate test files with source files using*_test.pynaming convention
Mock at boundaries — mock where the symbol is used, not where it's defined; after refactoring, update mock targets to match new module paths
UseAsyncMockfromunittest.mockfor async functions in tests
When writing tests, use Test-Driven Development (TDD): write failing tests marked with@pytest.mark.xfailbefore implementation, then remove the marker once the implementation is complete
When creating snapshots in tests, usepoetry run pytest path/to/test.py --snapshot-update; always review snapshot changes withgit diffbefore committing
Files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
🧠 Learnings (13)
📚 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/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_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/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_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/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
📚 Learning: 2026-03-31T15:37:38.626Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12623
File: autogpt_platform/backend/backend/copilot/tools/agent_generator/fixer.py:37-47
Timestamp: 2026-03-31T15:37:38.626Z
Learning: When validating/constructing Anthropic API model IDs in Significant-Gravitas/AutoGPT, allow the hyphen-separated Claude Opus 4.6 model ID `claude-opus-4-6` (it corresponds to `LlmModel.CLAUDE_4_6_OPUS` in `autogpt_platform/backend/backend/blocks/llm.py`). Do NOT require the dot-separated form in Anthropic contexts. Only OpenRouter routing variants should use the dot separator (e.g., `anthropic/claude-opus-4.6`); `claude-opus-4-6` should be treated as correct when passed to Anthropic, and flagged only if it’s used in the OpenRouter path where the dot form is expected.
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
📚 Learning: 2026-04-15T02:43:36.890Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12780
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:0-0
Timestamp: 2026-04-15T02:43:36.890Z
Learning: When reviewing Python exception handlers, do not flag `isinstance(e, X)` checks as dead/unreachable if the caught exception `X` is a subclass of the exception type being handled. For example, if `X` (e.g., `VirusScanError`) inherits from `ValueError` (directly or via an intermediate class) and it can be raised within an `except ValueError:` block, then `isinstance(e, X)` inside that handler is reachable and should not be treated as dead code.
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
📚 Learning: 2026-05-23T05:29:43.085Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13200
File: autogpt_platform/backend/backend/executor/scheduler.py:590-593
Timestamp: 2026-05-23T05:29:43.085Z
Learning: When reviewing Python code that uses Pydantic discriminated/tagged unions (e.g., `Annotated[Union[...], Field(discriminator="kind")]`), recognize that using `isinstance(x, SomeVariantInfo)` to narrow the union is an intentional and correct runtime guard and should also enable static type narrowing in tools like Pyright. Do not recommend replacing such `isinstance`-based narrowing with `cast(...)` when the check already proves the variant at runtime.
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
📚 Learning: 2026-04-21T04:35:34.710Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12865
File: autogpt_platform/backend/backend/data/credit.py:1584-1584
Timestamp: 2026-04-21T04:35:34.710Z
Learning: When reviewing this codebase, don’t flag snake_case attribute names (e.g., `subscription_tier`, `stripe_customer_id`, `top_up_config`) on the app-layer Pydantic `User` model as “wrong” field names. These are correct for the app-layer model and are expected to be mapped from the Prisma-layer camelCase fields (e.g., `subscriptionTier`, `stripeCustomerId`) inside methods like `User.from_db()`. Only Prisma-returned/raw objects would use camelCase, but functions like `get_user_by_id(user_id: str)` are expected to return the Pydantic app-layer model.
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.py
📚 Learning: 2026-05-07T15:32:39.703Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13033
File: autogpt_platform/backend/backend/data/generate_data.py:111-117
Timestamp: 2026-05-07T15:32:39.703Z
Learning: When reviewing the Python data-generation layer, do not treat missing `user_id`/user filtering in calls to graph-metadata resolvers as a security issue if the `graph_id` inputs are already guaranteed to be user-scoped by earlier upstream SQL (e.g., `WHERE "userId" = ...`). In particular, `_resolve_agent_name(graph_id)` in `generate_data.py` correctly calls `get_graph_metadata(graph_id=graph_id)` without a `user_id` parameter by design, because name resolution must also work for user-executed shared/marketplace agents that the user may not own.
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.py
📚 Learning: 2026-04-22T11:46:04.431Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/config.py:0-0
Timestamp: 2026-04-22T11:46:04.431Z
Learning: Do not flag the Claude Sonnet 4.6 model ID as incorrect when it uses the project’s established hyphenated convention: `anthropic/claude-sonnet-4-6`. This hyphen form is the intentional, production convention and should be treated as valid (including in files like llm.py, blocks tests, reasoning.py, `_is_anthropic_model` tests, and config defaults). Note that OpenRouter also accepts the dot variant `anthropic/claude-sonnet-4.6`, so either form may be tolerated, but `anthropic/claude-sonnet-4-6` should be considered the standard to match project usage.
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
📚 Learning: 2026-04-22T11:46:12.892Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/baseline/service.py:322-332
Timestamp: 2026-04-22T11:46:12.892Z
Learning: In this codebase (Significant-Gravitas/AutoGPT), OpenRouter-routed Anthropic model IDs should use the hyphen-separated convention (e.g., `anthropic/claude-sonnet-4-6`, `anthropic/claude-opus-4-6`). Although OpenRouter may accept both hyphen and dot variants, treat the hyphen-separated form as the intended, correct codebase-wide convention and do not flag it as an error. Only flag the dot-separated variant (e.g., `anthropic/claude-sonnet-4.6`) as incorrect when reviewing/validating model ID strings for OpenRouter-routed Anthropic models.
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
📚 Learning: 2026-05-07T18:48:14.242Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13040
File: autogpt_platform/backend/backend/blocks/llm.py:0-0
Timestamp: 2026-05-07T18:48:14.242Z
Learning: In this repository, isort may split imports from the same module into separate blocks when some imports are aliased (e.g., `from module import X as Y`) and others are not. Preserve the two-block layout when it results from isort (such as keeping `from openai.types.chat import ChatCompletion as OpenAIChatCompletion` separate from non-aliased imports from `openai.types.chat`). Do not treat that split as a style issue during review; merging them into a single block can fail CI with `Imports are incorrectly sorted and/or formatted`.
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
📚 Learning: 2026-05-26T14:24:34.866Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13217
File: autogpt_platform/backend/backend/api/features/search/service.py:137-137
Timestamp: 2026-05-26T14:24:34.866Z
Learning: In the Significant-Gravitas/AutoGPT backend, treat `user_id` (an opaque UUID used only for correlation/tracing) as non-PII. Do not flag direct logging of `user_id` in `logger.warning`/`logger.info` statements as a PII exposure issue, as the established convention is to log `user_id` for tracing while reserving PII for fields like email or display name.
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
📚 Learning: 2026-06-11T19:39:10.493Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 13337
File: autogpt_platform/backend/backend/copilot/graphiti/reranker.py:0-0
Timestamp: 2026-06-11T19:39:10.493Z
Learning: In the Significant-Gravitas/AutoGPT Python backend, when calling the OpenAI Python client `chat.completions.create`, construct the `messages` payload using the concrete typed-dict variants from `openai.types.chat` (e.g., `ChatCompletionSystemMessageParam`, `ChatCompletionUserMessageParam`, etc.) rather than trying to instantiate `ChatCompletionMessageParam` directly. `ChatCompletionMessageParam` is a `Union` alias and is not constructible, so `ChatCompletionMessageParam(role=..., content=...)` should fail type checking. Build each message element with the appropriate concrete typed dict and then annotate the resulting list as `list[ChatCompletionMessageParam]` (e.g., `messages: list[ChatCompletionMessageParam] = [ChatCompletionSystemMessageParam(...), ...]`).
Applied to files:
autogpt_platform/backend/backend/data/workspace_test.pyautogpt_platform/backend/backend/util/workspace_transfer_test.py
🪛 Ruff (0.16.0)
autogpt_platform/backend/backend/util/workspace_transfer_test.py
[warning] 343-346: Use a single with statement with multiple contexts instead of nested with statements
Combine with statements
(SIM117)
🔇 Additional comments (2)
autogpt_platform/backend/backend/data/workspace_test.py (2)
1-33: LGTM!
67-86: LGTM!
Strengthen test_update_location_is_scoped_to_the_workspace so the mocked row carries the new folderId and the test asserts the returned model's folder_id, not just the path.
|
!deploy |
|
🚀 Deploying PR #13700 to development environment... |
|
✅ Preview environment is live (all services healthy)
Push more commits, then comment |

Why / What / How
Why. The workspace file API had no move or copy primitive. The only way to relocate a file was a three-call workaround:
read_workspace_file(file_id, save_to_path=...)— downloads the whole file into the sandboxwrite_workspace_file(filename, path, source_path=...)— uploads it to the new pathdelete_workspace_file(file_id)— deletes the originalThat pulls the entire file through the agent's context — base64-encoded for binary — purely to change a path string. A 2.2 MB PNG burned a large slice of the context budget without a single byte ever being inspected. It also isn't atomic: if the session dies between steps 2 and 3 you end up with two copies and no way to tell which is authoritative. And it's non-obvious enough that it needed a dedicated skill entry to execute reliably — an agent observed without it fell back to rewriting file content from scratch.
Separately, workspace folders (the grouping shown on the Artifacts page, backed by
UserWorkspaceFolder) already existed with a full data layer and REST API, but were invisible to the agent — there were no tools for them at all.What. Six new CoPilot tools:
move_workspace_filecopy_workspace_filecreate_workspace_folderdelete_workspace_folderlist_workspace_foldersmove_workspace_files_to_folderHow. Both transfer operations are server-side; the bytes never enter this process or the model's context.
name/path(and optionallyfolderId) and deliberately leavesstoragePathalone, so no bytes move at all. The stale filename segment left in the blob path is harmless — nothing reads the filename back out ofstoragePath;get_download_urlparses out the file ID only.copy()primitive toWorkspaceStorageBackend: a GCS server-side blob copy, andshutil.copyfile(off the event loop) for local storage. It is quota-enforced but does not re-run the virus scan, since these exact bytes were already scanned bywrite_filewhen they first entered the workspace and a copy cannot change them.Path/folder are two orthogonal concepts here and the tools keep them that way:
move_workspace_filechanges the virtual path,move_workspace_files_to_folderchanges folder membership, and neither affects the other. Tool descriptions spell out the distinction from the existingcreate_folder/delete_foldertools, which manage library folders holding agents.Destination collisions fail by default with an error naming the conflicting path, with
overwrite=trueas the opt-in escape hatch — mirroringwrite_workspace_file. Folder deletion reparents files to the root rather than deleting them, matching the existingDELETE /api/workspace/folders/{id}behavior.Two other issues from the ticket:
filenamefromwrite_workspace_filereported "Tool call appears truncated (no arguments received)" even when plenty of content was supplied.content/content_base64/source_pathare named parameters, so probing**kwargsfor them always came up empty andhas_any_contentwas unconditionallyFalse. Now reads the bound parameters, and the genuine no-arguments case keeps its actionable guidance.Changes 🏗️
New tools
backend/copilot/tools/workspace_file_transfer.py—move_workspace_file/copy_workspace_file, sharing argument resolution and the skills-registry ACL check (enforced on the source path, the destination path, and again on the resolved path when the target was given byfile_id)backend/copilot/tools/workspace_folders.py— the four folder tools; folders resolvable by ID or by case-insensitive nameTransfer layer
backend/util/workspace_transfer.py(new) —move_file/copy_file, including quota enforcement, collision handling, orphaned-blob cleanup when the DB insert fails, and search-index refresh (the index is keyed on name and path). Kept out ofworkspace.py, which is already ~520 linesbackend/util/workspace.py— thinmove_file/copy_filedelegating methodsbackend/util/workspace_storage.py— new abstractcopy()plus GCS and local implementationsData layer
backend/data/workspace.py— newupdate_workspace_file_location, workspace-scoped viaupdate_many(notupdate, which matches on primary key alone and would let a cross-workspace ID or a concurrently-deleted row through);create_workspace_filegains an optionalfolder_idbackend/data/workspace_folder.py— folder functions renamed to workspace-prefixed names so they can be exposed over theDatabaseManagerRPC boundary alongside the identically-named library folder functionsbackend/data/db_accessors.py— newworkspace_folder_db()accessorbackend/data/db_manager.py— RPC exposure for the new file and folder functionsRegistration & generated artifacts
backend/copilot/tools/__init__.py,backend/copilot/permissions.py,backend/copilot/tools/models.py— tool registry entries,ToolNameliteral entries, and response typesfrontend/src/app/api/openapi.json— regenerated; the six newResponseTypeenum values changed the exported schemabackend/copilot/tools/tool_schema_test.py— tool-schema character budget raised for the six new tools, after trimming their descriptionsdocs/integrations/block-integrations/misc.md— regenerated viascripts/generate_block_docs.pyChecklist 📋
For code changes:
backend/util/workspace_transfer_test.py(new, 14 tests) — move rewrites path/name without touching storage; copy delegates to the storagecopy()and never callsretrieve(); quota rejection before any write; collision rejected / overwrite deletes the occupant first; same-path move is a no-op; folder preserved unless overridden; session-scoped path resolution; orphaned blob cleaned up when the DB insert conflictsbackend/copilot/tools/workspace_file_transfer_test.py(new, 19 tests) — response shapes, auth, argument validation, skills-registry ACL by path and byfile_id, error surfacingbackend/copilot/tools/workspace_folders_test.py(new, 20 tests) — all four folder tools including duplicate names, case-insensitive lookup, move-to-root, and files silently dropped as out-of-workspace being reported rather than counted as successbackend/util/workspace_storage_test.py— local copy duplicates bytes and leaves the source intact; missing source raises; GCS copy uses server-side copy without downloadingbackend/copilot/tools/workspace_files_test.py— regression tests for the missing-filenameerror; verified 4 of the 5 fail against the old code while the genuine-truncation case still passesToolNameliteral agree, and that every renamed folder function resolves on both the direct-import and RPC pathspoetry run format,poetry run lint,pyright, andpnpm typesclean; 272 tests pass locallyNote: the DB-backed suites (
folder_routes_test.pyand the round-trip tests inworkspace_files_test.py) could not run in my sandbox — the session-scoped autouse fixture needs Docker Postgres, which isn't available there. Their patch targets were updated for the rename and verified to resolve by import; they run in CI.For configuration changes:
.env.defaultis updated or already compatible with my changesdocker-compose.ymlis updated or already compatible with my changesNo configuration changes.