# Skills API - Task Instructions with Tools

The Skills API provides a way to manage skills - instructions on how to accomplish tasks using tools. Skills can be database-persisted or runtime-registered with optional setup/teardown functions.

## Quick Start

```typescript
import { definePlugin } from '@majkapp/plugin-kit';

// Access skills from plugin context
.function('enableCodeReview', {
  description: 'Enable code review mode',
  input: { type: 'object', properties: {}, additionalProperties: false },
  output: { type: 'object', properties: { instructions: { type: 'string' } } },
  handler: async (input, ctx) => {
    const result = await ctx.majk.skills.enable(ctx, {
      skill: 'code-review-mode'
    });
    return { instructions: result.instructions };
  }
})
```

## Interface Overview

```typescript
export interface SkillsAPI {
    // Discovery
    list(conversationId?: string, includeDisabled?: boolean): Promise<ListSkillsResult>;
    search(conversationId: string | undefined, input: SearchSkillsInput): Promise<SearchSkillsResult>;
    getById(skillId: string): Promise<Skill | null>;

    // Database skills
    add(conversationId: string | undefined, input: AddSkillInput): Promise<AddSkillResult>;
    update(input: UpdateSkillInput): Promise<UpdateSkillResult>;
    delete(input: DeleteSkillInput): Promise<boolean>;

    // Activation
    enable(context: SkillContext, input: EnableSkillInput): Promise<EnableSkillResult>;
    disable(conversationId: string, input: DisableSkillInput): Promise<boolean>;

    // Runtime skills
    registerRuntime(skill: RuntimeSkill): Promise<void>;
    unregisterRuntime(skillId: string): Promise<boolean>;
    getRuntime(skillId: string): Promise<RuntimeSkill | undefined>;

    // Events
    on(eventType: SkillEventType, handler: (event: SkillEvent) => void): Promise<Unsubscribe>;
}
```

## Core Concepts

### Skill Types

1. **Database Skills** - Persisted skills created via `add()`
2. **Runtime Skills** - Memory-only skills with setup/teardown functions

### Skill Definition

```typescript
interface SkillDefinition {
  id: string;           // Unique identifier
  name: string;         // Display name
  description: string;  // One-sentence description
  instructions: string; // Full task instructions
  tags?: string[];      // Optional categorization
  enabled: boolean;     // Whether currently active
}
```

## Discovery Operations

### List Skills

```typescript
// List all skills
const { skills, total } = await ctx.majk.skills.list();

// Include disabled skills
const all = await ctx.majk.skills.list(undefined, true);

// List conversation-specific skills
const conversationSkills = await ctx.majk.skills.list(conversationId);

console.log(`Found ${skills.length} skills out of ${total} total`);
```

### Search Skills

```typescript
const results = await ctx.majk.skills.search(conversationId, {
  query: 'code review',
  limit: 10,
  includeDisabled: false
});

console.log('Well-matching skills:', results.matching);
console.log('Related skills:', results.related);
console.log('Total found:', results.total);
```

### Get Skill by ID

```typescript
const skill = await ctx.majk.skills.getById('code-review-mode');
if (skill) {
  console.log('Skill:', skill.name);
  console.log('Instructions:', skill.instructions);
  console.log('Source:', skill.source); // 'database' | 'runtime'
}
```

## Database Skills Management

### Adding Skills

```typescript
const result = await ctx.majk.skills.add(conversationId, {
  id: 'custom-reviewer',      // Optional - auto-generated if not provided
  name: 'Custom Code Reviewer',
  description: 'Reviews code with custom standards',
  instructions: `You are now in Custom Code Review Mode.

  When reviewing code:
  1. Check for our company coding standards
  2. Look for security vulnerabilities
  3. Suggest performance improvements
  4. Verify test coverage

  Use these tools:
  - Static analysis tools
  - Security scanners
  - Test coverage reports`,
  tags: ['review', 'code-quality', 'security'],
  enabled: true
});

console.log(`Created skill: ${result.name} (${result.id})`);
```

### Updating Skills

```typescript
const result = await ctx.majk.skills.update({
  id: 'custom-reviewer',
  name: 'Enhanced Code Reviewer',
  description: 'Reviews code with enhanced AI analysis',
  instructions: 'Updated instructions here...',
  tags: ['review', 'ai', 'enhanced']
});

console.log(`Updated: ${result.name}, Success: ${result.updated}`);
```

### Deleting Skills

```typescript
const deleted = await ctx.majk.skills.delete({ id: 'custom-reviewer' });
console.log('Skill deleted:', deleted);
```

