#!/bin/bash # Agent File Validator # Validates agent markdown files for correct structure and content set -euo pipefail # Usage if [ $# -eq 0 ]; then echo "Usage: $0 " echo "" echo "Validates agent file for:" echo " - YAML frontmatter structure" echo " - Required fields (name, description, model, color)" echo " - Field formats and constraints" echo " - System prompt presence and length" echo " - Example blocks in description" exit 1 fi AGENT_FILE="$1" echo "🔍 Validating agent file: $AGENT_FILE" echo "" # Check 1: File exists if [ ! -f "$AGENT_FILE" ]; then echo "❌ File not found: $AGENT_FILE" exit 1 fi echo "✅ File exists" # Check 2: Starts with --- FIRST_LINE=$(head -1 "$AGENT_FILE") if [ "$FIRST_LINE" != "---" ]; then echo "❌ File must start with YAML frontmatter (---)" exit 1 fi echo "✅ Starts with frontmatter" # Check 3: Has closing --- if ! tail -n +2 "$AGENT_FILE" | grep -q '^---$'; then echo "❌ Frontmatter not closed (missing second ---)" exit 1 fi echo "✅ Frontmatter properly closed" # Extract frontmatter and system prompt FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$AGENT_FILE") SYSTEM_PROMPT=$(awk '/^---$/{i++; next} i>=2' "$AGENT_FILE") # Check 4: Required fields echo "" echo "Checking required fields..." error_count=0 warning_count=0 # Check name field NAME=$(echo "$FRONTMATTER" | grep '^name:' | sed 's/name: *//' | sed 's/^"\(.*\)"$/\1/') if [ -z "$NAME" ]; then echo "❌ Missing required field: name" ((error_count++)) else echo "✅ name: $NAME" # Validate name format if ! [[ "$NAME" =~ ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$ ]]; then echo "❌ name must start/end with alphanumeric and contain only letters, numbers, hyphens" ((error_count++)) fi # Validate name length name_length=${#NAME} if [ $name_length -lt 3 ]; then echo "❌ name too short (minimum 3 characters)" ((error_count++)) elif [ $name_length -gt 50 ]; then echo "❌ name too long (maximum 50 characters)" ((error_count++)) fi # Check for generic names if [[ "$NAME" =~ ^(helper|assistant|agent|tool)$ ]]; then echo "⚠️ name is too generic: $NAME" ((warning_count++)) fi fi # Check description field DESCRIPTION=$(echo "$FRONTMATTER" | grep '^description:' | sed 's/description: *//') if [ -z "$DESCRIPTION" ]; then echo "❌ Missing required field: description" ((error_count++)) else desc_length=${#DESCRIPTION} echo "✅ description: ${desc_length} characters" if [ $desc_length -lt 10 ]; then echo "⚠️ description too short (minimum 10 characters recommended)" ((warning_count++)) elif [ $desc_length -gt 5000 ]; then echo "⚠️ description very long (over 5000 characters)" ((warning_count++)) fi # Check for example blocks if ! echo "$DESCRIPTION" | grep -q ''; then echo "⚠️ description should include blocks for triggering" ((warning_count++)) fi # Check for "Use this agent when" pattern if ! echo "$DESCRIPTION" | grep -qi 'use this agent when'; then echo "⚠️ description should start with 'Use this agent when...'" ((warning_count++)) fi fi # Check model field MODEL=$(echo "$FRONTMATTER" | grep '^model:' | sed 's/model: *//') if [ -z "$MODEL" ]; then echo "❌ Missing required field: model" ((error_count++)) else echo "✅ model: $MODEL" case "$MODEL" in inherit|sonnet|opus|haiku) # Valid model ;; *) echo "⚠️ Unknown model: $MODEL (valid: inherit, sonnet, opus, haiku)" ((warning_count++)) ;; esac fi # Check color field COLOR=$(echo "$FRONTMATTER" | grep '^color:' | sed 's/color: *//') if [ -z "$COLOR" ]; then echo "❌ Missing required field: color" ((error_count++)) else echo "✅ color: $COLOR" case "$COLOR" in blue|cyan|green|yellow|magenta|red) # Valid color ;; *) echo "⚠️ Unknown color: $COLOR (valid: blue, cyan, green, yellow, magenta, red)" ((warning_count++)) ;; esac fi # Check tools field (optional) TOOLS=$(echo "$FRONTMATTER" | grep '^tools:' | sed 's/tools: *//') if [ -n "$TOOLS" ]; then echo "✅ tools: $TOOLS" else echo "💡 tools: not specified (agent has access to all tools)" fi # Check 5: System prompt echo "" echo "Checking system prompt..." if [ -z "$SYSTEM_PROMPT" ]; then echo "❌ System prompt is empty" ((error_count++)) else prompt_length=${#SYSTEM_PROMPT} echo "✅ System prompt: $prompt_length characters" if [ $prompt_length -lt 20 ]; then echo "❌ System prompt too short (minimum 20 characters)" ((error_count++)) elif [ $prompt_length -gt 10000 ]; then echo "⚠️ System prompt very long (over 10,000 characters)" ((warning_count++)) fi # Check for second person if ! echo "$SYSTEM_PROMPT" | grep -q "You are\|You will\|Your"; then echo "⚠️ System prompt should use second person (You are..., You will...)" ((warning_count++)) fi # Check for structure if ! echo "$SYSTEM_PROMPT" | grep -qi "responsibilities\|process\|steps"; then echo "💡 Consider adding clear responsibilities or process steps" fi if ! echo "$SYSTEM_PROMPT" | grep -qi "output"; then echo "💡 Consider defining output format expectations" fi fi echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" if [ $error_count -eq 0 ] && [ $warning_count -eq 0 ]; then echo "✅ All checks passed!" exit 0 elif [ $error_count -eq 0 ]; then echo "⚠️ Validation passed with $warning_count warning(s)" exit 0 else echo "❌ Validation failed with $error_count error(s) and $warning_count warning(s)" exit 1 fi