Skip to content

CAT Builder Phase 1: Backend API Foundation

Overview

Phase 1 implements the foundational Backend API for the CAT Builder, providing RESTful CRUD operations for all core entities. This API enables programmatic management of CAT configurations, CAT OS, knowledge domains, and agent pools.

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        BastApp (FastAPI)                        │
├─────────────────────────────────────────────────────────────────┤
│  /api/v1/cat-builder/                                          │
│  ├── /health                 Health check                       │
│  ├── /orgs                   Organizations                      │
│  ├── /orgs/{org_id}/cats     CATs                              │
│  ├── /orgs/{org_id}/cat-os                       │
│  ├── /orgs/{org_id}/knowledge-domains                          │
│  └── /orgs/{org_id}/agent-pools                                │
├─────────────────────────────────────────────────────────────────┤
│                    Service Layer (svc/)                         │
│  OrganizationService │ CATService │ CatOSService   │
│  KnowledgeDomainService │ AgentPoolService                      │
├─────────────────────────────────────────────────────────────────┤
│                    Repository Layer (svc/)                      │
│  BaseRepository<T> - Generic CRUD operations                    │
├─────────────────────────────────────────────────────────────────┤
│                    Data Layer                                   │
│  MongoBaseAPI (bast-ai-mongo) → MongoDB                        │
│  Database: bast_cat_builder                                     │
│  Collections: organizations, cats, cat_os,        │
│               knowledge_domains, agent_pools                    │
└─────────────────────────────────────────────────────────────────┘

Directory Structure

src/apis/agno/bast_agno_api/
├── __init__.py                 # Package exports (cat_builder_api)
├── bp/                         # Blueprint/Routes
│   ├── __init__.py            # Exports cat_builder_api router
│   ├── cat_builder.py         # Main router aggregating sub-routers
│   ├── dependencies.py        # FastAPI dependencies (MongoDB, CAT)
│   ├── organizations.py       # Organization CRUD routes
│   ├── cats.py               # CAT CRUD routes
│   ├── cat_os.py
│   ├── knowledge_domains.py
│   └── agent_pools.py
├── dto/                        # Data Transfer Objects (Pydantic)
│   ├── __init__.py            # All model exports
│   ├── organization.py        # Organization models
│   ├── cat.py                # CAT models
│   ├── cat_os.py # CAT OS models
│   ├── knowledge_domain.py   # Knowledge Domain models
│   └── agent_pool.py         # Agent Pool models
└── svc/                        # Services (Business Logic)
    ├── __init__.py            # Service exports
    ├── database.py            # Database constants, indexes
    ├── base_repository.py     # Generic CRUD repository
    ├── organization_service.py
    ├── cat_service.py
    ├── cat_os_service.py
    ├── knowledge_domain_service.py
    └── agent_pool_service.py

Data Model

Entity Relationships

Organization (1)
    │
    ├── (many) CATs
    │       │
    │       ├── cat_os_id → CAT OS
    │       ├── agent_pool_id → Agent Pool
    │       └── knowledge_domain_ids → [Knowledge Domains]
    │
    ├── (many) CAT OS
    ├── (many) Knowledge Domains
    └── (many) Agent Pools

MongoDB Collections

Collection Index(es) Description
organizations slug (unique) Multi-tenant organizations
cats organization_id, organization_id+prefix (unique), uuid (unique) CAT configurations
cat_os organization_id Identity, personality, ethics modules
knowledge_domains organization_id KB topic configurations
agent_pools organization_id Agent configurations

API Endpoints Reference

Organizations

Method Endpoint Description
GET /orgs List all organizations
POST /orgs Create organization
GET /orgs/{org_id} Get organization with stats
PUT /orgs/{org_id} Update organization
DELETE /orgs/{org_id} Delete organization
GET /orgs/slug/{slug} Get organization by slug
GET /orgs/slug/{slug}/exists Check if slug exists

CATs

