mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-08 22:58:01 -05:00
feat(backend): Standardize error handling with BlockSchemaInput & BlockSchemaOutput base class (#11257)
<!-- Clearly explain the need for these changes: --> This PR addresses the need for consistent error handling across all blocks in the AutoGPT platform. Previously, each block had to manually define an `error` field in their output schema, leading to code duplication and potential inconsistencies. Some blocks might forget to include the error field, making error handling unpredictable. ### Changes 🏗️ <!-- Concisely describe all of the changes made in this pull request: --> - **Created `BlockSchemaOutput` base class**: New base class that extends `BlockSchema` with a standardized `error` field - **Created `BlockSchemaInput` base class**: Added for consistency and future extensibility - **Updated 140+ block implementations**: Changed all block `Output` classes from `class Output(BlockSchema):` to `class Output(BlockSchemaOutput):` - **Removed manual error field definitions**: Eliminated hundreds of duplicate `error: str = SchemaField(...)` definitions - **Updated type annotations**: Changed `Block[BlockSchema, BlockSchema]` to `Block[BlockSchemaInput, BlockSchemaOutput]` throughout the codebase - **Fixed imports**: Added `BlockSchemaInput` and `BlockSchemaOutput` imports to all relevant files - **Maintained backward compatibility**: Updated `EmptySchema` to inherit from `BlockSchemaOutput` **Key Benefits:** - Consistent error handling across all blocks - Reduced code duplication (removed ~200 lines of repetitive error field definitions) - Type safety improvements with distinct input/output schema types - Blocks can still override error field with more specific descriptions when needed ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: <!-- Put your test plan here: --> - [x] Verified `poetry run format` passes (all linting, formatting, and type checking) - [x] Tested block instantiation works correctly (MediaDurationBlock, UnrealTextToSpeechBlock) - [x] Confirmed error fields are automatically present in all updated blocks - [x] Verified block loading system works (successfully loads 353+ blocks) - [x] Tested backward compatibility with EmptySchema - [x] Confirmed blocks can still override error field with custom descriptions - [x] Validated core schema inheritance chain works correctly #### For configuration changes: - [x] `.env.default` is updated or already compatible with my changes - [x] `docker-compose.yml` is updated or already compatible with my changes - [x] I have included a list of my configuration changes in the PR description (under **Changes**) *Note: No configuration changes were needed for this refactoring.* 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Lluis Agusti <hi@llu.lu> Co-authored-by: Ubbe <hi@ubbe.dev>
This commit is contained in:
@@ -55,6 +55,8 @@ from backend.sdk import (
|
||||
BlockCategory,
|
||||
BlockOutput,
|
||||
BlockSchema,
|
||||
BlockSchemaInput,
|
||||
BlockSchemaOutput,
|
||||
CredentialsMetaInput,
|
||||
SchemaField,
|
||||
)
|
||||
@@ -62,7 +64,7 @@ from ._config import my_provider
|
||||
|
||||
|
||||
class MyBlock(Block):
|
||||
class Input(BlockSchema):
|
||||
class Input(BlockSchemaInput):
|
||||
# Define input fields
|
||||
credentials: CredentialsMetaInput = my_provider.credentials_field(
|
||||
description="API credentials for My Provider"
|
||||
@@ -80,11 +82,11 @@ class MyBlock(Block):
|
||||
advanced=True # Hidden by default in UI
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
class Output(BlockSchemaOutput):
|
||||
# Define output fields
|
||||
results: list = SchemaField(description="List of results")
|
||||
count: int = SchemaField(description="Total count")
|
||||
error: str = SchemaField(description="Error message if failed")
|
||||
# error output pin is already defined on BlockSchemaOutput
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
@@ -145,7 +147,7 @@ The `ProviderBuilder` allows you to:
|
||||
1. **Unique ID**: Generate using `uuid.uuid4()`
|
||||
2. **Categories**: Choose from `BlockCategory` enum (e.g., SEARCH, AI, PRODUCTIVITY)
|
||||
3. **async run()**: Main execution method that yields outputs
|
||||
4. **Error handling**: Always include error output field
|
||||
4. **Error handling**: Error output pin is already defined on BlockSchemaOutput
|
||||
|
||||
## Advanced Features
|
||||
|
||||
@@ -225,7 +227,7 @@ backend/blocks/my_provider/
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Error Handling**: Always include an error field in outputs
|
||||
1. **Error Handling**: Error output pin is already defined on BlockSchemaOutput
|
||||
2. **Credentials**: Use the provider's `credentials_field()` method
|
||||
3. **Validation**: Use SchemaField constraints (ge, le, min_length, etc.)
|
||||
4. **Categories**: Choose appropriate categories for discoverability
|
||||
|
||||
@@ -20,13 +20,13 @@ Follow these steps to create and test a new block:
|
||||
Every block should contain the following:
|
||||
|
||||
```python
|
||||
from backend.data.block import Block, BlockSchema, BlockOutput
|
||||
from backend.data.block import Block, BlockSchemaInput, BlockSchemaOutput, BlockOutput
|
||||
```
|
||||
|
||||
Example for the Wikipedia summary block:
|
||||
|
||||
```python
|
||||
from backend.data.block import Block, BlockSchema, BlockOutput
|
||||
from backend.data.block import Block, BlockSchemaInput, BlockSchemaOutput, BlockOutput
|
||||
from backend.utils.get_request import GetRequest
|
||||
import requests
|
||||
|
||||
@@ -42,12 +42,11 @@ Follow these steps to create and test a new block:
|
||||
Example:
|
||||
|
||||
```python
|
||||
class Input(BlockSchema):
|
||||
class Input(BlockSchemaInput):
|
||||
topic: str # The topic to get the Wikipedia summary for
|
||||
|
||||
class Output(BlockSchema):
|
||||
class Output(BlockSchemaOutput):
|
||||
summary: str # The summary of the topic from Wikipedia
|
||||
error: str # Any error message if the request fails, error field needs to be named `error`.
|
||||
```
|
||||
|
||||
4. **Implement the `__init__` method, including test data and mocks:**
|
||||
@@ -173,14 +172,14 @@ from backend.data.model import (
|
||||
Credentials,
|
||||
)
|
||||
|
||||
from backend.data.block import Block, BlockOutput, BlockSchema
|
||||
from backend.data.block import Block, BlockOutput, BlockSchemaInput, BlockSchemaOutput
|
||||
from backend.data.model import CredentialsField
|
||||
from backend.integrations.providers import ProviderName
|
||||
|
||||
|
||||
# API Key auth:
|
||||
class BlockWithAPIKeyAuth(Block):
|
||||
class Input(BlockSchema):
|
||||
class Input(BlockSchemaInput):
|
||||
# Note that the type hint below is require or you will get a type error.
|
||||
# The first argument is the provider name, the second is the credential type.
|
||||
credentials: CredentialsMetaInput[
|
||||
@@ -203,7 +202,7 @@ class BlockWithAPIKeyAuth(Block):
|
||||
|
||||
# OAuth:
|
||||
class BlockWithOAuth(Block):
|
||||
class Input(BlockSchema):
|
||||
class Input(BlockSchemaInput):
|
||||
# Note that the type hint below is require or you will get a type error.
|
||||
# The first argument is the provider name, the second is the credential type.
|
||||
credentials: CredentialsMetaInput[
|
||||
@@ -226,7 +225,7 @@ class BlockWithOAuth(Block):
|
||||
|
||||
# API Key auth + OAuth:
|
||||
class BlockWithAPIKeyAndOAuth(Block):
|
||||
class Input(BlockSchema):
|
||||
class Input(BlockSchemaInput):
|
||||
# Note that the type hint below is require or you will get a type error.
|
||||
# The first argument is the provider name, the second is the credential type.
|
||||
credentials: CredentialsMetaInput[
|
||||
|
||||
Reference in New Issue
Block a user