## Skill Activation

### Enabling Skills

```typescript
// Basic skill enablement
const result = await ctx.majk.skills.enable(ctx, { skill: 'code-review-mode' });
console.log('Skill enabled:', result.name);
console.log('Instructions to follow:', result.instructions);

// The instructions returned include:
// - Base skill instructions
// - Additional context from setup function (if any)
```

### Disabling Skills

```typescript
const disabled = await ctx.majk.skills.disable(conversationId, {
  skill: 'code-review-mode'
});
console.log('Skill disabled:', disabled);
```

## Runtime Skills

Runtime skills exist only in memory and can have setup/teardown functions for dynamic behavior.

### Registering Runtime Skills

```typescript
await ctx.majk.skills.registerRuntime({
  id: 'dynamic-analyzer',
  name: 'Dynamic Code Analyzer',
  description: 'Analyzes code with runtime context',
  instructions: 'Base instructions for dynamic analysis...',
  enabled: true,

  // Optional setup function - called when skill is enabled
  setup: async (context: SkillContext) => {
    // Perform setup logic
    console.log(`Setting up for teammate: ${context.teammateId}`);
    console.log(`In conversation: ${context.conversationId}`);

    // Initialize tools, connect to services, etc.
    const projectPath = process.cwd();
    const config = await loadProjectConfig(projectPath);

    // Return additional instructions to prepend
    return `Project configuration loaded from ${projectPath}.
    Using ${config.language} with ${config.framework} framework.`;
  },

  // Optional teardown function - called when skill is disabled
  teardown: async (context: SkillContext) => {
    // Cleanup logic
    console.log(`Cleaning up dynamic analyzer for ${context.teammateId}`);
    await cleanupTempFiles();
    await disconnectServices();
  }
});
```

### Managing Runtime Skills

```typescript
// Get runtime skill
const runtimeSkill = await ctx.majk.skills.getRuntime('dynamic-analyzer');
if (runtimeSkill) {
  console.log('Runtime skill found:', runtimeSkill.name);
}

// Unregister runtime skill
const removed = await ctx.majk.skills.unregisterRuntime('dynamic-analyzer');
console.log('Runtime skill removed:', removed);
```

## Event Handling

Subscribe to skill-related events:

```typescript
// Subscribe to all skill events
const unsubscribe = await ctx.majk.skills.on('skill_enabled', (event) => {
  console.log(`Skill ${event.skillId} enabled at ${event.timestamp}`);
  console.log('Event data:', event.data);
});

// Subscribe to specific events
await ctx.majk.skills.on('skill_added', (event) => {
  console.log('New skill added:', event.skillId);
});

await ctx.majk.skills.on('skill_deleted', (event) => {
  console.log('Skill deleted:', event.skillId);
});

// Clean up subscription
await unsubscribe();
```

Event types:
- `skill_added` - New skill created
- `skill_updated` - Skill modified
- `skill_deleted` - Skill removed
- `skill_enabled` - Skill activated
- `skill_disabled` - Skill deactivated

## Plugin Integration

### Declaring Skills in Plugins

```typescript
import { definePlugin } from '@majkapp/plugin-kit';

const plugin = definePlugin('code-tools', 'Code Analysis Tools', '1.0.0')

  // Declare a skill capability
  .skill({
    id: 'advanced-reviewer',
    name: 'Advanced Code Reviewer',
    description: 'Performs deep code analysis with AI',
    instructions: `You are now in Advanced Code Review Mode.

    Perform comprehensive analysis including:
    - Architecture patterns
    - Performance bottlenecks
    - Security vulnerabilities
    - Maintainability issues`,
    tags: ['review', 'ai', 'advanced']
  })

  .build();
```

## Complete Example

Here's a comprehensive example showing database skills, runtime skills, and event handling:

