Skip to content

feat(copilot): add dummy agent generator for testing#12071

Merged
Otto-AGPT merged 0 commit intodevfrom
feat/dummy-agent-generator
Mar 4, 2026
Merged

feat(copilot): add dummy agent generator for testing#12071
Otto-AGPT merged 0 commit intodevfrom
feat/dummy-agent-generator

Conversation

@Otto-AGPT
Copy link
Copy Markdown
Contributor

@Otto-AGPT Otto-AGPT commented Feb 11, 2026

Summary

Add an optional dummy agent generator that returns mock responses matching the expected format from the external Agent Generator service. This enables local CoPilot testing without needing the external service running.

Changes

  • settings.py: Add agentgenerator_use_dummy setting (default: false)
  • dummy.py (new): Mock implementations of all service functions:
    • decompose_goal_dummy() - Returns static instructions
    • generate_agent_dummy() - Returns minimal valid 2-node agent (Input → Output)
    • generate_agent_patch_dummy() - Returns current agent with updated description
    • customize_template_dummy() - Returns template with updated description
    • get_blocks_dummy() - Returns AgentInputBlock and AgentOutputBlock
    • health_check_dummy() - Always returns healthy
  • service.py: Route to dummy functions when AGENTGENERATOR_USE_DUMMY=true
    • Add startup warning when dummy mode is active
    • Update is_external_service_configured() to return true in dummy mode

Usage

Set environment variable:

AGENTGENERATOR_USE_DUMMY=true

Or in .env:

AGENTGENERATOR_USE_DUMMY=true

Testing

  1. Set AGENTGENERATOR_USE_DUMMY=true
  2. CoPilot can now create/edit agents without external service
  3. Check logs for "Agent Generator running in DUMMY MODE" warning

Notes

  • Default is false - requires explicit opt-in
  • Logs a warning at startup when enabled to prevent accidental production use
  • Uses correct block IDs from backend/blocks/io.py

Requested by @majdyz

Greptile Overview

Greptile Summary

Adds a dummy mode for the Agent Generator service to enable local testing without the external service. When AGENTGENERATOR_USE_DUMMY=true, all agent generator functions return mock responses with valid structure.

Key Changes

  • Added agentgenerator_use_dummy boolean setting in settings.py (defaults to false)
  • Created dummy.py with mock implementations returning minimal valid agent structures
  • Modified service.py to check dummy mode and route to dummy functions when enabled
  • Adds warning log "Agent Generator running in DUMMY MODE" on startup when enabled

Issues Found

  • Shallow copy issue in generate_agent_patch_dummy() and customize_template_dummy() - using .copy() instead of copy.deepcopy() could cause unintended mutations of nested agent structures

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk once the shallow copy issues are addressed
  • The implementation is straightforward and well-structured for testing purposes. The dummy functions return valid agent structures with correct block IDs. However, two shallow copy bugs could cause unintended mutations in generate_agent_patch_dummy and customize_template_dummy. These should use copy.deepcopy() instead of .copy() for nested structures. The feature is opt-in (default false) with clear warnings, reducing production risk.
  • Pay attention to dummy.py lines 120 and 133 - fix shallow copy issues before merging

Sequence Diagram

sequenceDiagram
    participant Client as CoPilot Client
    participant Core as core.py
    participant Service as service.py
    participant Dummy as dummy.py
    participant External as External Agent Generator

    Client->>Core: decompose_goal("description")
    Core->>Service: is_external_service_configured()
    
    alt Dummy Mode Enabled
        Service->>Service: _is_dummy_mode() returns True
        Service-->>Core: True (configured)
        Core->>Service: decompose_goal_external()
        Service->>Service: Check _is_dummy_mode()
        Service->>Dummy: decompose_goal_dummy()
        Dummy-->>Service: {type: "instructions", steps: [...]}
        Service-->>Core: Mock response
    else External Service
        Service-->>Core: True (configured)
        Core->>Service: decompose_goal_external()
        Service->>External: POST /api/decompose-description
        External-->>Service: Real response
        Service-->>Core: Agent data
    end
    
    Core-->>Client: Agent instructions/questions