Method Endpoint Description
GET /orgs/{org_id}/cats List CATs for organization
POST /orgs/{org_id}/cats Create CAT
GET /orgs/{org_id}/cats/{cat_id} Get CAT with expanded refs
PUT /orgs/{org_id}/cats/{cat_id} Update CAT
DELETE /orgs/{org_id}/cats/{cat_id} Delete CAT
POST /orgs/{org_id}/cats/{cat_id}/activate Activate CAT
POST /orgs/{org_id}/cats/{cat_id}/deactivate Deactivate CAT
GET /orgs/{org_id}/cats/prefix/{prefix} Get CAT by prefix
GET /orgs/{org_id}/cats/prefix/{prefix}/exists Check if prefix exists

CAT OS

Method Endpoint Description
GET /orgs/{org_id}/cat-os List CAT OS
POST /orgs/{org_id}/cat-os Create CAT OS
GET /orgs/{org_id}/cat-os/{cat_os_id} Get with usage stats
PUT /orgs/{org_id}/cat-os/{cat_os_id} Update
DELETE /orgs/{org_id}/cat-os/{cat_os_id} Delete
POST /orgs/{org_id}/cat-os/{cat_os_id}/publish Publish
POST /orgs/{org_id}/cat-os/{cat_os_id}/draft Set to draft

Knowledge Domains

Method Endpoint Description
GET /orgs/{org_id}/knowledge-domains List knowledge domains
POST /orgs/{org_id}/knowledge-domains Create knowledge domain
GET /orgs/{org_id}/knowledge-domains/{domain_id} Get with usage stats
PUT /orgs/{org_id}/knowledge-domains/{domain_id} Update
DELETE /orgs/{org_id}/knowledge-domains/{domain_id} Delete
POST /orgs/{org_id}/knowledge-domains/{domain_id}/publish Publish
POST /orgs/{org_id}/knowledge-domains/{domain_id}/enable Enable
POST /orgs/{org_id}/knowledge-domains/{domain_id}/disable Disable

Agent Pools

Method Endpoint Description
GET /orgs/{org_id}/agent-pools List agent pools
POST /orgs/{org_id}/agent-pools Create agent pool
GET /orgs/{org_id}/agent-pools/{pool_id} Get with usage stats
PUT /orgs/{org_id}/agent-pools/{pool_id} Update
DELETE /orgs/{org_id}/agent-pools/{pool_id} Delete
GET /orgs/{org_id}/agent-pools/{pool_id}/agents/{agent_name} Get agent
POST /orgs/{org_id}/agent-pools/{pool_id}/agents Add agent
PUT /orgs/{org_id}/agent-pools/{pool_id}/agents/{agent_name} Update agent
DELETE /orgs/{org_id}/agent-pools/{pool_id}/agents/{agent_name} Remove agent

DTOs (Pydantic Models)

Organization Models

class OrganizationSettings(BaseModel):
    default_model: str = "gpt-4o"
    accepted_score: float = 0.25
    persona_provider: str = "bast"

class OrganizationCreate(BaseModel):
    name: str          # 1-100 chars
    slug: str          # lowercase, alphanumeric, hyphens only
    settings: OrganizationSettings = OrganizationSettings()

class OrganizationUpdate(BaseModel):
    name: Optional[str]
    settings: Optional[OrganizationSettings]

class OrganizationInDB(BaseModel):
    id: str            # MongoDB _id
    name: str
    slug: str
    settings: OrganizationSettings
    created_at: datetime
    updated_at: datetime

class OrganizationResponse(OrganizationInDB):
    cats_count: int = 0
    cat_os_count: int = 0
    knowledge_domains_count: int = 0
    agent_pools_count: int = 0

CAT Models

class CATSettings(BaseModel):
    accepted_score: float = 0.25
    cache_ttl: int = 300
    debug_mode: bool = False

