Skip to content

feat(platform): Add Block Development SDK with auto-registration system #10074

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 82 commits into from
Jul 10, 2025

Conversation

Swiftyos
Copy link
Contributor

@Swiftyos Swiftyos commented Jun 2, 2025

Block Development SDK - Simplifying Block Creation

Problem

Currently, creating a new block requires manual updates to 5+ files scattered across the codebase:

  • backend/data/block_cost_config.py - Manually add block costs
  • backend/integrations/credentials_store.py - Add default credentials
  • backend/integrations/providers.py - Register new providers
  • backend/integrations/oauth/__init__.py - Register OAuth handlers
  • backend/integrations/webhooks/__init__.py - Register webhook managers

This creates significant friction for developers, increases the chance of configuration errors, and makes the platform difficult to scale.

Solution

This PR introduces a Block Development SDK that provides:

  • Single import for all block development needs: from backend.sdk import *
  • Automatic registration of all block configurations
  • Zero external file modifications required
  • Provider-based configuration with inheritance

Changes 🏗️

1. New SDK Module (backend/sdk/)

  • __init__.py: Unified exports of 68+ block development components
  • registry.py: Central auto-registration system for all block configurations
  • builder.py: ProviderBuilder class for fluent provider configuration
  • provider.py: Provider configuration management
  • cost_integration.py: Automatic cost application system

2. Provider Builder Pattern

# Configure once, use everywhere
my_provider = (
    ProviderBuilder("my-service")
    .with_api_key("MY_SERVICE_API_KEY", "My Service API Key")
    .with_base_cost(5, BlockCostType.RUN)
    .build()
)

3. Automatic Cost System

  • Provider base costs automatically applied to all blocks using that provider
  • Override with @cost decorator for block-specific pricing
  • Tiered pricing support with cost filters

4. Dynamic Provider Support

  • Modified ProviderName enum to accept any string via _missing_ method
  • No more manual enum updates for new providers

5. Application Integration

  • Added sync_all_provider_costs() to initialize_blocks() for automatic cost registration
  • Maintains full backward compatibility with existing blocks

6. Comprehensive Examples (backend/blocks/examples/)

  • simple_example_block.py - Basic block structure
  • example_sdk_block.py - Provider with credentials
  • cost_example_block.py - Various cost patterns
  • advanced_provider_example.py - Custom API clients
  • example_webhook_sdk_block.py - Webhook configuration

7. Extensive Testing

  • 6 new test modules with 30+ test cases
  • Integration tests for all SDK features
  • Cost calculation verification
  • Provider registration tests

Before vs After

Before SDK:

# 1. Multiple complex imports
from backend.data.block import Block, BlockCategory, BlockOutput
from backend.data.model import SchemaField, CredentialsField
# ... many more imports

# 2. Update block_cost_config.py
BLOCK_COSTS[MyBlock] = [BlockCost(...)]

# 3. Update credentials_store.py
DEFAULT_CREDENTIALS.append(...)

# 4. Update providers.py enum
# 5. Update oauth/__init__.py
# 6. Update webhooks/__init__.py

After SDK:

from backend.sdk import *

# Everything configured in one place
my_provider = (
    ProviderBuilder("my-service")
    .with_api_key("MY_API_KEY", "My API Key")
    .with_base_cost(10, BlockCostType.RUN)
    .build()
)

class MyBlock(Block):
    class Input(BlockSchema):
        credentials: CredentialsMetaInput = my_provider.credentials_field()
        data: String = SchemaField(description="Input data")
    
    class Output(BlockSchema):
        result: String = SchemaField(description="Result")
    
    # That's it\! No external files to modify

Checklist 📋

For code changes:

  • I have clearly listed my changes in the PR description
  • I have made a test plan
  • I have tested my changes according to the test plan:
    • Created new blocks using SDK pattern with provider configuration
    • Verified automatic cost registration for provider-based blocks
    • Tested cost override with @cost decorator
    • Confirmed custom providers work without enum modifications
    • Verified all example blocks execute correctly
    • Tested backward compatibility with existing blocks
    • Ran all SDK tests (30+ tests, all passing)
    • Created blocks with credentials and verified authentication
    • Tested webhook block configuration
    • Verified application startup with auto-registration

For configuration changes:

  • .env.example is updated or already compatible with my changes (no changes needed)
  • docker-compose.yml is updated or already compatible with my changes (no changes needed)
  • I have included a list of my configuration changes in the PR description (under Changes)

Impact

  • Developer Experience: Block creation time reduced from hours to minutes
  • Maintainability: All block configuration in one place
  • Scalability: Support hundreds of blocks without enum updates
  • Type Safety: Full IDE support with proper type hints
  • Testing: Easier to test blocks in isolation

…gistration

- Add backend.sdk module with complete re-exports via 'from backend.sdk import *'
- Implement auto-registration system for costs, credentials, OAuth, and webhooks
- Add decorators (@Provider, @cost_config, @default_credentials, etc.) for self-contained blocks
- Patch application startup to use auto-registration system
- Create example blocks demonstrating new SDK patterns
- Add comprehensive test suite for SDK functionality

