Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
A comprehensive collection of Agent Skills for context engineering, multi-agent architectures, and production agent systems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
examples/interleaved-thinking/reasoning_trace_optimizer/skill_generator.py
1"""2SkillGenerator: Converts optimization insights into shareable Agent Skills.34Transforms the learnings from optimization loops into reusable skills5following the Agent Skills template format.6"""78import json9import os10from datetime import datetime11from pathlib import Path12from typing import Any1314import anthropic1516from reasoning_trace_optimizer.models import (17AnalysisResult,18LoopResult,19Pattern,20PatternType,21)222324SKILL_TEMPLATE = '''---25name: {skill_name}26description: "{description}"27---2829# {title}3031{intro}3233## When to Activate3435{activation}3637## Core Concepts3839{concepts}4041## Patterns to Avoid4243{anti_patterns}4445## Recommended Practices4647{practices}4849## Guidelines5051{guidelines}5253## Examples5455{examples}5657---5859## Skill Metadata6061**Generated**: {date}62**Source**: Reasoning Trace Optimizer63**Optimization Iterations**: {iterations}64**Score Improvement**: {initial_score:.1f} → {final_score:.1f} (+{improvement:.1f}%)65'''666768GENERATOR_SYSTEM_PROMPT = """You are an expert at converting agent optimization insights into reusable skills.6970Your task is to analyze optimization results and generate a shareable Agent Skill that71captures the learnings so other developers can benefit.7273The skill should:741. Describe WHEN to use these learnings (activation triggers)752. Explain the PATTERNS to avoid (anti-patterns found)763. Provide CONCRETE practices that improved performance774. Give VERIFIABLE guidelines (things that can be checked)785. Include EXAMPLES showing before/after improvements7980Write in a clear, direct style. Focus on actionable guidance, not theory."""818283def _format_list_to_markdown(items: list | str) -> str:84"""Convert a list to markdown bullet points."""85if isinstance(items, str):86return items87if not items:88return ""8990import re91formatted = []92for item in items:93# Strip any existing leading bullet points/dashes to avoid duplication94cleaned = re.sub(r'^[-*•]\s*', '', str(item).strip())95formatted.append(f"- {cleaned}")96return "\n".join(formatted)979899def _format_numbered_list_to_markdown(items: list | str) -> str:100"""Convert a list to markdown numbered list."""101if isinstance(items, str):102return items103if not items:104return ""105106import re107formatted = []108for i, item in enumerate(items):109# Strip any existing leading numbers (e.g., "1. ", "2. ") to avoid duplication110cleaned = re.sub(r'^\d+\.\s*', '', str(item).strip())111formatted.append(f"{i+1}. {cleaned}")112return "\n".join(formatted)113114115def _format_examples_to_markdown(examples: list | str) -> str:116"""Convert example dicts to markdown format."""117if isinstance(examples, str):118return examples119if not examples:120return ""121122parts = []123for i, ex in enumerate(examples):124if isinstance(ex, dict):125parts.append(f"### Example {i+1}: {ex.get('context', 'Scenario')}")126if ex.get('before'):127parts.append(f"\n**Before:**\n```\n{ex['before']}\n```")128if ex.get('after'):129parts.append(f"\n**After:**\n```\n{ex['after']}\n```")130if ex.get('improvement'):131parts.append(f"\n**Improvement:** {ex['improvement']}")132parts.append("")133else:134parts.append(f"- {ex}")135return "\n".join(parts)136137138class SkillGenerator:139"""140Generates shareable Agent Skills from optimization results.141142Converts the learnings from optimization loops into the standard143Agent Skills format for sharing with other developers.144145Example:146```python147generator = SkillGenerator()148skill_path = generator.generate(149result=loop_result,150skill_name="web-search-agent",151output_dir="./generated_skills"152)153print(f"Generated skill at: {skill_path}")154```155"""156157def __init__(158self,159api_key: str | None = None,160base_url: str = "https://api.minimax.io/anthropic",161model: str = "MiniMax-M2.1",162):163"""164Initialize SkillGenerator.165166Args:167api_key: MiniMax API key168base_url: API endpoint169model: Model for skill generation170"""171self.model = model172self.client = anthropic.Anthropic(173api_key=api_key or os.environ.get("ANTHROPIC_API_KEY"),174base_url=base_url,175)176177def generate(178self,179result: LoopResult,180skill_name: str,181output_dir: str = "./generated_skills",182title: str | None = None,183) -> str:184"""185Generate an Agent Skill from optimization results.186187Args:188result: The optimization loop result189skill_name: Name for the skill (lowercase-with-hyphens)190output_dir: Directory to save the skill191title: Optional human-readable title192193Returns:194Path to the generated SKILL.md file195"""196# Extract insights from all iterations197all_patterns = self._collect_patterns(result)198all_recommendations = self._collect_recommendations(result)199key_changes = self._collect_key_changes(result)200201# Generate skill content using M2.1202content = self._generate_skill_content(203task=result.task,204patterns=all_patterns,205recommendations=all_recommendations,206key_changes=key_changes,207initial_prompt=result.iterations[0].trace.system_prompt if result.iterations else "",208final_prompt=result.final_prompt,209)210211# Format content - convert lists to markdown212formatted_content = {213"activation": _format_list_to_markdown(content.get("activation", "")),214"concepts": _format_list_to_markdown(content.get("concepts", "")),215"anti_patterns": _format_list_to_markdown(content.get("anti_patterns", "")),216"practices": _format_list_to_markdown(content.get("practices", "")),217"guidelines": _format_numbered_list_to_markdown(content.get("guidelines", "")),218"examples": _format_examples_to_markdown(content.get("examples", "")),219}220221# Format using template222skill_content = SKILL_TEMPLATE.format(223skill_name=skill_name,224description=content.get("description", f"Optimized practices for {skill_name}"),225title=title or content.get("title", skill_name.replace("-", " ").title()),226intro=content.get("intro", ""),227activation=formatted_content["activation"],228concepts=formatted_content["concepts"],229anti_patterns=formatted_content["anti_patterns"],230practices=formatted_content["practices"],231guidelines=formatted_content["guidelines"],232examples=formatted_content["examples"],233date=datetime.now().strftime("%Y-%m-%d"),234iterations=result.total_iterations,235initial_score=result.initial_score,236final_score=result.final_score,237improvement=result.improvement_percentage,238)239240# Save skill241skill_dir = Path(output_dir) / skill_name242skill_dir.mkdir(parents=True, exist_ok=True)243244skill_path = skill_dir / "SKILL.md"245with open(skill_path, "w") as f:246f.write(skill_content)247248# Save optimization data as reference249self._save_references(skill_dir, result, content)250251return str(skill_path)252253def generate_from_analysis(254self,255analyses: list[AnalysisResult],256skill_name: str,257task_description: str,258output_dir: str = "./generated_skills",259) -> str:260"""261Generate a skill from multiple analysis results (without full loop).262263Useful when you have analysis data but didn't run the full optimization loop.264265Args:266analyses: List of analysis results267skill_name: Name for the skill268task_description: Description of the task context269output_dir: Output directory270271Returns:272Path to generated skill273"""274# Aggregate patterns and recommendations275all_patterns = []276all_recommendations = []277278for analysis in analyses:279all_patterns.extend(analysis.patterns)280all_recommendations.extend(analysis.recommendations)281282content = self._generate_skill_content(283task=task_description,284patterns=all_patterns,285recommendations=list(set(all_recommendations)),286key_changes=[],287initial_prompt="",288final_prompt="",289)290291# Calculate average score292avg_score = sum(a.overall_score for a in analyses) / len(analyses) if analyses else 0293294skill_content = SKILL_TEMPLATE.format(295skill_name=skill_name,296description=content.get("description", f"Learnings for {skill_name}"),297title=content.get("title", skill_name.replace("-", " ").title()),298intro=content.get("intro", ""),299activation=content.get("activation", ""),300concepts=content.get("concepts", ""),301anti_patterns=content.get("anti_patterns", ""),302practices=content.get("practices", ""),303guidelines=content.get("guidelines", ""),304examples=content.get("examples", ""),305date=datetime.now().strftime("%Y-%m-%d"),306iterations=len(analyses),307initial_score=avg_score,308final_score=avg_score,309improvement=0,310)311312skill_dir = Path(output_dir) / skill_name313skill_dir.mkdir(parents=True, exist_ok=True)314315skill_path = skill_dir / "SKILL.md"316with open(skill_path, "w") as f:317f.write(skill_content)318319return str(skill_path)320321def _collect_patterns(self, result: LoopResult) -> list[Pattern]:322"""Collect all unique patterns from iterations."""323patterns = []324seen = set()325326for iteration in result.iterations:327for pattern in iteration.analysis.patterns:328key = (pattern.type, pattern.description[:50])329if key not in seen:330patterns.append(pattern)331seen.add(key)332333return patterns334335def _collect_recommendations(self, result: LoopResult) -> list[str]:336"""Collect all unique recommendations."""337recommendations = []338seen = set()339340for iteration in result.iterations:341for rec in iteration.analysis.recommendations:342if rec not in seen:343recommendations.append(rec)344seen.add(rec)345346return recommendations347348def _collect_key_changes(self, result: LoopResult) -> list[str]:349"""Collect all key changes from optimizations."""350changes = []351352for iteration in result.iterations:353if iteration.optimization:354changes.extend(iteration.optimization.key_changes)355356return changes357358def _generate_skill_content(359self,360task: str,361patterns: list[Pattern],362recommendations: list[str],363key_changes: list[str],364initial_prompt: str,365final_prompt: str,366) -> dict[str, str]:367"""Use M2.1 to generate skill content sections."""368patterns_text = "\n".join(369f"- [{p.severity.value}] {p.type.value}: {p.description}"370for p in patterns371)372373recommendations_text = "\n".join(f"- {r}" for r in recommendations)374changes_text = "\n".join(f"- {c}" for c in key_changes)375376prompt = f"""Generate an Agent Skill based on these optimization insights:377378## Task Context379{task}380381## Patterns Detected (Anti-patterns to avoid)382{patterns_text or "No significant patterns detected"}383384## Recommendations from Analysis385{recommendations_text or "No specific recommendations"}386387## Key Changes That Improved Performance388{changes_text or "No recorded changes"}389390## Prompt Evolution391Initial: {initial_prompt[:500] if initial_prompt else "N/A"}...392Final: {final_prompt[:500] if final_prompt else "N/A"}...393394---395396Generate skill content as JSON:397```json398{{399"title": "Human-readable skill title",400"description": "One-line description for skill discovery (what triggers this skill)",401"intro": "2-3 sentence introduction explaining what this skill teaches",402"activation": "Bullet points of when to activate this skill (specific keywords, task types)",403"concepts": "Core concepts this skill covers (3-5 key ideas)",404"anti_patterns": "Patterns to AVOID - formatted as markdown list with descriptions",405"practices": "Recommended practices - formatted as markdown list",406"guidelines": "Numbered verifiable guidelines (things that can be checked)",407"examples": "1-2 concrete before/after examples showing improvement"408}}409```"""410411response = self.client.messages.create(412model=self.model,413max_tokens=4096,414system=GENERATOR_SYSTEM_PROMPT,415messages=[{"role": "user", "content": prompt}],416)417418# Parse response419for block in response.content:420if block.type == "text":421try:422text = block.text423if "```json" in text:424text = text.split("```json")[1].split("```")[0]425return json.loads(text)426except json.JSONDecodeError:427pass428429# Return defaults if parsing fails430return {431"title": "Generated Agent Skill",432"description": f"Optimized practices for {task}",433"intro": "This skill contains learnings from automated prompt optimization.",434"activation": "- When working on similar tasks\n- When debugging agent failures",435"concepts": "See recommendations section.",436"anti_patterns": patterns_text or "No patterns identified.",437"practices": recommendations_text or "No specific practices.",438"guidelines": "1. Review the anti-patterns before implementation\n2. Apply recommended practices",439"examples": "See optimization artifacts for detailed examples.",440}441442def _save_references(443self,444skill_dir: Path,445result: LoopResult,446content: dict[str, str],447) -> None:448"""Save reference materials alongside the skill."""449refs_dir = skill_dir / "references"450refs_dir.mkdir(exist_ok=True)451452# Save optimization summary453summary = {454"task": result.task,455"iterations": result.total_iterations,456"initial_score": result.initial_score,457"final_score": result.final_score,458"improvement": result.improvement_percentage,459"converged": result.converged,460"generated_at": datetime.now().isoformat(),461}462with open(refs_dir / "optimization_summary.json", "w") as f:463json.dump(summary, f, indent=2)464465# Save final optimized prompt466with open(refs_dir / "optimized_prompt.txt", "w") as f:467f.write(result.final_prompt)468469# Save all patterns found470patterns_data = []471for iteration in result.iterations:472for p in iteration.analysis.patterns:473patterns_data.append({474"type": p.type.value,475"severity": p.severity.value,476"description": p.description,477"suggestion": p.suggestion,478"iteration": iteration.iteration,479})480481with open(refs_dir / "patterns_found.json", "w") as f:482json.dump(patterns_data, f, indent=2)483484485def generate_skill_from_loop(486result: LoopResult,487skill_name: str,488output_dir: str = "./generated_skills",489) -> str:490"""491Quick helper to generate a skill from optimization results.492493Args:494result: Optimization loop result495skill_name: Name for the skill496output_dir: Output directory497498Returns:499Path to generated skill500"""501generator = SkillGenerator()502return generator.generate(result, skill_name, output_dir)503