Skip to content

feat(backend/copilot): parallel block execution via infrastructure-level pre-launch - #12472

Merged
majdyz merged 53 commits into
devfrom
feat/run-block-parallel
Mar 24, 2026
Merged

feat(backend/copilot): parallel block execution via infrastructure-level pre-launch#12472
majdyz merged 53 commits into
devfrom
feat/run-block-parallel

Conversation

@majdyz

@majdyz majdyz commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Implements infrastructure-level parallel tool execution for CoPilot: all tools called in a single LLM turn now execute concurrently with zero changes to individual tool implementations or LLM prompts.
  • Adds pre_launch_tool_call() to tool_adapter.py: when an AssistantMessage with ToolUseBlocks arrives, all tools are immediately fired as asyncio.Tasks before the SDK dispatches MCP handlers. Each MCP handler then awaits its pre-launched task instead of executing fresh.
  • Adds a _tool_task_queues ContextVar (initialized per-session in set_execution_context()) so concurrent sessions never share task queues.
  • DRY refactor: extracts prepare_block_for_execution(), check_hitl_review(), and BlockPreparation dataclass into helpers.py so the execution pipeline is reusable.
  • 10 unit tests for the parallel pre-launch infrastructure (queue enqueue/dequeue, MCP prefix stripping, fallback path, CancelledError handling, multi-same-tool FIFO ordering).

Root cause

The Claude Agent SDK CLI sends MCP tool calls as sequential request-response pairs: it waits for each control_response before issuing the next mcp_message. Even though Python dispatches handlers with start_soon, the CLI never issues call B until call A's response is sent — blocks always ran sequentially. The pre-launch pattern fixes this at the infrastructure level by starting all tasks before the SDK even dispatches the first handler.

Test plan

  • poetry run pytest backend/copilot/sdk/tool_adapter_test.py — 27 tests pass (10 new parallel infra tests)
  • poetry run pytest backend/copilot/tools/helpers_test.py — 20 tests pass
  • poetry run pytest backend/copilot/tools/run_block_test.py backend/copilot/tools/test_run_block_details.py — all pass
  • Manually test in CoPilot: ask the agent to run two blocks simultaneously — verify both start executing before either completes
  • E2E: Both GetCurrentTimeBlock and CalculatorBlock executed concurrently (time=09:35:42, 42×7=294)
  • E2E: Pre-launch mechanism active — two run_block events at same timestamp (3ms apart)
  • E2E: Arg-mismatch fallback tested — system correctly cancels and falls back to direct execution

@majdyz
majdyz requested a review from a team as a code owner March 18, 2026 10:49
@majdyz
majdyz requested review from 0ubbe and ntindle and removed request for a team March 18, 2026 10:49
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban Mar 18, 2026
@github-actions github-actions Bot added platform/frontend AutoGPT Platform - Front end platform/backend AutoGPT Platform - Back end labels Mar 18, 2026
@coderabbitai

coderabbitai Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds per-session background job tracking via a ContextVar, two async tools to start and retrieve background block executions, new job response models, helpers for prepare/HITL flows, refactors run_block to use preparation, and adds tests and OpenAPI enum updates.

Changes

Cohort / File(s) Summary
SDK / Execution Context
autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
Adds _background_jobs: ContextVar[dict[str, asyncio.Task]], initializes it in set_execution_context(), and exposes get_background_jobs() for session-local background job tracking.
Async tools & registry
autogpt_platform/backend/backend/copilot/tools/__init__.py, autogpt_platform/backend/backend/copilot/tools/run_block_async.py, autogpt_platform/backend/backend/copilot/tools/get_block_result.py
Registers run_block_async and get_block_result; adds RunBlockAsyncTool to schedule background block execution and GetBlockResultTool to await/return job results with cancellation, error handling, and cleanup.
Models / API
autogpt_platform/backend/backend/copilot/tools/models.py, autogpt_platform/frontend/src/app/api/openapi.json
Adds ResponseType literals BLOCK_JOB_STARTED and BLOCK_JOB_RESULT; introduces BlockJobStartedResponse and BlockJobResultResponse; updates frontend OpenAPI enum.
Helpers & run flow refactor
autogpt_platform/backend/backend/copilot/tools/helpers.py, autogpt_platform/backend/backend/copilot/tools/run_block.py
Introduces BlockPreparation, prepare_block_for_execution, and check_hitl_review; refactors run_block to a two-stage prepare/HITL flow and re-exports related types; moves credential resolution and input validation into helpers.
Tests
autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py, .../helpers_test.py, .../run_block_test.py, .../test_run_block_details.py
Adds tests for async job start/result flows, preparation and HITL scenarios; updates mocks/patch targets to new helpers; validates cleanup and error paths.

Sequence Diagram

sequenceDiagram
    autonumber
    actor Client
    participant RunBlockAsync as RunBlockAsyncTool
    participant JobRegistry as BackgroundJobs (ContextVar)
    participant Executor as BlockExecutor
    participant GetResult as GetBlockResultTool

    Client->>RunBlockAsync: execute(block_id, inputs)
    RunBlockAsync->>RunBlockAsync: prepare_block_for_execution / check_hitl_review
    RunBlockAsync->>Executor: schedule async Task (job_id)
    RunBlockAsync->>JobRegistry: store Task under job_id
    RunBlockAsync-->>Client: BlockJobStartedResponse(job_id)

    Client->>GetResult: execute(job_id)
    GetResult->>JobRegistry: lookup Task by job_id
    GetResult->>Executor: await Task completion
    Executor-->>GetResult: result or exception
    GetResult->>JobRegistry: remove finished job
    GetResult-->>Client: BlockJobResultResponse / ErrorResponse
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

platform/blocks, Review effort 4/5

Suggested reviewers

  • ntindle
  • 0ubbe
  • Bentlybro

Poem

🐰 I hid some tasks beneath a log,
Launched them swift like hopping fog,
I track each job with tiny paws,
Await the bell, then fetch the cause,
Async carrots, tidy logs, hoorah!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately describes the main change: adding infrastructure for parallel block execution via background job handling (run_block_async and get_block_result tools).
Description check ✅ Passed The PR description is directly related to the changeset, explaining the implementation of run_block_async and get_block_result tools for parallel block execution.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/run-block-parallel

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

🔍 PR Overlap Detection

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

🔴 Merge Conflicts Detected

The following PRs have been tested and will have merge conflicts if merged after this PR. Consider coordinating with the authors.

🟢 Low Risk — File Overlap Only

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

Summary: 3 conflict(s), 0 medium risk, 3 low risk (out of 6 PRs with file overlap)


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

Comment thread autogpt_platform/backend/backend/copilot/tools/run_block_async.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/run_block_async.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/run_block_async.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/get_block_result.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py (1)

100-149: Happy-path test doesn't verify task storage in jobs dict.

The test patches get_background_jobs to return jobs dict but never asserts that a task was actually stored in it. Since the tool returns BlockJobStartedResponse regardless of whether jobs is None (only logs a warning), this test would pass even if the task storage was broken.

Consider adding an assertion that verifies a task was added to the jobs dict:

💡 Suggested addition after line 149
    # Verify task was stored in background jobs
    assert len(jobs) == 1
    assert result.job_id in jobs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py`
around lines 100 - 149, The test uses a mocked get_background_jobs returning the
local jobs dict but never asserts that run_block_async_tool._execute actually
stored the created task in that dict; add assertions after the call to _execute
to verify the task was stored (e.g., assert len(jobs) == 1 and assert
result.job_id in jobs) so the happy-path confirms background job registration
when BlockJobStartedResponse is returned.
autogpt_platform/backend/backend/copilot/tools/run_block_async.py (1)

324-337: Task exceptions are silently swallowed if never awaited.

If get_block_result is never called for a job, exceptions from execute_block will be silently ignored when the task is garbage collected (Python logs "Task exception was never retrieved"). While not a bug, it can make debugging difficult.

Consider adding a done callback to log unhandled exceptions:

💡 Optional improvement
 task = asyncio.create_task(_run())
+task.add_done_callback(
+    lambda t: logger.error(
+        "Background block job failed: %s", t.exception()
+    ) if t.exception() else None
+)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/tools/run_block_async.py` around
lines 324 - 337, The created background task (task from
asyncio.create_task(_run())) can swallow exceptions if never awaited; add a done
callback on the task (after creation, where job_id is stored and
get_background_jobs() is used) that checks task.done() and if task.exception()
is not None logs the exception and context (job_id, session_id, maybe block id)
so unhandled exceptions from _run()/execute_block are surfaced; implement this
in the same block that assigns jobs[job_id] = task using
task.add_done_callback(...) to call a small handler that inspects
task.exception() and calls logger.error with the error and identifiers.
autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (1)

