Skip to content
tzurot-architecture logo

Tzurot v3 Architecture

tzurot-architecture

Microservices architecture for Tzurot v3 - Service boundaries, responsibilities, dependency rules, and anti-patterns from v2. Use when deciding where code belongs or designing new features.

SKILL.md

Full skill instructions

Tzurot v3 Architecture

Use this skill when: Adding new features, deciding where code belongs, designing system interactions, or refactoring service boundaries.

Quick Reference

Discord User
    ↓
bot-client (Discord.js)
    ↓ HTTP
api-gateway (Express + BullMQ)
    ↓ Redis Queue
ai-worker (AI + pgvector)
    ↓
OpenRouter/​Gemini API

Core Principles

  1. Simple, clean classes - No DDD over-engineering (learned from v2)
  2. Clear service boundaries - Each service has single responsibility
  3. No circular dependencies - Services can't import from each other
  4. Shared code in common-types - Cross-service types, utils, services
  5. Constructor injection - Simple dependency passing, no DI containers

Three Microservices

ServiceResponsibilityDoesDoes NOT
bot-clientDiscord interfaceEvents, webhooks, commands, formattingBusiness logic, AI calls, direct DB
api-gatewayHTTP API + queueEndpoints, validation, job creationAI processing, Discord interaction
ai-workerAI + memoryJobs, memory, AI calls, embeddingsHTTP endpoints, Discord interaction

Where to Put New Code

TypeLocation
Webhook/​message formattingbot-client/
Slash commandsbot-client/​commands/
HTTP endpointsapi-gateway/​routes/
Job creationapi-gateway/​queue.ts
AI provider clientsai-worker/​providers/
Memory/​embeddingsai-worker/​services/
Shared types/​constantscommon-types/
Discord type guardscommon-types/​types/

Autocomplete Utilities (CRITICAL)

ALWAYS check for existing utilities before writing autocomplete handlers.

Available in bot-client/​src/​utils/​autocomplete/:

UtilityPurposeOption Names
handlePersonalityAutocompletePersonality selectionpersonality, character
handlePersonaAutocompleteProfile/​persona selectionprofile, persona
// ✅ GOOD - Delegate to shared utility
import { handlePersonalityAutocomplete } from '../​../​utils/​autocomplete/​personalityAutocomplete.js';

await handlePersonalityAutocomplete(interaction, {
  optionName: 'personality',
  showVisibility: true,
  ownedOnly: false,
});

// ❌ BAD - Duplicating 50+ lines of autocomplete logic

Error Message Patterns

LayerPatternExample
api-gatewayClean JSON, NO emojis{ "error": "NOT_FOUND", "message": "Persona not found" }
bot-clientADD emojis for users'❌ Profile not found.'
// ✅ Gateway - clean for programmatic use
sendError(res, ErrorResponses.notFound('Persona'));

// ✅ Bot - emoji for users
await interaction.editReply({ content: '❌ Profile not found.' });

Anti-Patterns from v2 (DON'T DO)

PatternWhy Notv3 Alternative
Generic IRepository<T>Too abstractConcrete service methods
DI containersOver-engineeredDirect instantiation
Controller→UseCase→Service→Repository→ORMToo many layersRoute→Service→Prisma
Complex event busUnnecessaryRedis pub/​sub for cache only
Value objects everywhereOverheadSimple validation functions
// ❌ v2 - Container hell
container.bind('PersonalityService').to(PersonalityService);
const service = container.get('PersonalityService');

// ✅ v3 - Simple
const service = new PersonalityService(prisma);

Dependency Injection

// ✅ GOOD - Simple constructor injection
class MyService {
  constructor(
    private prisma: PrismaClient,
    private redis: Redis
  ) {}
}

const service = new MyService(prisma, redis);

When to Extract a Service

Extract when:

  • Shared across multiple microservices → common-types
  • Complex business logic
  • Stateful operations
  • Easier testability needed

Keep inline when:

  • Used in one place only
  • Stateless utility function
  • Very simple logic

Database Access

Direct Prisma in services - No repository pattern

// ✅ Direct Prisma
async getPersonality(id: string) {
  return this.prisma.personality.findUnique({ where: { id } });
}

// ❌ Generic repository
interface PersonalityRepository {
  findById(id: string): Promise<Personality>;
}

Configuration

  • Environment variables: Secrets (tokens, DB URLs)
  • common-types constants: Application config (timeouts, limits)
import { TIMEOUTS, RETRY_CONFIG } from '@tzurot/​common-types';
const timeout = TIMEOUTS.LLM_INVOCATION;

Related Skills

  • tzurot-async-flow - BullMQ job patterns
  • tzurot-db-vector - Database patterns
  • tzurot-types - Type definitions
  • tzurot-gemini-collab - Major design decisions

References

  • Full architecture: CLAUDE.md#architecture
  • Project structure: CLAUDE.md#project-structure
  • Architecture decisions: docs/​architecture/​ARCHITECTURE_DECISIONS.md

More Other skills

Delegate independent tasks to specialized agents working concurrently with isolated context.

295.4K 206.3K
View

Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.

179.7K 100.1K
View

Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.

179.7K 89.5K
View

A set of resources to help me write all kinds of internal communications, using the formats that my company likes to use. Claude should use this skill whenever asked to write some sort of internal communications (status reports, leadership updates, 3P updates, company newsletters, FAQs, incident reports, project updates, etc.).

179.7K 76.1K
View

Fundamental design principles for writing maintainable, testable Python code.

40.2K 21.9K
View

Modern responsive layouts using container queries, fluid typography, CSS Grid, and mobile-first strategies.

40.2K 20K
View

Generate Playwright tests from scenarios using interactive browser exploration and validation.

39.7K 18.2K
View

Modern React state management with Redux Toolkit, Zustand, Jotai, and React Query for every state category.

40.2K 14.7K
View

GDPR-compliant data handling with consent management, data subject rights, and privacy controls.

40.2K 14.3K
View

Python error handling patterns including input validation, exception hierarchies, and partial failure handling. Use when implementing validation logic, designing exception strategies, handling batch processing failures, or building robust APIs.

40.2K 13.5K
View

Detailed multi-file refactor planning with safety checks and rollback guidance.

39.7K 13K
View