# Subagents

Specialized agents with dedicated knowledge bases and system prompts.

## What are Subagents?

Subagents are focused AI agents designed for specific tasks. Unlike general-purpose agents, each subagent has:

- **Specialized knowledge**: Multi-file memory directory with domain-specific info
- **Custom system prompt**: Tailored instructions for the task
- **Model override**: Can use different models than the main agent
- **Capability tags**: Declare what they can do

## Directory Structure

```
subagents/
├── base-subagent.ts         # Base class
├── {subagent-name}/
│   ├── config.yaml          # Configuration
│   ├── system-prompt.md     # System instructions
│   ├── memory/              # Knowledge base (multi-file)
│   │   ├── file1.md
│   │   ├── file2.md
│   │   └── file3.md
│   └── index.ts             # Implementation
└── README.md                # This file
```

## Creating a New Subagent

### 1. Create Directory Structure

```bash
mkdir -p subagents/my-subagent/memory
```

### 2. Create config.yaml

```yaml
name: my-subagent
description: What it does

# Model override (optional)
model: claude-sonnet-4-6
temperature: 0.3
maxTokens: 4096

# Memory files to load
memoryFiles:
  - guidelines.md
  - examples.md
  - best-practices.md

# System prompt file
systemPromptFile: system-prompt.md

# Capabilities
capabilities:
  - capability1
  - capability2
```

### 3. Write system-prompt.md

```markdown
# My Subagent System Prompt

You are an expert in [domain].

## Your Role
[What the subagent does]

## Approach
1. [Step 1]
2. [Step 2]

## Output Format
[How to structure responses]
```

### 4. Create Memory Files

Split knowledge into logical files:

```markdown
<!-- memory/guidelines.md -->
# Guidelines

## What to Check
- Thing 1
- Thing 2

## What to Avoid
- Anti-pattern 1
- Anti-pattern 2
```

### 5. Implement Subagent

```typescript
// index.ts
import { BaseSubagent, SubagentConfig, SubagentContext } from '../base-subagent.js';
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
import { FastifyBaseLogger } from 'fastify';

export class MySubagent extends BaseSubagent {
  constructor(config: SubagentConfig, model: BaseChatModel, logger: FastifyBaseLogger) {
    super(config, model, logger);
  }

  async execute(context: SubagentContext, input: string): Promise<string> {
    this.logger.info({ subagent: this.getName() }, 'Executing subagent');

    const messages = this.buildMessages(context, input);
    const response = await this.model.invoke(messages);

    return response.content as string;
  }
}

// Factory function
export async function createMySubagent(
  model: BaseChatModel,
  logger: FastifyBaseLogger,
  basePath: string
): Promise<MySubagent> {
  const { readFile } = await import('fs/promises');
  const { join } = await import('path');
  const yaml = await import('js-yaml');

  const configPath = join(basePath, 'config.yaml');
  const configContent = await readFile(configPath, 'utf-8');
  const config = yaml.load(configContent) as SubagentConfig;

  const subagent = new MySubagent(config, model, logger);
  await subagent.initialize(basePath);

  return subagent;
}
```

### 6. Export from index.ts

```typescript
// subagents/index.ts
export { MySubagent, createMySubagent } from './my-subagent/index.js';
```

## Using Subagents

### Direct Usage

```typescript
import { createMySubagent } from './harness/subagents';

const subagent = await createMySubagent(model, logger, basePath);
const result = await subagent.execute({ userContext }, 'input text');
```

### In Workflows

```typescript
const analyzeNode = async (state) => {
  const result = await mySubagent.execute(
    { userContext: state.userContext },
    state.input
  );

  return { analysis: result };
};
```

### With Routing

Add to `config/subagent-routing.yaml`:

```yaml
subagents:
  my-subagent:
    enabled: true
    path: src/harness/subagents/my-subagent
    triggers:
      keywords:
        - "keyword1"
        - "keyword2"
      patterns:
        - "pattern.*regex"
    priority: medium
    timeout: 30000
```

## Multi-File Memory Benefits

### Why Split Memory?

1. **Organization**: Easier to maintain separate concerns
2. **Versioning**: Update specific files without touching others
3. **Collaboration**: Multiple people can work on different files
4. **Context Management**: LLM sees structured knowledge

### Example Split

For a code reviewer:
- `review-guidelines.md`: What to check
- `common-patterns.md`: Good/bad examples
- `best-practices.md`: Industry standards

All files are loaded and concatenated at initialization.

## Best Practices

### Memory Files

- **Be Specific**: Include concrete examples, not just theory
- **Use Markdown**: Tables, lists, code blocks for clarity
- **Keep Focused**: Each file should have a clear purpose
- **Update Regularly**: Improve based on real usage

### System Prompts

- **Define Role Clearly**: "You are a [specific role]"
- **Specify Output Format**: Show examples of expected output
- **Set Constraints**: What to do, what not to do
- **Give Context**: Why this subagent exists

### Configuration

- **Model Selection**: Use faster models for simple tasks
- **Temperature**: Lower (0.2-0.3) for precise work, higher (0.7-0.9) for creative
- **Capabilities**: Tag accurately for routing

## Available Subagents

### code-reviewer
Reviews trading strategy code for bugs, performance, and best practices.

**Capabilities:**
- `static_analysis`
- `performance_review`
- `security_audit`
- `code_quality`

**Memory:**
- Review guidelines
- Common patterns
- Best practices

### risk-analyzer (TODO)
Analyzes trading risk and exposure.

### market-analyst (TODO)
Provides market analysis and insights.

## Troubleshooting

### Memory Files Not Loading

- Check file paths in config.yaml
- Ensure files exist in memory/ directory
- Check file permissions

### Subagent Not Being Routed

- Verify triggers in subagent-routing.yaml
- Check priority (higher priority matches first)
- Ensure enabled: true

### Model Errors

- Verify API keys in environment
- Check model override is valid
- Ensure token limits not exceeded