53-59: Consider cleanup for abandoned background jobs.

If a session ends (client disconnects, timeout, etc.) before the user calls get_block_result, background tasks remain in the dict and continue running to completion, but their results are never collected. While this doesn't leak memory indefinitely (the dict is per-session and GC'd when the session context is released), the tasks themselves run unsupervised.

For robustness, consider cancelling pending tasks when the session ends, or at minimum logging a warning in a session-cleanup hook if orphaned tasks exist.

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

In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py` around lines 53
- 59, Session background tasks stored in the ContextVar _background_jobs can be
left running if a session ends before get_block_result is called; update the
session cleanup logic (the code path that tears down set_execution_context()) to
iterate over _background_jobs.get() and cancel any pending asyncio.Tasks created
by run_block_async, optionally awaiting them with a short timeout and removing
them from the dict, and if cancellation is skipped log a warning listing
orphaned job_ids so operators can triage; ensure you reference and mutate the
same ContextVar (_background_jobs) and keep behavior consistent with
run_block_async and get_block_result.
autogpt_platform/backend/backend/copilot/tools/get_block_result.py (1)

84-98: No timeout for awaiting background task.

The await task on line 85 blocks indefinitely until the block execution completes. If a block hangs or takes an extremely long time, this call will never return, potentially causing client timeouts or resource exhaustion.

Consider adding an optional timeout parameter or a reasonable default:

💡 Suggested improvement
+import asyncio
+
+# In parameters property:
+"timeout": {
+    "type": "number",
+    "description": "Maximum seconds to wait for result (default: 300)",
+}

 # In _execute:
+timeout = kwargs.get("timeout", 300.0)
 try:
-    result = await task
+    result = await asyncio.wait_for(task, timeout=timeout)
+except asyncio.TimeoutError:
+    return ErrorResponse(
+        message=f"Block execution timed out after {timeout}s. Job is still running.",
+        session_id=session_id,
+    )
 except Exception as exc:

Note: Don't pop the job on timeout since it's still running — the user may want to retry.

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

In `@autogpt_platform/backend/backend/copilot/tools/get_block_result.py` around
lines 84 - 98, The await on the background "task" can block indefinitely; wrap
the await task in asyncio.wait_for with a configurable timeout (e.g.,
timeout_seconds parameter or a default like DEFAULT_BLOCK_TIMEOUT) inside the
same function that references job_id, jobs, and BlockJobResultResponse, and
handle asyncio.TimeoutError separately: on timeout, log a warning including
job_id and timeout, do NOT pop the job from jobs (since it is still running),
and return a BlockJobResultResponse indicating timeout (success=False,
appropriate message and error string). Also keep the existing Exception handler
for other errors to pop the job and return failure as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@autogpt_platform/backend/backend/copilot/tools/run_block_async.py`:
- Around line 329-337: The code currently logs when get_background_jobs()
returns None but still proceeds to return a BlockJobStartedResponse with job_id;
instead, in the run_block_async pathway that creates task and computes job_id
(variables job_id, task, session_id), detect when jobs is None and return an
ErrorResponse immediately (and keep the warning log) so callers won’t receive a
job_id that can’t be retrieved via get_block_result; modify the branch that
currently does "if jobs is None: logger.warning(...)" to return an ErrorResponse
with a clear message about the missing background job store, otherwise continue
to assign jobs[job_id] = task and return BlockJobStartedResponse as before.

In `@autogpt_platform/frontend/src/app/api/openapi.json`:
- Around line 11968-11969: The ResponseType enum was extended with
"block_job_started" and "block_job_result" but the OpenAPI spec lacks
corresponding schemas; add backend models BlockJobStartedResponse and
BlockJobResultResponse and include them in the tool-response export used by the
/api/chat/schema/tool-responses route (or the module that builds that response
union), update any model exports/imports so the tool-response union references
these new types, then regenerate the OpenAPI JSON (do not hand-edit
autogpt_platform/frontend/src/app/api/openapi.json) so the frontend typings
include the new async block response types.

---

Nitpick comments:
In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py`:
- Around line 53-59: Session background tasks stored in the ContextVar
_background_jobs can be left running if a session ends before get_block_result
is called; update the session cleanup logic (the code path that tears down
set_execution_context()) to iterate over _background_jobs.get() and cancel any
pending asyncio.Tasks created by run_block_async, optionally awaiting them with
a short timeout and removing them from the dict, and if cancellation is skipped
log a warning listing orphaned job_ids so operators can triage; ensure you
reference and mutate the same ContextVar (_background_jobs) and keep behavior
consistent with run_block_async and get_block_result.

In `@autogpt_platform/backend/backend/copilot/tools/get_block_result.py`:
- Around line 84-98: The await on the background "task" can block indefinitely;
wrap the await task in asyncio.wait_for with a configurable timeout (e.g.,
timeout_seconds parameter or a default like DEFAULT_BLOCK_TIMEOUT) inside the
same function that references job_id, jobs, and BlockJobResultResponse, and
handle asyncio.TimeoutError separately: on timeout, log a warning including
job_id and timeout, do NOT pop the job from jobs (since it is still running),
and return a BlockJobResultResponse indicating timeout (success=False,
appropriate message and error string). Also keep the existing Exception handler
for other errors to pop the job and return failure as before.

In `@autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py`:
- Around line 100-149: The test uses a mocked get_background_jobs returning the
local jobs dict but never asserts that run_block_async_tool._execute actually
stored the created task in that dict; add assertions after the call to _execute
to verify the task was stored (e.g., assert len(jobs) == 1 and assert
result.job_id in jobs) so the happy-path confirms background job registration
when BlockJobStartedResponse is returned.

In `@autogpt_platform/backend/backend/copilot/tools/run_block_async.py`:
- Around line 324-337: The created background task (task from
asyncio.create_task(_run())) can swallow exceptions if never awaited; add a done
callback on the task (after creation, where job_id is stored and
get_background_jobs() is used) that checks task.done() and if task.exception()
is not None logs the exception and context (job_id, session_id, maybe block id)
so unhandled exceptions from _run()/execute_block are surfaced; implement this
in the same block that assigns jobs[job_id] = task using
task.add_done_callback(...) to call a small handler that inspects
task.exception() and calls logger.error with the error and identifiers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 51892983-52f3-4cbc-bc13-c9d2b1fd43dd

📥 Commits

Reviewing files that changed from the base of the PR and between 156d61f and d04392d.

📒 Files selected for processing (7)
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/__init__.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/models.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
  • autogpt_platform/frontend/src/app/api/openapi.json
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: check API types
  • GitHub Check: integration_test
  • GitHub Check: Seer Code Review
  • GitHub Check: end-to-end tests
  • GitHub Check: conflicts
  • GitHub Check: type-check (3.11)
  • GitHub Check: type-check (3.12)
  • GitHub Check: type-check (3.13)
  • GitHub Check: test (3.13)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.12)
  • GitHub Check: Check PR Status
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (typescript)
🧰 Additional context used
📓 Path-based instructions (6)
autogpt_platform/backend/**/*.py

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

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

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/models.py
  • autogpt_platform/backend/backend/copilot/tools/__init__.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/models.py
  • autogpt_platform/backend/backend/copilot/tools/__init__.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/models.py
  • autogpt_platform/backend/backend/copilot/tools/__init__.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/models.py
  • autogpt_platform/backend/backend/copilot/tools/__init__.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
autogpt_platform/backend/**/*_test.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

autogpt_platform/backend/**/*_test.py: Always review snapshot changes with git diff before committing when updating snapshots with poetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the *_test.py naming convention

Files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
autogpt_platform/backend/**/*test*.py

📄 CodeRabbit inference engine (AGENTS.md)

Run poetry run test for backend testing (runs pytest with docker based postgres + prisma)

Files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
🧠 Learnings (23)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:20.657Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ blocks (and across the codebase), wrapping synchronous AgentMail SDK calls with `await asyncio.to_thread()` is NOT required. The block executor runs node execution in dedicated threads via `asyncio.run_coroutine_threadsafe` (manager.py lines ~745-752, ~1079), and the existing codebase pattern does not use `asyncio.to_thread` for SDK calls inside async `run()` methods.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Implement 'run' method with proper error handling in backend blocks
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/copilot/workflow_import/converter.py:0-0
Timestamp: 2026-03-17T10:57:10.126Z
Learning: In Significant-Gravitas/AutoGPT PR `#12440`, `autogpt_platform/backend/backend/copilot/workflow_import/converter.py` was fully rewritten (commit 732960e2d) to no longer make direct LLM/OpenAI API calls. The converter now builds a structured text prompt for AutoPilot/CoPilot instead. There is no `response.choices` access or any direct LLM client usage in this file. Do not flag `response.choices` access or LLM client initialization patterns as issues in this file.
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Write tests alongside block implementation when adding new blocks in backend
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12173
File: autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py:153-179
Timestamp: 2026-02-20T03:28:06.619Z
Learning: The copilot executor (`backend.copilot.executor`) runs in its own Docker container with Python 3.13, so Python 3.11+ features like `asyncio.timeout()` are available in copilot code even though the general backend pyproject.toml specifies `python = ">=3.10,<3.14"`.
📚 Learning: 2026-03-16T17:00:02.827Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
📚 Learning: 2026-03-15T16:52:15.463Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12426
File: autogpt_platform/backend/backend/copilot/sdk/service.py:0-0
Timestamp: 2026-03-15T16:52:15.463Z
Learning: In Significant-Gravitas/AutoGPT (copilot backend), GitHub tokens (GH_TOKEN / GITHUB_TOKEN) for the `gh` CLI are injected lazily per-command in `autogpt_platform/backend/backend/copilot/tools/bash_exec._execute_on_e2b()` by calling `integration_creds.get_integration_env_vars(user_id)`, not on the global SDK subprocess environment in `sdk/service.py`. This scopes credentials to individual E2B sandbox command invocations and prevents token leakage into tool output streams or uploaded transcripts.

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/models.py
  • autogpt_platform/backend/backend/copilot/tools/__init__.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.

