Skip to main content

Overview

Stoneforge provides three built-in agent roles (Director, Worker, Steward), but you can customize them with role definitions and prompt overrides to create specialized agents tailored to your team’s workflow.

Role Definitions vs. Prompt Overrides

Role Definitions

Stored configurations that define agent specializations with custom behaviors and metadata

Prompt Overrides

Project-level prompt files in .stoneforge/prompts/ that replace built-in agent instructions
When to use each:
  • Role Definitions: Create specialized agent types (e.g., “Frontend Worker”, “Security Reviewer”)
  • Prompt Overrides: Customize instructions for all agents of a role (e.g., add project-specific coding standards)

Creating Role Definitions

Define a Specialized Worker

Role definitions let you create worker variants with specific skills and behaviors:
import { createRoleDefinitionService } from '@stoneforge/smithy';
import type { QuarryAPI } from '@stoneforge/quarry';

const roleDefService = createRoleDefinitionService(api);

// Frontend specialist
const frontendWorker = await roleDefService.createRoleDefinition({
  role: 'worker',
  name: 'Frontend Developer',
  systemPrompt: `You specialize in React, TypeScript, and modern web development.

## Technology Stack
- React 18 with hooks
- TypeScript with strict mode
- TanStack Query for data fetching
- Tailwind CSS for styling
- Vitest for testing

## Coding Standards
- Use functional components only
- Prefer named exports over default
- Write unit tests for all components
- Follow accessibility best practices (WCAG 2.1 AA)
`,
  workerMode: 'ephemeral',
  createdBy: directorId,
  tags: ['frontend', 'react', 'typescript'],
  behaviors: {
    onStartup: 'Review the component library documentation before starting',
    onTaskAssigned: 'Check for existing similar components to reuse patterns',
    onStuck: 'Review the design system docs, then ask for help after 30 min',
    onError: 'Check browser console, network tab, and React DevTools',
  },
});

// Backend specialist  
const backendWorker = await roleDefService.createRoleDefinitionForAgent({
  role: 'worker',
  name: 'Backend Developer',
  systemPrompt: `You specialize in Node.js, databases, and API development.

## Technology Stack
- Node.js with TypeScript
- PostgreSQL with Drizzle ORM
- tRPC for type-safe APIs
- Zod for validation

## Best Practices
- Use transactions for multi-step database operations
- Validate all inputs with Zod schemas
- Write integration tests for all endpoints
- Document API endpoints with JSDoc
`,
  workerMode: 'ephemeral',
  createdBy: directorId,
  tags: ['backend', 'api', 'database'],
  behaviors: {
    onStartup: 'Check database migration status',
    onTaskAssigned: 'Review API schema and database models',
    onStuck: 'Check logs, query explain plans, then escalate after 30 min',
    onError: 'Capture full stack trace and database error codes',
  },
});

Register Agents with Role Definitions

Once you’ve created role definitions, register agents that reference them:
import { createOrchestratorAPI } from '@stoneforge/smithy';

const api = createOrchestratorAPI(storage);

// Frontend worker using the frontend role definition
const feWorker = await api.registerWorker({
  name: 'fe-worker-1',
  workerMode: 'ephemeral',
  createdBy: directorId,
  roleDefinitionRef: frontendWorker.id,
});

// Backend worker using the backend role definition
const beWorker = await api.registerWorker({
  name: 'be-worker-1', 
  workerMode: 'ephemeral',
  createdBy: directorId,
  roleDefinitionRef: backendWorker.id,
});

Project-Level Prompt Overrides

Creating Override Files

Prompt overrides replace the built-in agent prompts for all agents of that role in your project:
1

Create the prompts directory

mkdir -p .stoneforge/prompts
2

Copy the built-in prompt

# Copy worker prompt as a starting point
cp packages/smithy/src/prompts/worker.md .stoneforge/prompts/worker.md
3

Customize the prompt

Edit .stoneforge/prompts/worker.md to add project-specific instructions.