class CATEnvironmentOverride(BaseModel):
    cat_os_id: Optional[str]
    agent_pool_id: Optional[str]
    knowledge_domain_ids: Optional[List[str]]
    settings: Optional[CATSettings]

class CATCreate(BaseModel):
    name: str          # 1-100 chars
    prefix: str        # lowercase, alphanumeric, underscores
    description: str = ""
    cat_os_id: Optional[str]
    agent_pool_id: Optional[str]
    knowledge_domain_ids: List[str] = []

class CATInDB(BaseModel):
    id: str
    organization_id: str
    uuid: str          # Auto-generated: PREFIX_XXXXXX
    name: str
    prefix: str
    description: str
    status: Literal["draft", "active", "disabled"]
    version: str
    cat_os_id: Optional[str]
    agent_pool_id: Optional[str]
    knowledge_domain_ids: List[str]
    environments: Dict[str, CATEnvironmentOverride]
    created_at: datetime
    updated_at: datetime
    created_by: str

class CATResponse(CATInDB):
    cat_os: Optional[dict]  # Expanded reference
    knowledge_domains: List[dict]       # Expanded references
    agent_pool: Optional[dict]          # Expanded reference

CAT OS Models

class ConceptContent(BaseModel):
    label: str
    hasAnswer: Optional[str]
    triggers: List[str] = []

class IdentityModule(BaseModel):
    name: ConceptContent
    role: ConceptContent
    org: ConceptContent
    capabilities: List[ConceptContent] = []

class PersonalityModule(BaseModel):
    tone: ConceptContent
    style: ConceptContent
    traits: List[ConceptContent] = []

class EthicsModule(BaseModel):
    principles: List[ConceptContent] = []
    boundaries: List[ConceptContent] = []

class FeatureModel(BaseModel):
    id: str
    label: str
    triggers: List[str] = []
    hasAnswer: Optional[str]
    handler_type: Optional[str]

class CatOSContent(BaseModel):
    identity: Optional[IdentityModule]
    personality: Optional[PersonalityModule]
    ethics: Optional[EthicsModule]
    features: List[FeatureModel] = []

class CatOSCreate(BaseModel):
    name: str
    description: str = ""
    content: CatOSContent = CatOSContent()

class CatOSInDB(BaseModel):
    id: str
    organization_id: str
    name: str
    description: str
    content: CatOSContent
    status: Literal["draft", "published"]
    version: str
    created_at: datetime
    updated_at: datetime

Knowledge Domain Models

class KnowledgeTopic(BaseModel):
    id: str
    label: str
    description: str = ""
    keywords: List[str] = []
    kb_collection: Optional[str]
    entities: List[str] = []

class KnowledgeDomainContent(BaseModel):
    label: str
    topics: List[KnowledgeTopic] = []

class KBConfig(BaseModel):
    collection: str
    search_type: str = "hybrid"
    num_documents: int = 5

class KnowledgeDomainCreate(BaseModel):
    name: str
    description: str = ""
    content: KnowledgeDomainContent = KnowledgeDomainContent(label="")
    kb_config: Optional[KBConfig]

class KnowledgeDomainInDB(BaseModel):
    id: str
    organization_id: str
    name: str
    description: str
    content: KnowledgeDomainContent
    kb_config: Optional[KBConfig]
    status: Literal["draft", "published"]
    enabled: bool
    created_at: datetime
    updated_at: datetime

Agent Pool Models

class AgentConfig(BaseModel):
    name: str
    description: str = ""
    model_id: str = "gpt-4o"
    temperature: float = 0.7
    max_tokens: Optional[int]
    instructions: Optional[str]
    tools: List[str] = []
    enabled: bool = True
    config: Dict[str, Any] = {}

class AgentPoolCreate(BaseModel):
    name: str
    description: str = ""
    agents: Dict[str, AgentConfig] = {}

class AgentPoolInDB(BaseModel):
    id: str
    organization_id: str
    name: str
    description: str
    agents: Dict[str, AgentConfig]
    status: Literal["draft", "published"]
    created_at: datetime
    updated_at: datetime

Service Layer Pattern

All services follow a consistent pattern:

class EntityService:
    def __init__(self, mongodb: MongoBaseAPI, db_name: str = DATABASE_NAME):
        self.mongodb = mongodb
        self.db_name = db_name
        self.repo = BaseRepository(mongodb, COLLECTION_NAME, db_name)

    def create(self, data: EntityCreate) -> EntityInDB: ...
    def get_by_id(self, id: str) -> Optional[EntityInDB]: ...
    def list(self, skip: int, limit: int) -> List[EntityInDB]: ...
    def update(self, id: str, data: EntityUpdate) -> Optional[EntityInDB]: ...
    def delete(self, id: str) -> bool: ...

BaseRepository Methods

class BaseRepository(Generic[T]):
    def create(self, data: Dict) -> str          # Returns inserted ID
    def get_by_id(self, id: str) -> Optional[Dict]
    def get_by_field(self, field: str, value: Any) -> Optional[Dict]
    def list(self, filter: Dict, skip: int, limit: int) -> List[Dict]
    def update(self, id: str, data: Dict) -> bool
    def delete(self, id: str) -> bool
    def count(self, filter: Dict) -> int
    def exists(self, id: str) -> bool
    def find_one(self, filter: Dict) -> Optional[Dict]

Integration with BastApp

The CAT Builder API is integrated via the main router:

# In org-services main.py or cat-runtime main.py
from bast_agno_api import cat_builder_api

api_router = APIRouter()
api_router.include_router(cat_builder_api, prefix='/cat-builder')
app.include_router(api_router, prefix='/api/v1')

Dependencies

The API uses FastAPI dependencies for database access:

# dependencies.py
def get_mongo_client(request: Request):
    """Get MongoDB client from CAT configuration."""
    cat = request.app.state.CAT
    mongo_conf = cat.mongodb
    return getMongoDBClient(mongo_conf)

Running Integration Tests

# Run all CRUD service tests
pants run src/apis/agno/integration/test_crud_services.py

# Run API route tests
pants run src/apis/agno/integration/test_api_routes.py

# Run DTO validation tests
pants run src/apis/agno/integration/test_dto_models.py

# Run MongoDB integration tests
pants run src/apis/agno/integration/test_mongodb_integration.py

Configuration Requirements

CAT Configuration (YAML)

The API requires a CAT configuration with MongoDB settings:

# resources/config/testcat.yaml
catname: testcat
mongodb:
  uri: "${MONGODB_URI}"
  database: bast_db

Environment Variables

export MONGODB_URI="mongodb+srv://..."

Error Handling

All endpoints follow consistent error responses:

Status Code Description
200 OK Successful GET/PUT
201 Created Successful POST
204 No Content Successful DELETE
400 Bad Request Invalid input data
404 Not Found Entity not found
409 Conflict Duplicate key (slug, prefix, etc.)
500 Internal Server Error Server error

Next Steps (Phase 2+)

  1. Phase 2: UI Components - React UI for CAT Builder dashboard
  2. Phase 3: CAT Composition - Link components to CATs
  3. Phase 4: Import/Export - YAML import/export for CAT configurations
  4. Phase 5: Versioning - Version control for configurations

Files Summary

File Purpose
bp/cat_builder.py Main router aggregating all sub-routers
bp/dependencies.py FastAPI dependencies for DB access
bp/organizations.py Organization CRUD routes
bp/cats.py CAT CRUD routes
bp/cat_os.py CAT OS CRUD routes
bp/knowledge_domains.py Knowledge Domain CRUD routes
bp/agent_pools.py Agent Pool CRUD routes
dto/*.py Pydantic models for all entities
svc/database.py Database constants and index setup
svc/base_repository.py Generic CRUD repository
svc/*_service.py Business logic services