Applied to files:

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

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/models.py
  • autogpt_platform/backend/backend/copilot/tools/__init__.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
📚 Learning: 2026-02-27T10:45:55.700Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:55.700Z
Learning: As of PR `#12213`, MCP tool response types (MCPToolsDiscoveredResponse, MCPToolOutputResponse) are defined in openapi.json and frontend code in autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx uses the generated types from `@/app/api/__generated__/`. Other tools like RunBlock still use inline TypeScript interfaces (e.g., BlockDetailsResponse) for SSE stream payloads that are not included in openapi.json schemas. The pattern is tool-specific: use generated types when available in openapi.json, use inline types only when the payload schema is truly SSE-stream-only and not exposed via OpenAPI.

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/models.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/models.py
  • autogpt_platform/backend/backend/copilot/tools/__init__.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
📚 Learning: 2026-03-16T16:35:20.978Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/lists.py:96-116
Timestamp: 2026-03-16T16:35:20.978Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ (and any blocks using the AgentMail SDK via `from agentmail import AgentMail`), the SDK supports native async/await. SDK calls such as `client.lists.list(...)`, `client.lists.create(...)`, etc. should be called with `await` directly (e.g., `await client.lists.list(...)`). Do NOT use `asyncio.to_thread()` for these calls — the SDK is natively asynchronous.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/__init__.py
📚 Learning: 2026-03-04T23:57:59.510Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12284
File: autogpt_platform/frontend/src/app/api/openapi.json:5593-5593
Timestamp: 2026-03-04T23:57:59.510Z
Learning: In Significant-Gravitas/AutoGPT backend (FastAPI), openapi.json is autogenerated: descriptions come from route docstrings and schemas from response_model/type annotations. To prevent drift when models are renamed (e.g., AdminView variants), avoid embedding specific schema class names in route docstrings; instead describe behavior, or keep names synced via backend edits—never hand-edit frontend/src/app/api/openapi.json.

Applied to files:

  • autogpt_platform/frontend/src/app/api/openapi.json
📚 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-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-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/backend/blocks/*.py : When adding new blocks, analyze block interfaces to ensure inputs and outputs tie well together for productive graph-based editor connections

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Implement 'run' method with proper error handling in backend blocks

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
📚 Learning: 2026-03-10T08:38:33.249Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-03-16T16:30:20.657Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:20.657Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ blocks (and across the codebase), wrapping synchronous AgentMail SDK calls with `await asyncio.to_thread()` is NOT required. The block executor runs node execution in dedicated threads via `asyncio.run_coroutine_threadsafe` (manager.py lines ~745-752, ~1079), and the existing codebase pattern does not use `asyncio.to_thread` for SDK calls inside async `run()` methods.

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/**/test/**/*.py : Use snapshot testing with '--snapshot-update' flag in backend tests when output changes; always review with 'git diff'

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
📚 Learning: 2026-03-16T16:30:30.764Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/pods.py:62-74
Timestamp: 2026-03-16T16:30:30.764Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, explicit try/except in the `run()` method is NOT required for standard error handling. The block framework's `_execute()` method in `_base.py` catches unhandled exceptions and re-raises them as `BlockExecutionError` or `BlockUnknownError`. Additionally, when a block yields `("error", message)`, `_execute()` immediately raises `BlockExecutionError` — so the `error` output port never propagates downstream. Explicit try/except is only needed when partial output must be controlled (e.g., attachment blocks that must skip yielding `content_base64` on failure).

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Run 'poetry run test' before committing backend changes to ensure all tests pass

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
📚 Learning: 2026-03-16T16:32:29.430Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/pods.py:62-74
Timestamp: 2026-03-16T16:32:29.430Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, the Block base class `execute()` method in `backend/blocks/_base.py` already wraps `run()` in a try/except that converts uncaught exceptions into `BlockExecutionError`/`BlockUnknownError`. Therefore, explicit try/except in individual block `run()` methods is redundant and not the established pattern (e.g., Gmail, Slack, Todoist blocks omit it). Exception: blocks like attachment blocks that need to distinguish between success and error yield paths within the generator use explicit try/except for branching control, not for the framework's error routing.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
🔇 Additional comments (12)
autogpt_platform/backend/backend/copilot/tools/__init__.py (1)

25-25: LGTM!

The new tool imports and registry entries are correctly added. The registry keys ("run_block_async" and "get_block_result") match the corresponding name properties in their tool classes, ensuring proper tool lookup.

Also applies to: 38-38, 74-75

autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (2)

53-59: Appropriate per-session isolation using ContextVar.

The _background_jobs ContextVar pattern correctly mirrors the existing _pending_tool_outputs approach, ensuring concurrent sessions do not share background-job state.

Also applies to: 102-102


131-133: LGTM!

The getter correctly returns None when the ContextVar hasn't been initialized, allowing callers to handle the uninitialized state gracefully.

autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py (2)

169-202: LGTM!

Good test coverage for the result retrieval path. The test correctly:

  • Creates a completed task with mock output
  • Verifies the response type and output values
  • Confirms job cleanup after retrieval (line 202)

156-159: Patch location is correct for get_background_jobs.

