Implement skill tool for loading specialized instructions

t-245·WorkTask·
·
·
·Omni/Agent/Tools.hs
Created3 months ago·Updated1 month ago

Description

Edit

Add a skill tool that loads specialized instructions from markdown files.

Purpose

Skills are domain-specific instruction sets that jr can load when working on specific types of tasks. For example:

  • Haskell refactoring patterns
  • Python testing conventions
  • Database migration procedures

Data Types

data SkillArgs = SkillArgs
  { skillName :: Text  -- Name of the skill to load
  }
  deriving (Show, Eq, Generic)

Implementation

Step 1: Create Skills Directory

Skills are stored in Omni/Agent/Skills/ as markdown files:

  • Omni/Agent/Skills/haskell-refactoring.md
  • Omni/Agent/Skills/python-testing.md
  • etc.

Step 2: Create the Skill Tool

skillTool :: Engine.Tool
skillTool = Engine.Tool
  { Engine.toolName = "skill",
    Engine.toolDescription = "Load specialized instructions for a domain. Available skills: haskell-refactoring, python-testing, database-migrations.",
    Engine.toolJsonSchema = ...,
    Engine.toolExecute = executeSkill
  }

Step 3: Implement executeSkill

1. Parse the skill name 2. Construct path: Omni/Agent/Skills/<name>.md 3. Check if file exists 4. If yes, read and return the content 5. If no, return error listing available skills

executeSkill :: Aeson.Value -> IO Aeson.Value
executeSkill v = do
  case Aeson.fromJSON v of
    Aeson.Error e -> pure (mkError (Text.pack e))
    Aeson.Success args -> do
      let name = skillName args
          path = "Omni/Agent/Skills/" <> Text.unpack name <> ".md"
      exists <- Directory.doesFileExist path
      if exists
        then do
          content <- TextIO.readFile path
          pure (mkSuccess content)
        else do
          -- List available skills
          files <- Directory.listDirectory "Omni/Agent/Skills/"
          let skills = [Text.pack (dropExtension f) | f <- files, ".md" `isSuffixOf` f]
          pure (mkError ("Skill not found. Available: " <> Text.intercalate ", " skills))

Tool Schema

{
  "type": "object",
  "properties": {
    "name": { 
      "type": "string", 
      "description": "Name of the skill to load (e.g., haskell-refactoring, python-testing)" 
    }
  },
  "required": ["name"]
}

Initial Skills to Create

Create these starter skill files:

Omni/Agent/Skills/haskell-refactoring.md

# Haskell Refactoring Skill

## Safe Refactoring Patterns

1. When splitting modules:
   - Create the new module first with all needed imports
   - Export the symbols from the new module
   - Update the original to re-export from the new module
   - Only after tests pass, remove the re-exports if desired

2. When renaming functions:
   - Use search_codebase to find ALL usages first
   - Update the definition and all call sites atomically
   
3. Common import patterns in this codebase:
   - `import Alpha` provides the custom prelude
   - Use qualified imports for Data.Text, Data.Aeson, etc.

Omni/Agent/Skills/python-testing.md

# Python Testing Skill

## Testing Patterns

1. Tests are inline in the same file, in a `test()` function
2. Use the pattern: `def test() -> int:` returning exit code
3. Run tests with: `bild --test <namespace>`

Testing

1. Create the Skills directory 2. Create at least one skill file 3. Test that skill tool can load it 4. Test error message when skill not found

Notes

  • Skills directory path should be relative to repo root
  • Add skillTool to exports and allTools list
  • Update tool count test

Timeline (2)

🔄[human]Open → InProgress1 month ago
🔄[human]InProgress → Done1 month ago