hbf-core Gotchas
Package-specific pitfalls and non-obvious patterns. Loaded automatically by workflow commands.
Jackson Serialization
- Never use
@JsonProperty(WRITE_ONLY)on fields crossing the hbf-core to hbf-bot boundary: BotDeployment API serializes via Jackson. WRITE_ONLY strips fields from the response, so hbf-bot receives null. Use@PrivatePropertyinstead (only affects the AutoMapped public org info path). OIDCIntegration.clientSecrethas NO annotation: The base class handles secret visibility.@PrivatePropertyremains onemailKeyandfullNameKeyonly.
MongoDB Polymorphic Types
- Prefer regular classes over data classes for MongoDB-persisted polymorphic types: Spring Data resolves subtypes via
_classnatively when subtypes are regular classes withvarproperties (no-arg constructor). Kotlin data classes lack no-arg constructor, forcing customReadingConverter/WritingConverter.Integration,ExternalEntity,LLMCompletionOptionsall use regular classes.Responsestill uses converters (legacy).
Localization
- Use
LanguageCode.code(lowercase: "en", "el") not.name(uppercase: "EN", "EL") when indexingLocalized<T>maps:Localized<T>keys are lowercase..namesilently falls through to fallback (.values.first()), masking the bug.FileUploadNodehas a pre-existing.namebug on develop.
Bot Content Manager
BotContentManagerImplhas 3when(node)blocks for i18n: New FlowGraphNode types with customLocalized<>fields must be added to all three: (1)trimActivityLanguages, (2) language detection inrewriteContentLanguage, (3) language remapping inrewriteContentLanguage. Non-nullable fields useremapOrEmpty(), nullable useremap().
Field Sync with hbf-core-api
- Adding a field to hbf-core-api types requires a matching field in hbf-core Kotlin models: Spring Data MongoDB silently drops fields not in the Kotlin model during deserialization. hbf-bot fetches through hbf-core REST API, not direct MongoDB.
Knowledge Base API
fetchKnowledgeBaseArticles(list endpoint) returns articlebodyunconditionally. There is noincludeBodyparameter inOrganizationKnowledgeBaseArticleResource.kt. Thecontentset (which containsbody) is always mapped inKnowledgeBaseArticleMapper.toDto(). The frontend'surlParams: { includeBody: true }on single-article fetches is a no-op — the backend ignores unknown query params. Use the list endpoint withpageSize: 5000to get all articles with bodies in a single call.