The patch targets backend.copilot.sdk.tool_adapter.get_background_jobs, and since the import happens inside _execute (line 67) after the patch is already applied via the with statement, the import will retrieve the patched version. The patch location does not need adjustment.

autogpt_platform/backend/backend/copilot/tools/models.py (2)

43-44: LGTM!

New enum members follow existing naming patterns and are logically grouped under the "Block" section.


479-498: LGTM!

Both response models are well-designed:

  • BlockJobStartedResponse includes all necessary tracking fields (job_id, block_id, block_name)
  • BlockJobResultResponse appropriately handles both success and failure cases with optional outputs and error fields
  • Models follow the established patterns in this file (extending ToolResponseBase, using ResponseType enum)
autogpt_platform/backend/backend/copilot/tools/run_block_async.py (2)

88-111: LGTM!

Input validation is thorough:

  • Empty block_id check
  • Type check for input_data
  • Authentication requirement enforced early

236-308: LGTM!

The HITL review logic correctly:

  • Reuses existing WAITING reviews to avoid duplicates
  • Creates proper synthetic IDs for CoPilot context
  • Returns ReviewRequiredResponse with actionable guidance for the LLM

This matches the documented pattern from retrieved learnings about auto-approval keys.

autogpt_platform/backend/backend/copilot/tools/get_block_result.py (3)

90-98: Error response lacks block metadata.

When an exception occurs, block_id and block_name are set to empty strings. If execute_block fails mid-execution, the task's exception doesn't carry block info. This is acceptable for now but reduces debuggability.


47-65: LGTM!

Validation logic is correct:

  • Validates job_id presence
  • Enforces authentication
  • Handles missing job store gracefully

103-110: Add type checking before accessing result attributes.

The code at lines 103-110 assumes result is a BlockOutputResponse and accesses .block_id, .block_name, .outputs, and .success directly. However, execute_block returns ToolResponseBase, which can be either BlockOutputResponse (with those attributes) or ErrorResponse (without them). Without checking the result type, accessing these attributes on an ErrorResponse will fail.

Add an isinstance check to verify result is a BlockOutputResponse before accessing these attributes, or handle both response types appropriately.

Comment thread autogpt_platform/backend/backend/copilot/tools/run_block_async.py Outdated
Comment thread autogpt_platform/frontend/src/app/api/openapi.json Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/get_block_result.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/run_block_async.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/run_block.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/helpers.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

Inline comments:
In `@autogpt_platform/backend/backend/copilot/tools/get_block_result.py`:
- Around line 58-64: Guard against non-string job_id before calling .strip():
retrieve job_id from kwargs, check isinstance(job_id, str) (or coerce safely)
and only call job_id.strip() when it's a string; if it's missing or not a
string, return the existing ErrorResponse with message "Please provide a job_id"
and session_id. Update the logic in get_block_result (the job_id handling near
the top of the function in get_block_result.py) to validate type first, then
strip, preserving current return behavior for invalid/missing values.

In `@autogpt_platform/backend/backend/copilot/tools/helpers.py`:
- Around line 332-366: The code is building missing_creds_dict from the raw
block.input_schema which can mismatch discriminated credential fields; instead
derive credentials_fields_info from the resolved input_schema (the input_schema
variable) that was generated with discriminator logic and use that when calling
build_missing_credentials_from_field_info; replace the call to
block.input_schema.get_credentials_fields_info() with logic that extracts
credential field info from input_schema (or call an existing helper like
get_credentials_fields_info_from_schema(input_schema) if available) and then
pass that result plus set(matched_credentials.keys()) into
build_missing_credentials_from_field_info to produce missing_creds_dict.

In `@autogpt_platform/backend/backend/copilot/tools/run_block_async.py`:
- Around line 94-111: The code currently calls .strip() on block_id immediately
which throws if block_id is None or non-string; update the validation in
run_block_async (around the block handling that sets block_id = kwargs.get(...))
to first check that block_id is a str (e.g., if not isinstance(block_id, str):
return ErrorResponse(...)) and only then call block_id = block_id.strip(); keep
the existing ErrorResponse for missing block_id and leave the input_data and
user_id checks (input_data dict check and Authentication required) unchanged so
invalid types are handled before any string operations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: be154b2c-156d-4521-b152-18cfc65c7700

📥 Commits

Reviewing files that changed from the base of the PR and between d04392d and bfbaada.

📒 Files selected for processing (5)
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • autogpt_platform/backend/backend/copilot/tools/run_block_async_test.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: check API types
  • GitHub Check: end-to-end tests
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.13)
  • GitHub Check: Seer Code Review
  • GitHub Check: Check PR Status
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (4)
autogpt_platform/backend/**/*.py

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

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