Override Structure

my-project/
├── .stoneforge/
│   └── prompts/
│       ├── worker.md              # Override ephemeral workers
│       ├── persistent-worker.md   # Override persistent workers
│       ├── director.md            # Override directors
│       ├── steward-base.md        # Override all stewards (base)
│       └── steward-merge.md       # Override merge steward addendum
└── src/
Override files apply to all agents of that role. Use role definitions if you need different prompts for different agent instances.

Example: Adding Security Focus

.stoneforge/prompts/worker.md
# Your Role: Worker

You are a worker agent in the Stoneforge orchestration system.

## Security-First Development

This project handles sensitive user data. Security is your top priority.

### Before Any Code Change

1. **Input Validation** - Never trust user input
   - Use Zod schemas for all API inputs
   - Sanitize data before storage or display
   - Validate file uploads (type, size, content)

2. **Authentication & Authorization**
   - Verify auth on every protected endpoint
   - Use principle of least privilege
   - Never expose user IDs in URLs

3. **Data Protection**
   - Never log sensitive data (passwords, tokens, PII)
   - Use parameterized queries (never string concat)
   - Encrypt sensitive fields at rest

### Security Red Flags

If you encounter ANY of these, report immediately to the security channel:
- Hardcoded credentials or API keys
- SQL injection vulnerabilities 
- XSS attack vectors
- Missing authentication checks
- Insecure direct object references
- Sensitive data in logs or error messages

## Your Responsibilities

- Execute tasks assigned to you
- Report progress and blockers
...

Custom Steward Types

Built-in Steward Focuses

Automatically dispatched when tasks enter REVIEW status. Handles conflict resolution, test verification, and merge execution.
Scans for outdated documentation, broken links, and missing API docs. Auto-merges documentation fixes.
Detects stuck tasks, orphaned processes, and stale worktrees. Creates recovery tasks when issues are found.
Executes custom maintenance workflows. Reference a Workflow Template (Playbook) for instructions.

Creating a Custom Steward

Custom stewards execute specialized maintenance workflows using playbooks:
import { createPlaybook } from '@stoneforge/core';

// 1. Create a playbook (workflow template)
const cleanupPlaybook = await createPlaybook({
  title: 'Stale Branch Cleanup',
  content: `## Stale Branch Cleanup

### Objective
Remove branches for closed tasks older than 30 days.

### Steps

1. **Find Stale Branches**
   \`\`\`bash
   git for-each-ref --format='%(refname:short) %(authordate:iso8601)' \
     refs/heads/agent/ | awk '$2 < "'$(date -d '30 days ago' +%Y-%m-%d)'" {print $1}'
   \`\`\`

2. **Verify Task Status**
   For each branch, check if the task is closed:
   \`\`\`bash
   sf show <task-id> --json | jq -r '.status'
   \`\`\`

3. **Delete Stale Branches**
   Only delete if task status is 'closed':
   \`\`\`bash
   git branch -D <branch-name>
   git push origin --delete <branch-name>
   \`\`\`

4. **Log Results**
   Create a summary document with deleted branches and send to the operations channel.
`,
  createdBy: operatorId,
  tags: ['maintenance', 'cleanup'],
});

const savedPlaybook = await api.create(cleanupPlaybook);

// 2. Register steward with playbook reference
const cleanupSteward = await api.registerSteward({
  name: 'cleanup-steward',
  stewardFocus: 'custom',
  playbookId: savedPlaybook.id,
  triggers: [
    { type: 'cron', schedule: '0 2 * * 0' }, // Weekly on Sunday at 2am
  ],
  createdBy: directorId,
});
Playbooks can include bash commands, CLI workflows, or decision trees. The steward executes the playbook instructions when triggered.

Scheduling Custom Stewards