Key benefits:
- Single import statement provides all block development dependencies
- Zero external configuration - blocks are fully self-contained
- Backward compatible - existing blocks continue to work unchanged
- Minimal implementation - only 3 files, ~500 lines total

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@Swiftyos Swiftyos requested review from a team as code owners June 2, 2025 13:01
@Swiftyos Swiftyos requested review from kcze and majdyz and removed request for a team June 2, 2025 13:01
@github-project-automation github-project-automation bot moved this to 🆕 Needs initial review in AutoGPT development kanban Jun 2, 2025
@github-actions github-actions bot added platform/frontend AutoGPT Platform - Front end platform/backend AutoGPT Platform - Back end platform/blocks labels Jun 2, 2025
@github-actions github-actions bot changed the base branch from master to dev June 2, 2025 13:01
@Swiftyos Swiftyos marked this pull request as draft June 2, 2025 13:03
Swiftyos and others added 9 commits June 2, 2025 15:22
…tatus

- Mark completed items with ✅ (12/17 tasks completed)
- Core SDK implementation: 100% complete
- Auto-registration patches: 100% complete (with note on enum extension)
- Testing and migration: 60% complete (3/5 tasks)
- Note items left for future PRs (existing block migration, performance testing)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Analyze current ProviderName enum usage and limitations
- Propose provider registry pattern as alternative solution
- Maintain backward compatibility while enabling dynamic registration
- Include 7-phase implementation checklist with ~30 tasks
- Address the concern from PR #10074 about enum extension

The plan enables true zero-configuration for new providers while maintaining
type safety and validation through a custom Pydantic type.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add _missing_ method to ProviderName enum (15 lines)
- Allows any string to be used as a provider name
- Enables SDK @Provider decorator to work with custom providers
- Maintains full backward compatibility and type safety
- Much simpler than complex registry pattern (10 lines vs 200+)

This completes the SDK implementation by solving the last remaining issue
of dynamic provider registration.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add test_sdk_comprehensive.py with 8 test cases covering all SDK features
- Add demo_sdk_block.py showing real-world usage with custom provider
- Add test_sdk_integration.py for integration testing scenarios
- Fix missing oauth_config export in SDK __init__.py
- Add SDK_IMPLEMENTATION_SUMMARY.md documenting complete implementation
- Update REVISED_PLAN.md checklist to show 100% completion

Test Results:
- All 8 comprehensive tests pass
- Demo block works with zero external configuration
- Auto-registration verified for providers, costs, and credentials
- Dynamic provider enum support confirmed
- Import * functionality working correctly

The SDK is now fully implemented, tested, and ready for production use.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add noqa comments for star imports in SDK example/test files
- Configure Ruff to ignore F403/F405 in SDK files
- Fix webhook manager method signatures to match base class
- Change == to is for type comparisons in tests
- Remove unused variables or add noqa comments
- Create pyrightconfig.json to exclude SDK examples from type checking
- Update BlockWebhookConfig to use resource_format instead of event_format
- Fix all poetry run format errors

All formatting tools (ruff, isort, black, pyright) now pass successfully.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed patched_get_all_creds to return list instead of dict
- Fixed webhook manager _deregister_webhook signature to match base class
- Fixed PROVIDER_NAME to use ProviderName enum properly
- Removed all SDK file exclusions from pyrightconfig.json
- All pyright errors resolved with 0 errors, 0 warnings

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update CredentialsMetaInput.allowed_providers() to return None for unrestricted providers
- Fix pyright type errors by using ProviderName() constructor instead of string literals
- Update webhook manager signatures in tests to match abstract base class
- Add comprehensive test suites for custom provider functionality
- Configure ruff to ignore star import warnings in SDK and test files
- Ensure all formatting tools (ruff, black, isort, pyright) pass successfully

This enables SDK users to define custom providers without modifying core enums
while maintaining strict type safety throughout the codebase.
@Swiftyos Swiftyos marked this pull request as ready for review June 4, 2025 09:39
- Remove all per-file-ignores from pyproject.toml
- Delete pyrightconfig.json as it's no longer needed
- Replace all star imports with explicit imports in SDK examples and tests
- Reorganize imports in sdk/__init__.py to fix E402 errors
- Fix duplicate imports and ensure all files pass strict linting
- Maintain full functionality while improving code quality

All linting tools (ruff, black, isort, pyright) now pass without any
special exceptions or configuration overrides.
ntindle
ntindle previously approved these changes Jul 9, 2025
@github-project-automation github-project-automation bot moved this from 🚧 Needs work to 👍🏼 Mergeable in AutoGPT development kanban Jul 9, 2025
@github-actions github-actions bot added the conflicts Automatically applied to PRs with merge conflicts label Jul 9, 2025
Copy link
Contributor

github-actions bot commented Jul 9, 2025

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

ntindle
ntindle previously approved these changes Jul 9, 2025
@github-actions github-actions bot removed the conflicts Automatically applied to PRs with merge conflicts label Jul 10, 2025
Copy link
Contributor

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

@ntindle
Copy link
Member

ntindle commented Jul 10, 2025

:shipit:

@Swiftyos Swiftyos merged commit 243400e into dev Jul 10, 2025
32 of 33 checks passed
@github-project-automation github-project-automation bot moved this from 👍🏼 Mergeable to ✅ Done in AutoGPT development kanban Jul 10, 2025
@github-project-automation github-project-automation bot moved this to Done in Frontend Jul 10, 2025
@Swiftyos Swiftyos deleted the swiftyos/sdk branch July 10, 2025 14:18
Copy link
Contributor

🧹 Auto-undeploying: PR closed with active deployment. Cleaning up development environment for PR #10074.

@Swiftyos
Copy link
Contributor Author

🧹 Preview Environment Cleaned Up

All resources for PR #10074 have been removed:

  • ☸️ Kubernetes namespace deleted
  • 🗃️ Database schema pr_10074 dropped

Cleanup completed successfully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Status: Done
Development

Successfully merging this pull request may close these issues.

6 participants