Files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
🧠 Learnings (25)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:20.657Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ blocks (and across the codebase), wrapping synchronous AgentMail SDK calls with `await asyncio.to_thread()` is NOT required. The block executor runs node execution in dedicated threads via `asyncio.run_coroutine_threadsafe` (manager.py lines ~745-752, ~1079), and the existing codebase pattern does not use `asyncio.to_thread` for SDK calls inside async `run()` methods.
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Implement 'run' method with proper error handling in backend blocks
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/copilot/workflow_import/converter.py:0-0
Timestamp: 2026-03-17T10:57:10.126Z
Learning: In Significant-Gravitas/AutoGPT PR `#12440`, `autogpt_platform/backend/backend/copilot/workflow_import/converter.py` was fully rewritten (commit 732960e2d) to no longer make direct LLM/OpenAI API calls. The converter now builds a structured text prompt for AutoPilot/CoPilot instead. There is no `response.choices` access or any direct LLM client usage in this file. Do not flag `response.choices` access or LLM client initialization patterns as issues in this file.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Write tests alongside block implementation when adding new blocks in backend
📚 Learning: 2026-03-10T08:38:36.655Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:349-370
Timestamp: 2026-03-10T08:38:36.655Z
Learning: In the AutoGPT CoPilot HITL (Human-In-The-Loop) flow (`autogpt_platform/backend/backend/copilot/tools/run_block.py`), the review card presented to users sets `editable: false`, meaning reviewers cannot modify the input payload. Therefore, credentials resolved before `is_block_exec_need_review()` remain valid and do not need to be recomputed after the review step — the original `input_data` is unchanged through the review lifecycle.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-03-10T08:38:33.249Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-03-10T08:39:22.025Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/backend/blocks/*.py : When adding new blocks, analyze block interfaces to ensure inputs and outputs tie well together for productive graph-based editor connections

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Implement 'run' method with proper error handling in backend blocks

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-15T15:30:02.282Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/tools/helpers.py:149-185
Timestamp: 2026-03-15T15:30:02.282Z
Learning: In autogpt_platform/backend/backend/copilot/tools/helpers.py, inside execute_block: when InsufficientBalanceError occurs after post-execution credit charging (i.e., balance drained concurrently after pre-check passed), treat as a non-fatal billing leak. Log at ERROR level with structured JSON: {"billing_leak": True, "user_id": ..., "cost": ...} for monitoring/alerting, then return BlockOutputResponse normally (do not discard the output). Do not perform a second get_user_credit_model call; reuse the credit_model obtained during the pre-execution balance check (guarded by if cost > 0 and credit_model:). This guidance improves UX by not discarding results and provides observable billing leak signals.

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.

Applied to files:

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

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-16T16:30:20.657Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:20.657Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ blocks (and across the codebase), wrapping synchronous AgentMail SDK calls with `await asyncio.to_thread()` is NOT required. The block executor runs node execution in dedicated threads via `asyncio.run_coroutine_threadsafe` (manager.py lines ~745-752, ~1079), and the existing codebase pattern does not use `asyncio.to_thread` for SDK calls inside async `run()` methods.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-03-16T16:30:30.764Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/pods.py:62-74
Timestamp: 2026-03-16T16:30:30.764Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, explicit try/except in the `run()` method is NOT required for standard error handling. The block framework's `_execute()` method in `_base.py` catches unhandled exceptions and re-raises them as `BlockExecutionError` or `BlockUnknownError`. Additionally, when a block yields `("error", message)`, `_execute()` immediately raises `BlockExecutionError` — so the `error` output port never propagates downstream. Explicit try/except is only needed when partial output must be controlled (e.g., attachment blocks that must skip yielding `content_base64` on failure).

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-16T16:32:29.430Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/pods.py:62-74
Timestamp: 2026-03-16T16:32:29.430Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, the Block base class `execute()` method in `backend/blocks/_base.py` already wraps `run()` in a try/except that converts uncaught exceptions into `BlockExecutionError`/`BlockUnknownError`. Therefore, explicit try/except in individual block `run()` methods is redundant and not the established pattern (e.g., Gmail, Slack, Todoist blocks omit it). Exception: blocks like attachment blocks that need to distinguish between success and error yield paths within the generator use explicit try/except for branching control, not for the framework's error routing.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-02-27T10:45:55.700Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:55.700Z
Learning: As of PR `#12213`, MCP tool response types (MCPToolsDiscoveredResponse, MCPToolOutputResponse) are defined in openapi.json and frontend code in autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx uses the generated types from `@/app/api/__generated__/`. Other tools like RunBlock still use inline TypeScript interfaces (e.g., BlockDetailsResponse) for SSE stream payloads that are not included in openapi.json schemas. The pattern is tool-specific: use generated types when available in openapi.json, use inline types only when the payload schema is truly SSE-stream-only and not exposed via OpenAPI.

Applied to files:

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

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/backend/blocks/*.py : When creating new blocks, inherit from the `Block` base class and define input/output schemas using `BlockSchema`

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-02-05T04:11:15.945Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11796
File: autogpt_platform/backend/backend/blocks/video/concat.py:3-4
Timestamp: 2026-02-05T04:11:15.945Z
Learning: Block IDs in autogpt_platform/backend/backend/blocks/**/*.py must be stable, hard-coded UUID strings. When initially creating a new block, generate a UUID once using `uuid.uuid4()` and then hard-code that UUID string as the block's `id` parameter. Do not call uuid.uuid4() dynamically at runtime, as block IDs must remain constant across all imports and runs.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-03-15T15:30:09.706Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/tools/helpers.py:149-185
Timestamp: 2026-03-15T15:30:09.706Z
Learning: In autogpt_platform/backend/backend/copilot/tools/helpers.py, within execute_block, when InsufficientBalanceError occurs after post-execution credit charging (concurrent balance drain after pre-check passed), this is treated as a non-fatal billing leak: log at ERROR level with structured JSON fields `{"billing_leak": True, "user_id": ..., "cost": ...}` for monitoring/alerting, then return BlockOutputResponse normally. Discarding the output would worsen UX since the block already executed with potential side effects. Reuse the credit_model obtained during the pre-execution balance check (guarded by `if cost > 0 and credit_model:`) for the post-execution charge; do not perform a second get_user_credit_model call.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-16T16:30:20.657Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:20.657Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ (and other blocks under autogpt_platform/backend/backend/blocks/), the block executor framework (backend/executor/manager.py lines ~708-733) automatically catches all uncaught exceptions from a block's `run()` method and emits them on the `"error"` output. Explicit try/except blocks within `run()` are therefore not required for standard error propagation — they are only needed when partial output behaviour must be controlled (e.g., preventing some outputs from being yielded on failure, as in attachment blocks). This is the standard pattern across the codebase.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-03-10T08:38:29.078Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:29.078Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review is session-scoped: it uses graph_exec_id (copilot-session-{session_id}) combined with node_id (copilot-node-{block_id}). If the user enables the auto-approve toggle for a CoPilot session, approving a block type in that session automatically approves all future invocations of that same block type within the same session. If the user does not toggle auto-approve (default), each individual invocation requires its own approval. This behavior should be clearly documented in code and comments, and tested to ensure the toggle reliably toggles between session-scoped auto-approval and per-invocation approval.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-03-10T08:38:30.834Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:349-370
Timestamp: 2026-03-10T08:38:30.834Z
Learning: In the AutoGPT CoPilot HITL flow, the review card presents with editable: false, so the input payload cannot be modified. Therefore credentials resolved before is_block_exec_need_review() remain valid and do not need to be recomputed after the review step. Ensure run_block.py uses the original input_data for credential validation and that any credential caching relies on the pre-review input. If there is any logic that would recompute credentials post-review, guard it against input_data mutations and rely on the UI to enforce immutability. This guideline is specific to autogpt_platform/backend/backend/copilot/tools/run_block.py.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
🔇 Additional comments (2)
autogpt_platform/backend/backend/copilot/tools/get_block_result.py (1)

108-121: Nice result-type guard.

Returning non-BlockOutputResponse results directly avoids attribute-access failures when execute_block() surfaces an ErrorResponse.

autogpt_platform/backend/backend/copilot/tools/run_block.py (1)

119-177: Shared prep/HITL flow looks good.

RunBlockTool now stays focused on the two-step schema-preview UX while validation and execution rules live in one place.

Comment thread autogpt_platform/backend/backend/copilot/tools/get_block_result.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/helpers.py
Comment thread autogpt_platform/backend/backend/copilot/tools/run_block_async.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
autogpt_platform/backend/backend/copilot/tools/run_block_async.py (1)

93-100: ⚠️ Potential issue | 🟠 Major

Guard block_id before calling .strip().

Line 93 assumes block_id is a str. Non-string inputs can fail before this path returns a validation error.

Suggested fix
-        block_id = kwargs.get("block_id", "").strip()
+        raw_block_id = kwargs.get("block_id", "")
         input_data = kwargs.get("input_data", {})
         session_id = session.session_id
