Post 06

The Skills System: Extensible AI Capabilities

Designing a skill-based architecture for AI capabilities with triggers, prompts, and parameters

Nov 29, 2025 12 min read AI, Skills, Architecture

Why Skills?

As TimOS grew, we faced a design challenge: how do you make AI capabilities modular, testable, and extensible? Hardcoding prompts throughout the codebase would create maintenance nightmares. We needed a system.

The Core Insight

A Skill is a reusable AI capability with a defined trigger, prompt template, required context, and expected output format. Skills can be system-provided or user-customized.

Skill Architecture

┌─────────────────────────────────────────────────────────┐
│                      SKILL                               │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  name: "daily-reflection"                               │
│  description: "End-of-day synthesis and insights"       │
│                                                          │
│  TRIGGERS (what invokes this skill)                     │
│  ├── Natural: "reflect on today"                        │
│  ├── Command: "/reflect"                                │
│  └── Scheduled: "18:00 daily"                           │
│                                                          │
│  CONTEXT REQUIREMENTS (what data it needs)              │
│  ├── Daily entries from today                           │
│  ├── Morning pulse data                                 │
│  ├── EOD reflection (if completed)                      │
│  └── Pillar scores                                      │
│                                                          │
│  PROMPT TEMPLATE                                         │
│  "You are reviewing {{user_name}}'s day. Given:         │
│   - Morning state: {{morning_pulse}}                    │
│   - Entries: {{daily_entries}}                          │
│   Provide insights on patterns and one actionable..."   │
│                                                          │
│  OUTPUT FORMAT                                           │
│  { patterns: [], insights: [], action: string }         │
│                                                          │
└─────────────────────────────────────────────────────────┘

Database Schema

// api/src/prisma/vault.prisma
model Skill {
  id              String   @id @default(uuid())
  userId          String?  @map("user_id")  // null = system skill
  name            String
  slug            String   @unique
  description     String?
  category        String   @default("general")

  // Trigger configuration
  triggers        String   @db.Text  // JSON array
  naturalTriggers String?  @db.Text  // Natural language patterns

  // Prompt configuration
  systemPrompt    String   @db.Text
  userPromptTemplate String @db.Text
  contextScope    String   @default("standard")  // minimal, standard, comprehensive

  // Parameters
  parameters      String?  @db.Text  // JSON schema for required params
  outputFormat    String?  @db.Text  // Expected response structure

  // Metadata
  isSystem        Boolean  @default(false)
  isActive        Boolean  @default(true)
  version         Int      @default(1)

  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt

  usageLogs       SkillUsageLog[]

  @@map("skills")
}

model SkillUsageLog {
  id              String   @id @default(uuid())
  skillId         String   @map("skill_id")
  userId          String   @map("user_id")

  trigger         String   // What triggered the skill
  inputTokens     Int      @default(0)
  outputTokens    Int      @default(0)
  latencyMs       Int      @default(0)
  success         Boolean  @default(true)
  errorMessage    String?

  createdAt       DateTime @default(now())

  skill           Skill    @relation(fields: [skillId], references: [id])

  @@map("skill_usage_logs")
}

Default Skills

TimOS ships with 5 default skills. Users can customize these or create their own:

Daily Reflection
/reflect

Synthesizes your day into patterns, insights, and one actionable takeaway.

Context: Today's entries, morning pulse, EOD reflection, pillar scores
Morning Intention
/intention

Based on your current state and yesterday's patterns, suggests focus areas for today.

Context: Morning pulse, yesterday's recap, pillar targets, upcoming schedule
Quick Capture
/capture

Quickly categorizes and stores a thought, assigning it to the appropriate pillar.

Context: User's pillars, recent entries (for tone matching)
Task Brain Dump
/braindump

Takes an unstructured brain dump and organizes it into actionable tasks by pillar.

Context: User's pillars, current priorities, pillar targets
Weekly Patterns
/patterns

Analyzes the past week to identify recurring themes, energy patterns, and blind spots.

Context: Past 7 days of entries, feels data, pillar scores, habit completions

Skill Execution Flow