Loading

@Otto-AGPT Otto-AGPT requested a review from a team as a code owner February 11, 2026 16:10
@Otto-AGPT Otto-AGPT requested review from 0ubbe and Bentlybro and removed request for a team February 11, 2026 16:10
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban Feb 11, 2026
@github-actions github-actions Bot added platform/backend AutoGPT Platform - Back end size/l labels Feb 11, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 11, 2026

Walkthrough

This PR introduces a dummy agent generator module for testing purposes, adding stub implementations of core agent generation functions. A new configuration flag enables switching between external and dummy modes, with service-layer routing logic to delegate calls appropriately based on the active mode.

Changes

Cohort / File(s) Summary
Dummy Agent Generator Implementation
backend/api/features/chat/tools/agent_generator/dummy.py
New module providing mock implementations of agent generation workflow functions, including decompose_goal, generate_agent, generate_agent_patch, customize_template, get_blocks, and health_check. Includes predefined constants and helper function for constructing minimal valid agent JSON structures for testing.
Service Layer Routing
backend/api/features/chat/tools/agent_generator/service.py
Adds dummy mode detection via _is_dummy_mode() function and extends is_external_service_configured() check to include dummy mode flag. Routes six external call functions to dummy implementations when dummy mode is active, with one-time warning logging.
Configuration
backend/util/settings.py
Introduces agentgenerator_use_dummy: bool configuration field (default False) to enable dummy responses for testing without external service dependency.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Service
    participant DummyImpl
    participant ExternalAPI

    Client->>Service: decompose_goal() / generate_agent() / etc.
    activate Service
    Service->>Service: _is_dummy_mode()?
    alt Dummy Mode Enabled
        Service->>DummyImpl: delegate to dummy implementation
        activate DummyImpl
        DummyImpl->>DummyImpl: log & construct response
        DummyImpl-->>Service: return mock result
        deactivate DummyImpl
    else External Mode
        Service->>ExternalAPI: call actual external service
        activate ExternalAPI
        ExternalAPI-->>Service: return actual result
        deactivate ExternalAPI
    end
    Service-->>Client: return result
    deactivate Service
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

size/xl, platform/backend

Suggested reviewers

  • 0ubbe

Poem