+
+        if not isinstance(raw_block_id, str):
+            return ErrorResponse(
+                message="block_id must be a string",
+                session_id=session_id,
+            )
+        block_id = raw_block_id.strip()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/tools/run_block_async.py` around
lines 93 - 100, The code calls .strip() on kwargs.get("block_id") assuming it's
a string; first retrieve the raw value (e.g., raw_block_id =
kwargs.get("block_id", None)) and validate its type before stripping: if
raw_block_id is None or not isinstance(raw_block_id, str) return
ErrorResponse(message="Please provide a block_id",
session_id=session.session_id); otherwise set block_id = raw_block_id.strip()
and continue. Update the logic around block_id, raw_block_id, ErrorResponse and
session.session_id in run_block_async to avoid calling .strip() on non-strings.
autogpt_platform/backend/backend/copilot/tools/get_block_result.py (1)

59-65: ⚠️ Potential issue | 🟠 Major

Guard job_id before calling .strip().

Line 59 assumes job_id is a str. Non-string inputs can fail before this tool returns its normal validation response.

Suggested fix
-        job_id = kwargs.get("job_id", "").strip()
+        raw_job_id = kwargs.get("job_id", "")
         session_id = session.session_id
+
+        if not isinstance(raw_job_id, str):
+            return ErrorResponse(
+                message="job_id must be a string",
+                session_id=session_id,
+            )
+        job_id = raw_job_id.strip()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/tools/get_block_result.py` around
lines 59 - 65, The code calls .strip() on kwargs.get("job_id", "") assuming a
string; first retrieve the raw value (e.g., raw_job_id = kwargs.get("job_id")),
then validate its type before stripping: if raw_job_id is None or not
isinstance(raw_job_id, str) return the same ErrorResponse (using
session.session_id) or convert non-string inputs safely (e.g., cast to str) per
API contract; update the logic around job_id, the .strip() call, and the
ErrorResponse return to use this guarded value so get_block_result (and the
local job_id variable) never calls .strip() on a non-string.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@autogpt_platform/backend/backend/copilot/tools/get_block_result.py`:
- Around line 90-102: In get_block_result, protect awaiting the background task
by wrapping the await in asyncio.shield(task) so cancellation of the outer await
won't propagate into the underlying task; after the shielded await, only
pop/remove the task from the jobs registry (jobs.pop(job_id, None)) if the
actual task is cancelled or finished as intended (inspect task.cancelled() /
task.done()), and when handling asyncio.CancelledError return the
BlockJobResultResponse without having orphaned the real background task; update
references to task, jobs, job_id, and BlockJobResultResponse accordingly.

In `@autogpt_platform/backend/backend/copilot/tools/helpers_test.py`:
- Around line 711-733: The HITL test helper _make_hitl_prep currently generates
synthetic_graph_id and synthetic_node_id using underscore-based strings; update
it to match production CoPilot formatting by using the hyphenated keys (e.g.,
synthetic_graph_id = f"copilot-session-{session_id}" and synthetic_node_id =
f"copilot-node-{block_id}") or, if there are exportable CoPilot constants for
those formats, reference those constants instead so tests mirror runtime ID
semantics used by BlockPreparation and any assertions elsewhere.
- Line 720: The fixture helper _make_hitl_prep currently sets data = input_data
or {"action": "delete"}, which treats empty dicts as falsy and overwrites
intentionally empty inputs; change that to an explicit None check so that if
input_data is None you assign the default payload, otherwise use the provided
input_data (e.g., if input_data is None: data = {"action":"delete"} else: data =
input_data) — update the _make_hitl_prep helper to use this None-check with the
input_data parameter.

---

Duplicate comments:
In `@autogpt_platform/backend/backend/copilot/tools/get_block_result.py`:
- Around line 59-65: The code calls .strip() on kwargs.get("job_id", "")
assuming a string; first retrieve the raw value (e.g., raw_job_id =
kwargs.get("job_id")), then validate its type before stripping: if raw_job_id is
None or not isinstance(raw_job_id, str) return the same ErrorResponse (using
session.session_id) or convert non-string inputs safely (e.g., cast to str) per
API contract; update the logic around job_id, the .strip() call, and the
ErrorResponse return to use this guarded value so get_block_result (and the
local job_id variable) never calls .strip() on a non-string.

In `@autogpt_platform/backend/backend/copilot/tools/run_block_async.py`:
- Around line 93-100: The code calls .strip() on kwargs.get("block_id") assuming
it's a string; first retrieve the raw value (e.g., raw_block_id =
kwargs.get("block_id", None)) and validate its type before stripping: if
raw_block_id is None or not isinstance(raw_block_id, str) return
ErrorResponse(message="Please provide a block_id",
session_id=session.session_id); otherwise set block_id = raw_block_id.strip()
and continue. Update the logic around block_id, raw_block_id, ErrorResponse and
session.session_id in run_block_async to avoid calling .strip() on non-strings.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3605fa3f-7a0d-4f01-ae74-ede9d51787c0

📥 Commits

Reviewing files that changed from the base of the PR and between bfbaada and c3ff8c1.

📒 Files selected for processing (4)
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: end-to-end tests
  • GitHub Check: test (3.13)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.11)
  • GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (6)
autogpt_platform/backend/**/*.py

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

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

Files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
autogpt_platform/backend/**/*_test.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

autogpt_platform/backend/**/*_test.py: Always review snapshot changes with git diff before committing when updating snapshots with poetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the *_test.py naming convention

Files:

  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
autogpt_platform/backend/**/*test*.py

📄 CodeRabbit inference engine (AGENTS.md)

Run poetry run test for backend testing (runs pytest with docker based postgres + prisma)

Files:

  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
🧠 Learnings (30)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:20.657Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ blocks (and across the codebase), wrapping synchronous AgentMail SDK calls with `await asyncio.to_thread()` is NOT required. The block executor runs node execution in dedicated threads via `asyncio.run_coroutine_threadsafe` (manager.py lines ~745-752, ~1079), and the existing codebase pattern does not use `asyncio.to_thread` for SDK calls inside async `run()` methods.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12439
File: autogpt_platform/backend/backend/blocks/autogpt_copilot.py:0-0
Timestamp: 2026-03-16T17:00:02.827Z
Learning: In autogpt_platform/backend/backend/blocks/autogpt_copilot.py, the recursion guard uses two module-level ContextVars: `_copilot_recursion_depth` (tracks current nesting depth) and `_copilot_recursion_limit` (stores the chain-wide ceiling). On the first invocation, `_copilot_recursion_limit` is set to `max_recursion_depth`; nested calls use `min(inherited_limit, max_recursion_depth)`, so they can only lower the cap, never raise it. The entry/exit logic is extracted into module-level helper functions. This is the approved pattern for preventing runaway sub-agent recursion in AutogptCopilotBlock (PR `#12439`, commits 348e9f8e2 and 3b70f61b1).
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Implement 'run' method with proper error handling in backend blocks
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/copilot/workflow_import/converter.py:0-0
Timestamp: 2026-03-17T10:57:10.126Z
Learning: In Significant-Gravitas/AutoGPT PR `#12440`, `autogpt_platform/backend/backend/copilot/workflow_import/converter.py` was fully rewritten (commit 732960e2d) to no longer make direct LLM/OpenAI API calls. The converter now builds a structured text prompt for AutoPilot/CoPilot instead. There is no `response.choices` access or any direct LLM client usage in this file. Do not flag `response.choices` access or LLM client initialization patterns as issues in this file.
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
📚 Learning: 2026-03-10T08:38:29.078Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:29.078Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review is session-scoped: it uses graph_exec_id (copilot-session-{session_id}) combined with node_id (copilot-node-{block_id}). If the user enables the auto-approve toggle for a CoPilot session, approving a block type in that session automatically approves all future invocations of that same block type within the same session. If the user does not toggle auto-approve (default), each individual invocation requires its own approval. This behavior should be clearly documented in code and comments, and tested to ensure the toggle reliably toggles between session-scoped auto-approval and per-invocation approval.

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
📚 Learning: 2026-03-10T08:38:30.834Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:349-370
Timestamp: 2026-03-10T08:38:30.834Z
Learning: In the AutoGPT CoPilot HITL flow, the review card presents with editable: false, so the input payload cannot be modified. Therefore credentials resolved before is_block_exec_need_review() remain valid and do not need to be recomputed after the review step. Ensure run_block.py uses the original input_data for credential validation and that any credential caching relies on the pre-review input. If there is any logic that would recompute credentials post-review, guard it against input_data mutations and rely on the UI to enforce immutability. This guideline is specific to autogpt_platform/backend/backend/copilot/tools/run_block.py.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Implement 'run' method with proper error handling in backend blocks

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-03-16T16:30:30.764Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/pods.py:62-74
Timestamp: 2026-03-16T16:30:30.764Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, explicit try/except in the `run()` method is NOT required for standard error handling. The block framework's `_execute()` method in `_base.py` catches unhandled exceptions and re-raises them as `BlockExecutionError` or `BlockUnknownError`. Additionally, when a block yields `("error", message)`, `_execute()` immediately raises `BlockExecutionError` — so the `error` output port never propagates downstream. Explicit try/except is only needed when partial output must be controlled (e.g., attachment blocks that must skip yielding `content_base64` on failure).

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-02-27T10:45:55.700Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:55.700Z
Learning: As of PR `#12213`, MCP tool response types (MCPToolsDiscoveredResponse, MCPToolOutputResponse) are defined in openapi.json and frontend code in autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx uses the generated types from `@/app/api/__generated__/`. Other tools like RunBlock still use inline TypeScript interfaces (e.g., BlockDetailsResponse) for SSE stream payloads that are not included in openapi.json schemas. The pattern is tool-specific: use generated types when available in openapi.json, use inline types only when the payload schema is truly SSE-stream-only and not exposed via OpenAPI.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-03-16T16:32:29.430Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/pods.py:62-74
Timestamp: 2026-03-16T16:32:29.430Z
Learning: In autogpt_platform/backend/backend/blocks/**/*.py, the Block base class `execute()` method in `backend/blocks/_base.py` already wraps `run()` in a try/except that converts uncaught exceptions into `BlockExecutionError`/`BlockUnknownError`. Therefore, explicit try/except in individual block `run()` methods is redundant and not the established pattern (e.g., Gmail, Slack, Todoist blocks omit it). Exception: blocks like attachment blocks that need to distinguish between success and error yield paths within the generator use explicit try/except for branching control, not for the framework's error routing.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-03-15T15:30:09.706Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/tools/helpers.py:149-185
Timestamp: 2026-03-15T15:30:09.706Z
Learning: In autogpt_platform/backend/backend/copilot/tools/helpers.py, within execute_block, when InsufficientBalanceError occurs after post-execution credit charging (concurrent balance drain after pre-check passed), this is treated as a non-fatal billing leak: log at ERROR level with structured JSON fields `{"billing_leak": True, "user_id": ..., "cost": ...}` for monitoring/alerting, then return BlockOutputResponse normally. Discarding the output would worsen UX since the block already executed with potential side effects. Reuse the credit_model obtained during the pre-execution balance check (guarded by `if cost > 0 and credit_model:`) for the post-execution charge; do not perform a second get_user_credit_model call.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/backend/blocks/*.py : When adding new blocks, analyze block interfaces to ensure inputs and outputs tie well together for productive graph-based editor connections

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-03-17T08:57:35.290Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/api/features/workflow_import.py:0-0
Timestamp: 2026-03-17T08:57:35.290Z
Learning: In Significant-Gravitas/AutoGPT PR `#12440`, the dedicated REST endpoint `/api/import/workflow` for competitor/external workflow import was removed (commit 30f801a5e). The frontend now redirects users to AutoPilot/CoPilot, which invokes the underlying conversion modules (format detector, describers, converter) directly via an `import_workflow` tool. Do not expect or require a standalone HTTP endpoint or route-level integration tests for workflow import in this repository — the functionality lives in the CoPilot tool layer.

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-03-04T12:19:39.243Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12279
File: autogpt_platform/backend/backend/copilot/tools/base.py:184-188
Timestamp: 2026-03-04T12:19:39.243Z
Learning: In autogpt_platform/backend/backend/copilot/tools/, ensure that anonymous users always pass user_id=None to tool execution methods. The anon_ prefix (e.g., anon_123) is used only for PostHog/analytics distinct_id and must not be used as an actual user_id. Use a simple truthiness check on user_id (e.g., if user_id: ... else: ... or a dedicated is_authenticated flag) to distinguish anonymous from authenticated users, and review all tool execution call sites within this directory to prevent accidentally forwarding an anon_ user_id to tools.

Applied to files:

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

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block.py
  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-03-16T16:30:20.657Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:20.657Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ blocks (and across the codebase), wrapping synchronous AgentMail SDK calls with `await asyncio.to_thread()` is NOT required. The block executor runs node execution in dedicated threads via `asyncio.run_coroutine_threadsafe` (manager.py lines ~745-752, ~1079), and the existing codebase pattern does not use `asyncio.to_thread` for SDK calls inside async `run()` methods.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-03-10T08:38:33.249Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:297-300
Timestamp: 2026-03-10T08:38:33.249Z
Learning: In autogpt_platform/backend/backend/copilot/tools/run_block.py, the auto-approval key for sensitive block HITL review uses graph_exec_id (copilot-session-{session_id}) + node_id (copilot-node-{block_id}). This is intentional: approving a block type within a CoPilot session auto-approves all future invocations of that same block type within the same session, mirroring how auto-approve works in normal graph execution. The user explicitly opts into this session-scoped behavior via an auto-approve toggle. Without the toggle (default), each individual invocation requires its own approval.

Applied to files:

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

Applied to files:

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

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/backend/blocks/*.py : When creating new blocks, inherit from the `Block` base class and define input/output schemas using `BlockSchema`

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
📚 Learning: 2026-02-05T04:11:15.945Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11796
File: autogpt_platform/backend/backend/blocks/video/concat.py:3-4
Timestamp: 2026-02-05T04:11:15.945Z
Learning: Block IDs in autogpt_platform/backend/backend/blocks/**/*.py must be stable, hard-coded UUID strings. When initially creating a new block, generate a UUID once using `uuid.uuid4()` and then hard-code that UUID string as the block's `id` parameter. Do not call uuid.uuid4() dynamically at runtime, as block IDs must remain constant across all imports and runs.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-03-16T16:30:20.657Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 12417
File: autogpt_platform/backend/backend/blocks/agent_mail/threads.py:80-102
Timestamp: 2026-03-16T16:30:20.657Z
Learning: In autogpt_platform/backend/backend/blocks/agent_mail/ (and other blocks under autogpt_platform/backend/backend/blocks/), the block executor framework (backend/executor/manager.py lines ~708-733) automatically catches all uncaught exceptions from a block's `run()` method and emits them on the `"error"` output. Explicit try/except blocks within `run()` are therefore not required for standard error propagation — they are only needed when partial output behaviour must be controlled (e.g., preventing some outputs from being yielded on failure, as in attachment blocks). This is the standard pattern across the codebase.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-03-10T08:39:22.025Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
📚 Learning: 2026-03-10T08:38:36.655Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/tools/run_block.py:349-370
Timestamp: 2026-03-10T08:38:36.655Z
Learning: In the AutoGPT CoPilot HITL (Human-In-The-Loop) flow (`autogpt_platform/backend/backend/copilot/tools/run_block.py`), the review card presented to users sets `editable: false`, meaning reviewers cannot modify the input payload. Therefore, credentials resolved before `is_block_exec_need_review()` remain valid and do not need to be recomputed after the review step — the original `input_data` is unchanged through the review lifecycle.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
📚 Learning: 2026-02-04T16:50:51.495Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-04T16:50:51.495Z
Learning: Applies to autogpt_platform/**/data/*.py : For changes touching `data/*.py`, validate user ID checks or explain why not needed

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/run_block_async.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/**/test/**/*.py : Use snapshot testing with '--snapshot-update' flag in backend tests when output changes; always review with 'git diff'

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Always review snapshot changes with `git diff` before committing when updating snapshots with `poetry run pytest --snapshot-update`

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/**/*_test.py : Use pytest with snapshot testing for API responses in test files

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/helpers_test.py
📚 Learning: 2026-03-17T07:24:29.647Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/rate_limit.py:0-0
Timestamp: 2026-03-17T07:24:29.647Z
Learning: In `autogpt_platform/backend/backend/copilot/rate_limit.py`, all fail-open `except` blocks catch `(RedisError, ConnectionError, OSError)` specifically — not bare `except Exception`. This applies to `_session_reset_from_ttl`, `get_usage_status`, `check_rate_limit`, and `record_token_usage`. The narrowed tuple ensures only genuine Redis/network failures are swallowed; unexpected exceptions propagate normally.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/get_block_result.py
🔇 Additional comments (7)
autogpt_platform/backend/backend/copilot/tools/helpers_test.py (2)