```typescript
.function('setupCodeReviewWorkflow', {
  description: 'Set up complete code review workflow',
  input: {
    type: 'object',
    properties: {
      projectType: { type: 'string', enum: ['web', 'api', 'mobile'] }
    },
    required: ['projectType'],
    additionalProperties: false
  },
  output: {
    type: 'object',
    properties: {
      skillsEnabled: { type: 'array', items: { type: 'string' } },
      instructions: { type: 'string' }
    }
  },
  handler: async (input, ctx) => {
    const skillsEnabled = [];

    // 1. Add a persistent skill for this project type
    const projectSkill = await ctx.majk.skills.add(ctx.conversationId, {
      name: `${input.projectType.toUpperCase()} Code Reviewer`,
      description: `Specialized reviewer for ${input.projectType} projects`,
      instructions: `You are reviewing ${input.projectType} code.
      Focus on ${input.projectType}-specific best practices and patterns.`,
      tags: ['review', input.projectType],
      enabled: false
    });

    // 2. Register a runtime skill with dynamic setup
    await ctx.majk.skills.registerRuntime({
      id: 'project-context-analyzer',
      name: 'Project Context Analyzer',
      description: 'Analyzes project-specific context',
      instructions: 'Analyze code within project context...',
      enabled: true,

      setup: async (context) => {
        // Analyze project structure
        const analysis = await analyzeProjectStructure(input.projectType);
        return `Project analysis complete: ${analysis.summary}`;
      },

      teardown: async (context) => {
        await cleanupAnalysisCache();
      }
    });

    // 3. Enable both skills
    const result1 = await ctx.majk.skills.enable(ctx, {
      skill: projectSkill.id
    });
    skillsEnabled.push(result1.name);

    const result2 = await ctx.majk.skills.enable(ctx, {
      skill: 'project-context-analyzer'
    });
    skillsEnabled.push(result2.name);

    // 4. Subscribe to skill events
    await ctx.majk.skills.on('skill_disabled', async (event) => {
      ctx.logger.info(`Skill disabled: ${event.skillId}`);
      // Cleanup if needed
    });

    return {
      skillsEnabled,
      instructions: `Code review workflow active for ${input.projectType} project.
      ${result1.instructions}

      ${result2.instructions}`
    };
  }
})
```

## Types Reference

### Input Types

```typescript
interface AddSkillInput {
  id?: string;          // Auto-generated if not provided
  name: string;
  description: string;
  instructions: string;
  tags?: string[];
  enabled: boolean;
}

interface UpdateSkillInput {
  id: string;
  name?: string;
  description?: string;
  instructions?: string;
  tags?: string[];
  enabled?: boolean;
}

interface SearchSkillsInput {
  query: string;
  limit?: number;
  includeDisabled?: boolean;
}

interface EnableSkillInput {
  skill: string;        // ID or name
}

interface DisableSkillInput {
  skill: string;        // ID or name
}
```

### Output Types

```typescript
interface ListSkillsResult {
  skills: SkillSummary[];
  total: number;
}

interface SearchSkillsResult {
  matching: SkillSummary[];
  related: SkillSummary[];
  total: number;
}

interface EnableSkillResult {
  id: string;
  name: string;
  instructions: string; // Includes setup additions
}

interface SkillSummary {
  id: string;
  name: string;
  description: string;
  enabled: boolean;
  source: 'database' | 'runtime';
  tags?: string[];
}

interface Skill extends SkillDefinition {
  persisted: boolean;
  hasSetup: boolean;
  hasTeardown: boolean;
  source: 'database' | 'runtime';
}
```

### Context and Functions

```typescript
interface SkillContext {
  teammateId: string;
  conversationId: string;
  projectRoot: string;
}

type SkillSetupFn = (context: SkillContext) => Promise<string | void>;
type SkillTeardownFn = (context: SkillContext) => Promise<void>;

interface RuntimeSkill extends SkillDefinition {
  setup?: SkillSetupFn;
  teardown?: SkillTeardownFn;
}
```

## Best Practices

1. **Use descriptive IDs** - Make skill IDs meaningful and unique
2. **Write clear instructions** - Provide step-by-step guidance
3. **Tag appropriately** - Use consistent tags for discoverability
4. **Handle setup/teardown** - Clean up resources in teardown functions
5. **Subscribe to events** - Monitor skill state changes
6. **Conversation scoping** - Use conversation IDs when appropriate
7. **Error handling** - Skills operations can fail, handle gracefully

## Common Patterns

### Conditional Skills

```typescript
// Enable different skills based on context
const projectType = await detectProjectType();
const skillId = `${projectType}-expert`;
await ctx.majk.skills.enable(ctx, { skill: skillId });
```

### Skill Chains

```typescript
// Enable multiple related skills in sequence
const skills = ['basic-reviewer', 'security-scanner', 'performance-analyzer'];
for (const skillId of skills) {
  await ctx.majk.skills.enable(ctx, { skill: skillId });
}
```

### Dynamic Instructions

```typescript
// Use setup to provide context-aware instructions
setup: async (context) => {
  const codebase = await analyzeCodebase(context.projectRoot);
  return `Codebase uses ${codebase.languages.join(', ')}.
  Primary framework: ${codebase.framework}.
  Focus on ${codebase.framework}-specific patterns.`;
}
```