async function executeSkill(
  skillSlug: string,
  userId: string,
  additionalContext?: any
): Promise<SkillResult> {
  const startTime = Date.now();

  // 1. Load the skill
  const skill = await vaultDb.skill.findUnique({
    where: { slug: skillSlug }
  });

  if (!skill || !skill.isActive) {
    throw new Error(`Skill ${skillSlug} not found or inactive`);
  }

  // 2. Build context based on skill requirements
  const context = await buildContext(userId, {
    scope: skill.contextScope,
    dateRange: getContextDateRange(skill),
  });

  // 3. Compile the prompt
  const systemPrompt = skill.systemPrompt;
  const userPrompt = compileTemplate(
    skill.userPromptTemplate,
    { ...context, ...additionalContext }
  );

  // 4. Execute AI call
  const response = await aiOrchestrator.chat({
    userId,
    messages: [
      { role: 'system', content: systemPrompt },
      { role: 'user', content: userPrompt }
    ],
    temperature: 0.7,
  });

  // 5. Parse and validate output
  const output = parseSkillOutput(response, skill.outputFormat);

  // 6. Log usage
  await vaultDb.skillUsageLog.create({
    data: {
      skillId: skill.id,
      userId,
      trigger: additionalContext?.trigger || 'api',
      inputTokens: response.usage?.promptTokens || 0,
      outputTokens: response.usage?.completionTokens || 0,
      latencyMs: Date.now() - startTime,
      success: true,
    }
  });

  return output;
}

Natural Language Triggers

Skills can be triggered naturally through conversation. The system uses pattern matching to detect intent:

// Skill trigger patterns
const TRIGGER_PATTERNS = {
  'daily-reflection': [
    /reflect on (my )?day/i,
    /how (was|did) (my )?day go/i,
    /summarize today/i,
    /what happened today/i,
  ],
  'morning-intention': [
    /set (my )?intention/i,
    /what should I focus on/i,
    /plan (my )?day/i,
    /morning briefing/i,
  ],
  'quick-capture': [
    /^capture[: ]/i,
    /^note[: ]/i,
    /^remember[: ]/i,
  ],
  'task-brain-dump': [
    /brain dump/i,
    /dump (my )?tasks/i,
    /organize (my )?thoughts/i,
  ],
  'weekly-patterns': [
    /patterns? (this|last) week/i,
    /weekly (review|analysis)/i,
    /what patterns/i,
  ],
};

function detectSkillTrigger(input: string): string | null {
  for (const [skillSlug, patterns] of Object.entries(TRIGGER_PATTERNS)) {
    for (const pattern of patterns) {
      if (pattern.test(input)) {
        return skillSlug;
      }
    }
  }
  return null;
}

Skill API Endpoints

// GET /api/skills - List available skills
// GET /api/skills/:slug - Get skill details
// POST /api/skills - Create custom skill
// PUT /api/skills/:id - Update skill
// DELETE /api/skills/:id - Delete custom skill (not system)
// POST /api/skills/:slug/execute - Execute a skill
// GET /api/skills/:slug/usage - Get usage stats
Privacy First

When building context for skills, all user data is decrypted just-in-time and never stored in plaintext. The AI provider receives only the compiled prompt - no raw database access.

Future: Scheduled Skills

The next phase will add scheduled skill execution:

// Example scheduled trigger configuration
{
  "skill": "daily-reflection",
  "schedule": {
    "type": "daily",
    "time": "18:00",
    "timezone": "America/New_York",
    "conditions": {
      "requiresActivity": true,  // Only if user was active today
      "minEntries": 1
    }
  },
  "delivery": {
    "type": "push",
    "fallback": "email"
  }
}
Skills System Stats

Default skills: 5
Trigger types: 3 (command, natural, scheduled)
Context scopes: 3 (minimal, standard, comprehensive)
Implementation time: ~2 hours

Key Takeaways

  • Skills make AI capabilities modular and testable
  • Prompt templates with context variables enable personalization
  • Usage logging enables cost tracking and optimization
  • Natural language triggers make the system feel conversational
  • Privacy-first context building is essential for sensitive data