81-201: Strong coverage for credit-charging execution paths.

Nice set of assertions across positive-cost charging, pre-exec insufficient credits, zero-cost bypass, and post-exec insufficient-balance behavior.


580-704: Preparation flow tests cover the important validation branches well.

The cases for not-found/disabled blocks, unrecognized fields, missing credentials, and successful BlockPreparation are well targeted.

autogpt_platform/backend/backend/copilot/tools/run_block.py (5)

9-15: LGTM!

The imports are well-organized and all imported symbols (BlockPreparation, check_hitl_review, execute_block, prepare_block_for_execution, BlockDetails, BlockDetailsResponse, ErrorResponse, ToolResponseBase) are properly utilized throughout the file.


117-126: LGTM!

The preparation flow correctly uses the new prepare_block_for_execution helper with proper error handling. The isinstance check cleanly distinguishes between early-return responses and successful BlockPreparation results, and the type annotation at line 126 correctly narrows the type after the guard.


128-160: LGTM!

The two-step UX logic is well-implemented:

  • The set subset check (required_non_credential_keys <= provided_input_keys) correctly determines when to show schema vs. execute.
  • Output schema generation has proper error handling with a descriptive error message.
  • The BlockDetailsResponse construction correctly uses all BlockPreparation fields, matching the dataclass definition.

162-175: LGTM!