Stewards support two trigger types:
// Trigger on specific events
const steward = await api.registerSteward({
  name: 'post-merge-steward',
  stewardFocus: 'custom',
  playbookId: postMergePlaybookId,
  triggers: [
    { type: 'event', event: 'task_completed' },
  ],
  createdBy: directorId,
});

Behavior Hooks

Define agent behaviors for specific lifecycle events:
const roleDef = await roleDefService.createRoleDefinition({
  role: 'worker',
  name: 'Testing-Focused Worker',
  systemPrompt: 'You prioritize test-driven development...',
  workerMode: 'ephemeral',
  createdBy: directorId,
  behaviors: {
    // Runs when agent session starts
    onStartup: `
      1. Check git status and pull latest changes
      2. Run tests to verify clean baseline: npm test
      3. Review the Documentation Directory: sf docs dir --content
    `,
    
    // Runs when task is assigned
    onTaskAssigned: `
      1. Read the full task description and acceptance criteria
      2. Search for related documentation: sf document search <topic>
      3. Check for similar existing implementations
    `,
    
    // Guidance when stuck
    onStuck: `
      1. Review error messages and stack traces carefully
      2. Search documentation for the error/concept
      3. Try breaking the task into smaller steps
      4. If stuck for >30 min, handoff with context: sf task handoff <task-id> --message "..."
    `,
    
    // Error handling procedure
    onError: `
      1. Capture the full error output and context
      2. Check logs for additional information
      3. Verify the error is reproducible
      4. Report with full details to the Director
    `,
  },
});

Loading Custom Prompts in Code

The prompt system automatically checks for project overrides:
import { loadRolePrompt, buildAgentPrompt } from '@stoneforge/smithy';

// Load prompt (checks .stoneforge/prompts/ first, falls back to built-in)
const result = loadRolePrompt('worker', undefined, {
  projectRoot: process.cwd(),
});

if (result) {
  console.log('Prompt loaded from:', result.source);
  // source is either 'built-in' or the override file path
  console.log('Prompt content:', result.prompt);
}

// For stewards, load base + focus
const stewardPrompt = loadRolePrompt('steward', 'merge', {
  projectRoot: process.cwd(),
});

if (stewardPrompt) {
  console.log('Base prompt from:', stewardPrompt.baseSource);
  console.log('Focus addendum from:', stewardPrompt.focusSource);
}

// Build complete prompt with task context
const fullPrompt = buildAgentPrompt({
  role: 'worker',
  taskContext: 'Implement OAuth login for the user authentication system.',
  additionalInstructions: 'Use NextAuth.js and follow security best practices.',
  projectRoot: process.cwd(),
});

Best Practices

Keep Prompts Concise

Built-in prompts are additive to Claude’s system prompt. Focus on role-specific responsibilities and project conventions, not general coding advice.

Use Behaviors for Context

Instead of bloating the main prompt, use behavior hooks for event-specific instructions.

Test with Real Agents

After customizing prompts, spawn an agent and observe behavior on real tasks. Iterate based on performance.

Version Control Prompts

Store prompt overrides in git so the team shares the same agent instructions.

Troubleshooting

  1. Check file path: .stoneforge/prompts/{role}.md
  2. Verify file name matches exactly (case-sensitive)
  3. Ensure projectRoot is set correctly when loading
  4. Check file permissions (must be readable)
For stewards, both base and focus prompts are loaded separately:
const result = loadRolePrompt('steward', 'merge', { projectRoot });

// Check what loaded:
console.log('Base:', result?.baseSource);
console.log('Focus:', result?.focusSource);
You can override just the base, just the focus, or both independently.
If the combined prompt exceeds token limits:
  1. Move task-specific details to task context instead of prompt
  2. Use behaviors for event-specific instructions
  3. Link to external documentation rather than embedding it
  4. Focus on principles and decision-making, not detailed procedures

Agent Roles

Understand the Director, Worker, and Steward roles

Playbooks

Create workflow templates for custom stewards

Scaling Agents

Run multiple agents across Claude plans

Build docs developers (and LLMs) love