Comprehensive backend architecture rules for Nexent zero-code agent platform, covering code quality, environment management, layered architecture, and API design patterns.
Enforce strict backend development standards for Nexent, a zero-code platform for auto-generating agents. These rules ensure clean architecture, proper separation of concerns, and maintainable code across the entire backend stack.
**Rule:** All comments, docstrings, and documentation must be written in clear, concise English. No non-English characters are permitted in code comments (string literals for user-facing content may contain any language).
**Applies to:**
**When reviewing or writing code:**
1. Check all comments and docstrings for non-English characters
2. Flag any use of Chinese, Japanese, or other non-Latin script in comments
3. Verify proper English grammar and spelling
4. Ensure abbreviations are industry-standard and unambiguous
**Good example:**
```python
self.cache_ttl = 60
```
**Bad examples (reject these):**
```python
```
**Rule:** All environment variable access must be centralized in `backend/consts/const.py`. No direct `os.getenv()` or `os.environ.get()` calls are permitted outside this file.
**Architecture:**
**When adding a new environment variable:**
1. Add it to `backend/consts/const.py`:
```python
NEW_CONFIG_VAR = os.getenv("NEW_CONFIG_VAR", "default_value")
```
2. Update `.env.example` with the new variable
3. Import in other modules:
```python
from consts.const import NEW_CONFIG_VAR
```
4. For SDK modules, accept as parameter:
```python
def initialize_client(api_key: str, endpoint: str):
# Accept config as parameters, never read env vars directly
pass
```
**Bad pattern (reject):**
```python
import os
appid = os.getenv("APPID") # FORBIDDEN outside const.py
token = os.environ.get("TOKEN") # FORBIDDEN outside const.py
```
**Purpose:** HTTP boundary layer - parse/validate HTTP input, call services, map domain errors to HTTP responses.
**Responsibilities:**
**Routing and URL Design:**
1. **Path Structure:**
- Keep existing top-level prefixes for backward compatibility (e.g., `"/agent"`, `"/memory"`)
- Use plural nouns for collection resources: `"/agents"`, `"/memories"`
- Use snake_case for all path segments
- Path parameters must be singular, semantic nouns: `"/agents/{agent_id}"`
2. **HTTP Methods:**
- `GET`: Read and list operations only
- `POST`: Create resources, perform searches, or trigger actions with side effects
- `DELETE`: Delete resources or clear collections (ensure idempotency)
- `PUT/PATCH`: Update resources
3. **Authorization:**
- Retrieve bearer token via header injection: `authorization: Optional[str] = Header(None)`
- Use utility helpers from `utils.auth_utils` (e.g., `get_current_user_id`)
4. **Exception Mapping:**
- `UnauthorizedError` → `401 UNAUTHORIZED`
- `LimitExceededError` → `429 TOO_MANY_REQUESTS`
- Parameter/validation errors → `400 BAD_REQUEST` or `406 NOT_ACCEPTABLE`
- Unexpected errors → `500 INTERNAL_SERVER_ERROR`
**Correct endpoint pattern:**
```python
from http import HTTPStatus
import logging
from fastapi import APIRouter, HTTPException, Header
from starlette.responses import JSONResponse
from typing import Optional
from consts.exceptions import LimitExceededError, AgentRunException
from services.agent_service import run_agent
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post("/agent/run")
def run_agent_endpoint(
payload: dict,
authorization: Optional[str] = Header(None)
):
try:
result = run_agent(payload)
return JSONResponse(
status_code=HTTPStatus.OK,
content=result
)
except LimitExceededError as exc:
raise HTTPException(
status_code=HTTPStatus.TOO_MANY_REQUESTS,
detail=str(exc)
)
except AgentRunException as exc:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=str(exc)
)
```
**Purpose:** Implement core business logic orchestration; coordinate repositories, SDK modules, and complex workflows.
**Requirements:**
1. **Business Logic Focus:**
- Implement core business logic and orchestrate complex workflows
- Coordinate multiple repositories or SDK calls
- Handle domain-specific validations
2. **No HTTP Concerns:**
- Never import or raise `HTTPException`
- Never return `JSONResponse` or other HTTP-specific types
- Return plain Python objects (dicts, dataclasses, domain models)
3. **Exception Handling:**
- Raise domain/service exceptions from `backend/consts/exceptions.py`
- Available exceptions:
- `AgentRunException`: Agent execution failure
- `LimitExceededError`: Rate limiting violation
- `UnauthorizedError`: Authorization failure
- `SignatureValidationError`: Request signature validation failure
- `MemoryPreparationException`: Memory preprocessing/retrieval failure
4. **Configuration:**
- No direct environment variable access (use `consts.const`)
- Accept configuration via function parameters when possible
5. **Logging:**
- Use module-level logger: `logger = logging.getLogger(__name__)`
- Log at appropriate levels (DEBUG, INFO, WARNING, ERROR)
**Correct service pattern:**
```python
from typing import Any, Dict
import logging
from consts.exceptions import (
LimitExceededError,
AgentRunException,
MemoryPreparationException
)
logger = logging.getLogger(__name__)
def run_agent(task_payload: Dict[str, Any]) -> Dict[str, Any]:
"""
Execute agent workflow and return domain result.
Args:
task_payload: Task configuration and input data
Returns:
Dict containing execution status and results
Raises:
LimitExceededError: When rate limit exceeded
MemoryPreparationException: When memory preparation fails
AgentRunException: When agent execution fails
"""
# Business logic: rate limiting check
if _is_rate_limited(task_payload):
raise LimitExceededError("Too many requests for this tenant.")
# Business logic: prepare memory
try:
memory = _prepare_memory(task_payload)
except Exception as exc:
logger.error(f"Memory preparation failed: {exc}")
raise MemoryPreparationException(
"Failed to prepare memory."
) from exc
# Business logic: execute agent
try:
result = _execute_core_logic(task_payload, memory)
except Exception as exc:
logger.error(f"Agent execution failed: {exc}")
raise AgentRunException("Agent execution failed.") from exc
return {"status": "ok", "data": result}
```
When refactoring existing code or adding new features, follow this checklist:
```
backend/
├── apps/ # HTTP API layer (FastAPI endpoints)
│ ├── agent_app.py # Agent-related endpoints
│ ├── memory_app.py # Memory-related endpoints
│ └── ...
├── services/ # Business logic orchestration
│ ├── agent_service.py
│ ├── memory_service.py
│ └── ...
├── consts/
│ ├── const.py # Single source of truth for env vars
│ └── exceptions.py # Domain exceptions
└── utils/
└── auth_utils.py # Authentication utilities
sdk/ # Pure configuration-based, no env vars
├── module_a/
└── module_b/
```
Before committing code, verify:
1. **Create Pydantic models** in app layer for request/response
2. **Define domain exception** in `consts/exceptions.py` if needed
3. **Implement business logic** in service layer
4. **Create endpoint** in app layer that calls service
5. **Map exceptions** to HTTP status codes in endpoint
1. **Add to `const.py`**: `NEW_VAR = os.getenv("NEW_VAR", "default")`
2. **Update `.env.example`**: Document purpose and default
3. **Import in modules**: `from consts.const import NEW_VAR`
4. **Pass to SDK**: Never let SDK read env vars directly
1. **Identify env var reads** outside `const.py`
2. **Move to `const.py`** and update imports
3. **Check for non-English comments** and translate
4. **Verify layer separation**: HTTP in apps, logic in services
5. **Add logging** if missing
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/nexent-backend-development-standards-pqso0j/raw