Skip to content

Framework Development

alexheifetz edited this page Sep 22, 2025 · 1 revision

Framework Development

This section contains documentation for developers working on the Embabel Agent Framework itself, including architecture decisions, implementation plans, and migration guides.

🏗️ Architecture & Implementation

Core Framework Evolution

Implementation Strategy

The framework follows an incremental transformation approach:

  1. Property Foundation ✅ - Unified configuration system
  2. Hybrid Migration ✅ - Backward compatibility during transition
  3. Plugin Architecture 🔄 - Personality and model provider plugins
  4. Profile Deprecation 📋 - Clean removal of legacy patterns

Key Architectural Decisions

Property-Based Configuration

Moving from Spring profiles to property-based activation provides:

  • Library-centric design - No profile dependencies
  • Environment flexibility - Easy override with environment variables
  • IDE support - Auto-completion and validation
  • Better testing - Cleaner test configuration

Plugin Infrastructure

Transforming core systems into plugin architectures enables:

  • Runtime extensibility - Add capabilities without code changes
  • Dynamic discovery - Automatic registration of providers
  • Clean separation - Platform vs application concerns
  • Federation support - Multi-agent system coordination

🔄 Migration Strategies

Backward Compatibility Approach

The framework maintains 100% backward compatibility during transitions:

// OLD: Profile-based (still works)
@Profile("starwars")
@Component
class StarWarsLogging

// NEW: Property-based (preferred)
@ConditionalOnProperty("embabel.agent.logging.personality", havingValue = "starwars")
@Component  
class StarWarsLogging

Dual Support Pattern

Critical systems support both old and new approaches simultaneously:

@Configuration
class HybridConfiguration {
    
    // NEW: Primary approach
    @Bean
    @Primary
    @ConditionalOnProperty("embabel.agent.infrastructure.neo4j.enabled")
    fun propertyBasedNeo4j(): Neo4jConfig
    
    // OLD: Fallback for compatibility
    @Bean
    @Profile("neo")
    @ConditionalOnMissingBean
    fun profileBasedNeo4j(): Neo4jConfig
}

📋 Implementation Progress

Completed Phases

Phase A: Platform Foundation

  • Property segregation - Clear separation between platform and application config
  • Migration detection - Automatic scanning for deprecated usage
  • Unified properties - Single source of truth for platform configuration

Phase B: Core Migrations

  • Hybrid adapter pattern - Legacy classes become adapters
  • Constructor injection - Clean dependency management
  • Test infrastructure - Comprehensive testing patterns

Current Phase: Personality Plugin Infrastructure 🔄

Plugin Architecture Goals

Transform the personality system into a modern plugin architecture:

// Target: Plugin-based personality system
interface PersonalityProvider {
    val name: String
    val description: String
    fun createEventListener(): LoggingAgenticEventListener
}

@Component
class PersonalityRegistry(
    private val providers: List<PersonalityProvider>
) {
    fun switchPersonality(name: String): Boolean
    fun getAvailablePersonalities(): Set<String>
}

Implementation Iterations

  1. Property-Based Configuration - Replace profile activation
  2. Plugin Infrastructure - Registry and provider interfaces
  3. Provider Wrappers - Convert existing personalities
  4. Runtime Management - Dynamic switching capabilities
  5. Enhanced Properties - External configuration support

Future Phases

Phase C: Model Provider Plugins 📋

Apply plugin patterns to model providers:

  • Dynamic model discovery
  • Runtime provider switching
  • Cost-aware model selection
  • Performance-based routing

Phase D: Agent Federation 🔮

Enable multi-agent coordination:

  • Remote agent discovery
  • Cross-platform communication
  • Distributed goal achievement
  • Resource sharing protocols

🛠️ Development Patterns

Configuration Class Patterns

Platform Configuration

Internal framework behavior:

@ConfigurationProperties("embabel.agent.platform")
data class AgentPlatformProperties(
    val scanning: ScanningConfig,
    val autonomy: AutonomyConfig,
    val models: ModelsConfig
)

Application Configuration

Business logic and deployment:

@ConfigurationProperties("embabel.agent.logging")
data class PersonalityConfiguration(
    var personality: String = "default",
    var verbosity: String = "info"
)

Auto-Configuration Patterns

Conditional Activation

@Configuration
@ConditionalOnProperty("embabel.agent.infrastructure.neo4j.enabled")
@ConditionalOnClass(Neo4jRepository::class)
class Neo4jAutoConfiguration

Provider Registration

@Configuration
class ModelProviderAutoConfiguration {
    
    @Bean
    @ConditionalOnBean(OllamaApi::class)
    fun ollamaModelProvider(): ModelProvider = OllamaModelProvider()
}

Testing Patterns

Migration Testing

@Test
fun `should support both legacy and new configuration`() {
    // Test dual support during migration
    assertThat(legacyConfig).isNotNull()
    assertThat(newConfig).isNotNull() 
    assertThat(newConfig.getValue()).isEqualTo(legacyConfig.getValue())
}

Auto-Configuration Testing

@SpringBootTest
@TestPropertySource(properties = [
    "embabel.agent.platform.test.mockMode=true"
])
class AutoConfigurationTest {
    
    @Autowired
    private lateinit var agentPlatform: AgentPlatform
    
    @Test
    fun `should auto-configure platform correctly`()
}

📖 Contributing to Framework Development

Getting Started

  1. Understand the Architecture - Read existing implementation plans
  2. Follow Patterns - Use established configuration and testing patterns
  3. Maintain Compatibility - Never break existing APIs during transitions
  4. Test Comprehensively - Both unit and integration tests required

Implementation Guidelines

Property Naming Conventions

# Platform internals
embabel.agent.platform.scanning.enabled=true

# Application configuration  
embabel.agent.logging.personality=starwars

# Infrastructure integration
embabel.agent.infrastructure.neo4j.enabled=true

Migration Comments

// MIGRATED: @ConfigurationProperties("embabel.autonomy") → AgentPlatformProperties.autonomy
@Component
class AutonomyProperties(platformProperties: AgentPlatformProperties) {
    val goalConfidenceCutOff = platformProperties.autonomy.goalConfidenceCutOff
}

Validation Requirements

@ConfigurationProperties("embabel.agent.logging")
@Validated
data class PersonalityConfiguration(
    @field:Pattern(regexp = "^(default|starwars|severance)$")
    var personality: String = "default"
)

Testing Requirements

  1. Unit tests for individual configuration classes
  2. Integration tests for auto-configuration behavior
  3. Migration tests for backward compatibility
  4. End-to-end tests for complete scenarios

Documentation Standards

  1. Implementation plans for major changes
  2. Migration guides for breaking changes
  3. Code examples for new patterns
  4. Architecture decisions recorded in markdown

🎯 Success Criteria

Technical Goals

  • Zero breaking changes during migration periods
  • Complete test coverage for all new patterns
  • Performance maintained or improved
  • Memory usage optimized

Developer Experience Goals

  • Intuitive configuration with clear property names
  • IDE support with auto-completion and validation
  • Clear error messages when configuration is invalid
  • Comprehensive documentation with examples

Architectural Goals

  • Clean separation between platform and application concerns
  • Plugin extensibility without framework modifications
  • Federation readiness for multi-agent systems
  • Cloud-native deployment support

This framework development documentation ensures that contributors understand both the current state and the evolution path of the Embabel Agent Framework, enabling consistent and high-quality contributions to the platform.

Clone this wiki locally