The HITL review integration is clean and correct:

  • The isinstance check properly guards against ReviewRequiredResponse returns.
  • The tuple unpacking correctly handles the success case (synthetic_node_exec_id, input_data).
  • The execute_block call passes all required parameters matching the expected signature, including the matched_credentials from the preparation step.

Based on learnings, the credential validation performed before is_block_exec_need_review() remains valid since the review card presents with editable: false, so prep.matched_credentials is correctly reused here.


20-73: LGTM!

The RunBlockTool class structure is clean with well-defined properties. The description clearly documents the two-step flow and the requirement to call find_block first. Parameter definitions are comprehensive with helpful descriptions.

Comment thread autogpt_platform/backend/backend/copilot/tools/get_block_result.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/helpers_test.py
Comment thread autogpt_platform/backend/backend/copilot/tools/helpers_test.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/get_block_result.py Outdated
@github-actions github-actions Bot added conflicts Automatically applied to PRs with merge conflicts and removed platform/frontend AutoGPT Platform - Front end labels Mar 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request.

Comment thread autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py Outdated
@majdyz

majdyz commented Mar 24, 2026

Copy link
Copy Markdown
Contributor Author

Addressed reviewer feedback from autogpt-pr-reviewer:

Blockers (all 3 already resolved in prior commits):

  1. Legacy themed-prompt data — _json_to_list() already handles dict-format rows by flattening values
  2. reset_stash_event tests — TestResetStashEvent class with 3 dedicated tests already exists in tool_adapter_test.py
  3. Arg mismatch fallback — already cancels pre-launched task and falls through to direct execution

Should Fix addressed in 663a11b:

  • Sanitized exception messages in MCP error responses — replaced raw str(e) with generic messages to prevent leaking internals to LLM/client. Full exceptions still logged server-side.

Should Fix items no longer in PR scope (removed by rebase onto dev):

  • blocks/llm.py store=False — file not in this PR
  • EmptySession.tsx aria-live — file not in this PR
  • Breaking API changelog — API change not in this PR
  • call_order assertion — already present in test

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request.

@github-actions github-actions Bot added the conflicts Automatically applied to PRs with merge conflicts label Mar 24, 2026
@github-actions github-actions Bot removed the conflicts Automatically applied to PRs with merge conflicts label Mar 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Conflicts have been resolved! 🎉 A maintainer will review the pull request shortly.

@github-actions github-actions Bot added the conflicts Automatically applied to PRs with merge conflicts label Mar 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request.

Integrate block-level permission checking from #12482 into
the refactored run_block that uses prepare_block_for_execution helper.
@github-actions github-actions Bot removed the conflicts Automatically applied to PRs with merge conflicts label Mar 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Conflicts have been resolved! 🎉 A maintainer will review the pull request shortly.

@AutoGPT-Agent

Copy link
Copy Markdown
Contributor

Excellent work! This is a well-designed feature with thorough testing.

Blocking issue:

Merge conflicts must be resolved - The PR has the conflicts label. Please rebase or merge the latest changes from the target branch and resolve all conflicts.

After resolving conflicts:

The PR will be ready to merge. The implementation is solid:

Clear intent and comprehensive description - Root cause analysis and test plan are excellent

Proper scope - ~90%+ of changes support the parallel execution feature; the understanding.py fix for legacy data is reasonable technical debt cleanup

Excellent test coverage - 10 new parallel infrastructure tests, integration tests, and E2E verification

Clean architecture - DRY refactor with prepare_block_for_execution() and check_hitl_review() improves maintainability

Proper error handling - Cancellation support, fallback paths, and arg-mismatch detection all present

Conventional commit format - Title correctly follows feat(backend/copilot): pattern

Once conflicts are resolved, this will be a great addition to the codebase.

The permission tests were patching 'run_block.get_block' but after
the refactor, get_block is only imported in helpers.py. Update the
patch targets to 'helpers.get_block'.
Comment thread autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
Comment thread autogpt_platform/backend/backend/copilot/sdk/service.py
Comment thread autogpt_platform/backend/backend/data/understanding.py
majdyz added 2 commits March 24, 2026 17:39
- Add 5s timeout to cancel_pending_tool_tasks gather to prevent
  hanging on stuck task cleanup
- Await cancelled task on arg mismatch before falling through to
  direct execution, preventing duplicate concurrent side effects
- Add debug logging when flattening legacy dict-format understanding data
@AutoGPT-Agent

Copy link
Copy Markdown
Contributor

Feedback

❌ Out-of-scope change detected

Your PR includes a change to backend/data/understanding.py that is not mentioned in the description and appears unrelated to parallel block execution:

def _json_to_list(value: Any) -> list[str]:
    # ... new handling for legacy dict-format rows from "reverted themed-prompts feature"

This change handles data migration for a legacy feature and has nothing to do with the parallel execution infrastructure described in your PR.

Required action:

  • Either explain in the PR description why this data migration change is necessary for parallel execution (if there's a hidden dependency)
  • OR remove this change and submit it as a separate PR with appropriate title/description (recommended)

✅ What's good

  • Excellent description with root cause analysis and detailed test plan
  • Comprehensive test coverage (10 new tests for parallel infrastructure)
  • Well-structured code with clear separation of concerns
  • Thorough error handling including cancellation and cleanup
  • Good use of context variables for session isolation

Once the out-of-scope change is addressed, this will be ready to merge.

@majdyz
majdyz requested a review from Swiftyos March 24, 2026 11:00
@github-project-automation github-project-automation Bot moved this from 🚧 Needs work to 👍🏼 Mergeable in AutoGPT development kanban Mar 24, 2026
@majdyz
majdyz disabled auto-merge March 24, 2026 13:27
@majdyz
majdyz merged commit edb3d32 into dev Mar 24, 2026
24 of 26 checks passed
@majdyz
majdyz deleted the feat/run-block-parallel branch March 24, 2026 13:27
@github-project-automation github-project-automation Bot moved this to Done in Frontend Mar 24, 2026
@github-project-automation github-project-automation Bot moved this from 👍🏼 Mergeable to ✅ Done in AutoGPT development kanban Mar 24, 2026
Bentlybro pushed a commit that referenced this pull request Apr 4, 2026
#12507)

## Summary
- Adds `/pr-test` skill for automated E2E testing of PRs using docker
compose, agent-browser, and API calls
- Covers full environment setup (copy .env, configure copilot auth,
ARM64 Docker fix)
- Includes browser UI testing, direct API testing, screenshot capture,
and test report generation
- Has `--fix` mode for auto-fixing bugs found during testing (similar to
`/pr-address`)
- **Screenshot uploads use GitHub Git API** (blobs → tree → commit →
ref) — no local git operations, safe for worktrees
- **Subscription mode improvements:**
- Extract subscription auth logic to `sdk/subscription.py` — uses SDK's
bundled CLI binary instead of requiring `npm install -g
@anthropic-ai/claude-code`
- Auto-provision `~/.claude/.credentials.json` from
`CLAUDE_CODE_OAUTH_TOKEN` env var on container startup — no `claude
login` needed in Docker
- Add `scripts/refresh_claude_token.sh` — cross-platform helper
(macOS/Linux/Windows) to extract OAuth tokens from host and update
`backend/.env`

## Test plan
- [x] Validated skill on multiple PRs (#12482, #12483, #12499, #12500,
#12501, #12440, #12472) — all test scenarios passed
- [x] Confirmed screenshot upload via GitHub Git API renders correctly
on all 7 PRs
- [x] Verified subscription mode E2E in Docker:
`refresh_claude_token.sh` → `docker compose up` → copilot chat responds
correctly with no API keys (pure OAuth subscription)
- [x] Verified auto-provisioning of credentials file inside container
from `CLAUDE_CODE_OAUTH_TOKEN` env var
- [x] Confirmed bundled CLI detection
(`claude_agent_sdk._bundled/claude`) works without system-installed
`claude`
- [x] `poetry run pytest backend/copilot/sdk/service_test.py` — 24/24
tests pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform/backend AutoGPT Platform - Back end size/xl

Projects

Status: ✅ Done
Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants