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+)
- Phase 2: UI Components - React UI for CAT Builder dashboard
- Phase 3: CAT Composition - Link components to CATs
- Phase 4: Import/Export - YAML import/export for CAT configurations
- 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 |