🐰 A dummy mode blooms in the garden of tests,
No external calls needed—just harmless requests,
Mock agents and blocks spring forth with a hop,
Configuration flags help us troubleshoot and stop!
Testing flows freely, without a real server to call. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(copilot): add dummy agent generator for testing' accurately summarizes the main change—adding a dummy agent generator feature for testing purposes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The pull request description clearly describes the dummy agent generator feature, explaining its purpose, configuration, and implementation across three files.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/dummy-agent-generator

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.

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +120 to +122
patched = current_agent.copy()
patched["description"] = (
f"{current_agent.get('description', '')} (updated: {update_request})"
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.

shallow copy may not preserve nested structures in agent JSON

current_agent.copy() creates a shallow copy - nested dicts/lists are shared references. If the agent has nested nodes or links, modifying the description could potentially affect the original agent in unexpected ways.

Suggested change
patched = current_agent.copy()
patched["description"] = (
f"{current_agent.get('description', '')} (updated: {update_request})"
patched = copy.deepcopy(current_agent)
patched["description"] = (

Comment on lines +133 to +135
logger.info("Using dummy agent generator for customize_template")
customized = template_agent.copy()
customized["description"] = (
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.

shallow copy may not preserve nested structures

Same shallow copy issue - use copy.deepcopy() instead of .copy() for complex nested agent structures.

Suggested change
logger.info("Using dummy agent generator for customize_template")
customized = template_agent.copy()
customized["description"] = (
customized = copy.deepcopy(template_agent)
customized["description"] = (

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py`:
- Around line 90-97: The function decompose_goal_dummy returns a shallow copy of
DUMMY_DECOMPOSITION_RESULT which leaks nested mutable state; change it to return
a deep copy (e.g., use copy.deepcopy on DUMMY_DECOMPOSITION_RESULT) or
reconstruct the dict inline so callers cannot mutate the module-level constant,
and ensure you add the necessary import for copy if using deepcopy.
🧹 Nitpick comments (2)
autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py (1)

104-123: _is_dummy_mode() is called on every request — consider caching the result.

_is_dummy_mode() reads from the settings singleton on every external call. Since the dummy flag won't change at runtime, you could cache the resolved boolean once instead of re-reading and re-checking on every invocation. This is a minor optimization and readability nit — not blocking.

Optional: cache dummy mode at module level
-_dummy_mode_warned = False
+_dummy_mode: bool | None = None


 def _is_dummy_mode() -> bool:
     """Check if dummy mode is enabled for testing."""
-    global _dummy_mode_warned
-    settings = _get_settings()
-    is_dummy = bool(settings.config.agentgenerator_use_dummy)
-    if is_dummy and not _dummy_mode_warned:
-        logger.warning(
-            "Agent Generator running in DUMMY MODE - returning mock responses. "
-            "Do not use in production!"
-        )
-        _dummy_mode_warned = True
-    return is_dummy
+    global _dummy_mode
+    if _dummy_mode is None:
+        settings = _get_settings()
+        _dummy_mode = bool(settings.config.agentgenerator_use_dummy)
+        if _dummy_mode:
+            logger.warning(
+                "Agent Generator running in DUMMY MODE - returning mock responses. "
+                "Do not use in production!"
+            )
+    return _dummy_mode
autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py (1)

37-39: Hardcoded block IDs duplicate definitions in backend/blocks/io.py.

These constants match the source definitions (c0a8e994-ebf1-4a9c-a4d8-89d09c86741b and 363ae599-353e-4804-937e-b2ee3cef3da4), but duplicating them creates a maintenance risk. If the block IDs in io.py ever change, these hardcoded references will silently become stale and break the agent generator.

Consider importing directly from backend.blocks.io (e.g., from backend.blocks.io import AgentInputBlock, AgentOutputBlock) and referencing their .id attributes, or at minimum add a comment linking to the canonical import path (backend.blocks.io:AgentInputBlock and backend.blocks.io:AgentOutputBlock) so the relationship is explicit.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 36aeb0b and 316822a.

📒 Files selected for processing (3)
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py
  • autogpt_platform/backend/backend/util/settings.py
🧰 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/util/settings.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.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/util/settings.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.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/util/settings.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/util/settings.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py
autogpt_platform/backend/backend/api/features/**/*.py

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

Update routes in '/backend/backend/api/features/' and add/update Pydantic models in the same directory for API development

When modifying API routes, update corresponding Pydantic models in the same directory and write tests alongside the route file

Files:

  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py
autogpt_platform/backend/backend/api/**/*.py

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

autogpt_platform/backend/backend/api/**/*.py: Use FastAPI for building REST and WebSocket endpoints
Use JWT-based authentication with Supabase integration

Files:

  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py
  • autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py
🧬 Code graph analysis (1)
autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py (1)
autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py (6)
  • customize_template_dummy (127-138)
  • decompose_goal_dummy (90-97)
  • generate_agent_dummy (100-108)
  • generate_agent_patch_dummy (111-124)
  • get_blocks_dummy (141-147)
  • health_check_dummy (150-152)
⏰ 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: types
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.13)
  • GitHub Check: test (3.11)
  • GitHub Check: Check PR Status
🔇 Additional comments (5)
autogpt_platform/backend/backend/util/settings.py (1)

371-374: LGTM!

Clean addition, logically grouped with the other agentgenerator_* fields, sensible default of False, and consistent use of Field with description.

autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py (2)

42-87: LGTM!

The helper generates a fresh, structurally valid minimal agent each call with unique UUIDs, and the node/link wiring is internally consistent.


100-152: LGTM!

The remaining dummy functions (generate_agent_dummy, generate_agent_patch_dummy, customize_template_dummy, get_blocks_dummy, health_check_dummy) are clean stubs with signatures matching the real service call sites.

autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/service.py (2)

15-27: LGTM — clean routing setup.

Unconditional import is fine (negligible overhead from loading dummy stubs), and the one-time warning via _dummy_mode_warned is a nice touch to prevent log noise.


167-168: LGTM — consistent dummy-mode routing across all external functions.

Each function gates on _is_dummy_mode() before any HTTP client usage, argument forwarding matches the dummy signatures, and the early return prevents any network I/O in dummy mode.

Also applies to: 259-262, 335-338, 426-429, 493-494, 529-530

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +90 to +97
async def decompose_goal_dummy(
description: str,
context: str = "",
library_agents: list[dict[str, Any]] | None = None,
) -> dict[str, Any]:
"""Return dummy decomposition result."""
logger.info("Using dummy agent generator for decompose_goal")
return DUMMY_DECOMPOSITION_RESULT.copy()
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.

⚠️ Potential issue | 🟡 Minor

Shallow copy of DUMMY_DECOMPOSITION_RESULT leaks shared mutable nested state.

dict.copy() is shallow — the "steps" list (and its inner dicts) remains shared with the module-level constant. If any downstream caller mutates the nested structures (e.g., appending to steps or modifying a step dict), it corrupts the constant for all subsequent calls.

Use copy.deepcopy or reconstruct the dict inline.

Proposed fix
+import copy
+
 async def decompose_goal_dummy(
     description: str,
     context: str = "",
     library_agents: list[dict[str, Any]] | None = None,
 ) -> dict[str, Any]:
     """Return dummy decomposition result."""
     logger.info("Using dummy agent generator for decompose_goal")
-    return DUMMY_DECOMPOSITION_RESULT.copy()
+    return copy.deepcopy(DUMMY_DECOMPOSITION_RESULT)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def decompose_goal_dummy(
description: str,
context: str = "",
library_agents: list[dict[str, Any]] | None = None,
) -> dict[str, Any]:
"""Return dummy decomposition result."""
logger.info("Using dummy agent generator for decompose_goal")
return DUMMY_DECOMPOSITION_RESULT.copy()
import copy
async def decompose_goal_dummy(
description: str,
context: str = "",
library_agents: list[dict[str, Any]] | None = None,
) -> dict[str, Any]:
"""Return dummy decomposition result."""
logger.info("Using dummy agent generator for decompose_goal")
return copy.deepcopy(DUMMY_DECOMPOSITION_RESULT)
🤖 Prompt for AI Agents
In
`@autogpt_platform/backend/backend/api/features/chat/tools/agent_generator/dummy.py`
around lines 90 - 97, The function decompose_goal_dummy returns a shallow copy
of DUMMY_DECOMPOSITION_RESULT which leaks nested mutable state; change it to
return a deep copy (e.g., use copy.deepcopy on DUMMY_DECOMPOSITION_RESULT) or
reconstruct the dict inline so callers cannot mutate the module-level constant,
and ensure you add the necessary import for copy if using deepcopy.

@github-project-automation github-project-automation Bot moved this from 🆕 Needs initial review to 👍🏼 Mergeable in AutoGPT development kanban Feb 12, 2026
@github-actions github-actions Bot added the conflicts Automatically applied to PRs with merge conflicts label Feb 12, 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.

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

Labels

conflicts Automatically applied to PRs with merge conflicts platform/backend AutoGPT Platform - Back end size/l size/xs

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

2 participants