Skill Registration and Execution Mechanism
Chapter 17: Skill Registration and Execution Mechanics
Within the Hermes Agent tool ecosystem, a Skill is a higher-level abstraction than a single tool call. A Skill encapsulates a complete piece of business logic — it carries its own metadata description, parameter constraints, execution steps, and fallback strategies for failure. Understanding the Skill lifecycle is the foundational prerequisite for building maintainable, extensible Agent systems.
17.1 What Is a Skill?
A Skill is Hermes Agent's formal abstraction for a "reusable capability unit." Unlike direct tool calls, Skills have distinct characteristics:
| Dimension | Tool | Skill |
|---|---|---|
| Granularity | Single atomic operation (e.g., web_search) | Multi-step composite logic |
| Description | Function signature + docstring | SKILL.md file |
| Discoverability | Runtime enumeration | Semantic retrieval index |
| State management | Stateless | Can carry execution context |
| Error handling | Raise exception | Built-in fallback strategies |
| Reuse mechanism | Code import | Metadata-driven |
The core value of a Skill lies in declarative description: you tell the Agent "what this skill can do and how to invoke it," rather than "how to implement it step by step." The Agent decides autonomously when and how to compose these Skills during reasoning.
17.2 The Skill Lifecycle: From Registration to Feedback
Hermes structures the Skill lifecycle into five phases, forming a complete closed loop:
Register
↓
Index
↓
Retrieve
↓
Execute
↓
Feedback
↓ (updates index weights)
Register (next iteration)
17.2.1 Phase 1: Register
Registration is the entry point for introducing a Skill into the system. Each Skill exists as a directory that must contain a SKILL.md file as the primary descriptor.
# Skill directory structure
skills/
├── web_research/
│ ├── SKILL.md # Required: skill descriptor
│ ├── skill.py # Optional: Python entry point
│ ├── examples/ # Optional: invocation examples
│ │ ├── example1.json
│ │ └── example2.json
│ └── tests/
│ └── test_web_research.py
├── code_review/
│ ├── SKILL.md
│ └── skill.py
└── data_analysis/
├── SKILL.md
└── skill.py
Registration is triggered via the Hermes CLI:
# Register a single Skill
hermes skill register ./skills/web_research
# Batch-register all Skills in a directory
hermes skill register ./skills/ --recursive
# Register and immediately validate
hermes skill register ./skills/web_research --validate
# List all registered Skills
hermes skill list
During registration, the system:
- Parses the
SKILL.mdfile, extracting metadata - Validates completeness of required fields
- Checks that dependency tools are available
- Assigns a unique Skill ID
17.2.2 Phase 2: Index
After registration, the Skill's description text is vectorized and written into a semantic retrieval index. Hermes uses a local embedding model (e.g., nomic-embed-text) to generate vectors:
# Hermes internal indexing logic (simplified)
from hermes.skills import SkillRegistry
from hermes.embeddings import LocalEmbedder
registry = SkillRegistry()
embedder = LocalEmbedder(model="nomic-embed-text")
def index_skill(skill_path: str):
skill = registry.load(skill_path)
# Build index text from name + description + examples
index_text = f"""
Skill Name: {skill.name}
Description: {skill.description}
Use Cases: {skill.use_cases}
Example Queries: {' | '.join(skill.example_queries)}
"""
vector = embedder.encode(index_text)
registry.vector_db.upsert(
id=skill.id,
vector=vector,
metadata={
"name": skill.name,
"version": skill.version,
"tags": skill.tags,
"priority": skill.priority,
}
)
return skill.id
17.2.3 Phase 3: Retrieve
When the Agent receives a user task, it performs a vector search on the task description to find the most relevant Skill candidates:
def retrieve_skills(query: str, top_k: int = 5) -> list[Skill]:
query_vector = embedder.encode(query)
results = registry.vector_db.search(
vector=query_vector,
top_k=top_k,
filter={"tags": {"$in": ["active", "stable"]}},
)
skills = []
for result in results:
skill = registry.get(result.id)
skill.relevance_score = result.score
skills.append(skill)
return skills
# Example retrieval during Agent reasoning
relevant_skills = retrieve_skills(
query="Analyze the code quality of this Python file",
top_k=3,
)
# Returns: [code_review (0.94), static_analysis (0.87), test_generation (0.71)]
17.2.4 Phase 4: Execute
Once the Agent selects a Skill, execution follows a strict pipeline: parameter binding → pre-check → run → post-processing:
class SkillExecutor:
def execute(self, skill: Skill, params: dict, context: AgentContext) -> SkillResult:
# 1. Parameter binding and validation
bound_params = self._bind_params(skill.schema, params, context)
# 2. Pre-flight checks (permissions, resources, dependencies)
self._pre_check(skill, bound_params, context)
# 3. Execute core logic
try:
result = skill.run(bound_params, context)
except SkillTimeoutError:
result = self._handle_timeout(skill, context)
except SkillPermissionError as e:
result = self._handle_permission(e, context)
except Exception as e:
result = self._handle_generic_error(skill, e, context)
# 4. Post-processing (format output, record logs)
return self._post_process(skill, result, context)
def _bind_params(self, schema: dict, params: dict, context: AgentContext) -> dict:
bound = {}
for field_name, field_schema in schema["properties"].items():
if field_name in params:
bound[field_name] = params[field_name]
elif field_name in context.variables:
bound[field_name] = context.variables[field_name]
elif "default" in field_schema:
bound[field_name] = field_schema["default"]
elif field_name in schema.get("required", []):
raise MissingParameterError(f"Required parameter missing: {field_name}")
return bound
17.2.5 Phase 5: Feedback
Execution results are scored and fed back to the index system, influencing retrieval ranking weights:
class SkillFeedback:
def record(
self,
skill_id: str,
query: str,
result: SkillResult,
user_rating: int | None = None,
):
score = self._compute_score(result, user_rating)
self.registry.update_stats(skill_id, {
"execution_count": +1,
"success_count": +1 if result.success else 0,
"avg_latency_ms": result.latency_ms,
"avg_score": score,
})
# Skills with higher usage and success rates get a small retrieval boost
self.registry.update_priority(skill_id, score)
17.3 SKILL.md File Format Specification
SKILL.md serves as the Skill's "identity card," using a Markdown format with YAML Front Matter:
---
name: web_research
version: "1.2.0"
description: "Conducts deep research on a specified topic via multi-engine web search
and content extraction, returning a structured research report"
author: "NousResearch Team"
tags: [search, research, web, information-retrieval]
priority: 80
min_context_tokens: 8000
timeout_seconds: 120
requires_tools:
- web_search
- browser_navigate
- text_extract
permissions:
- network_access
- no_file_write
use_cases:
- "Research the latest developments in a technical topic"
- "Gather competitor intelligence and comparative analysis"
- "Verify the credibility of a factual claim"
example_queries:
- "Research best practices for async programming in Rust"
- "Find the latest news on quantum computing commercialization"
- "Compare Hermes model performance against GPT-4"
---
# Web Research Skill
## Description
This skill executes deep web research through the following steps:
1. Decompose the query into 3-5 search sub-queries from multiple angles
2. Execute searches concurrently, collecting the top 10 results
3. Extract full-text content from high-quality sources
4. Cross-validate key facts
5. Generate a structured report with citations
## Output Format
```json
{
"summary": "Executive summary (under 200 words)",
"key_findings": ["finding 1", "finding 2"],
"sources": [{"title": "...", "url": "...", "relevance": 0.95}],
"confidence": 0.87,
"report": "Full report body (Markdown format)"
}
### Key Field Reference
| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Unique identifier, snake_case |
| `version` | semver | Semantic version for compatibility checks |
| `priority` | 0-100 | Base retrieval priority; higher = more likely to be selected |
| `min_context_tokens` | integer | Minimum context window required for execution |
| `timeout_seconds` | integer | Execution timeout |
| `requires_tools` | list | List of required built-in tools |
| `permissions` | list | Permission declarations |
---
## 17.4 Skill Metadata Structure
```python
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class SkillMetadata:
"""Complete structure definition for Skill metadata"""
# Identity
id: str # System-assigned UUID4
name: str # Skill name (lowercase + underscores)
version: str # Semantic version
description: str # Functional description for LLM understanding
# Classification and retrieval
tags: list[str]
priority: int = 50 # Base priority (0-100)
use_cases: list[str] = field(default_factory=list)
example_queries: list[str] = field(default_factory=list)
# Technical constraints
min_context_tokens: int = 4000
timeout_seconds: int = 60
max_retries: int = 3
requires_tools: list[str] = field(default_factory=list)
# Permissions
permissions: list[str] = field(default_factory=list)
sandbox: bool = False
# Parameter schemas (JSON Schema format)
input_schema: dict = field(default_factory=dict)
output_schema: dict = field(default_factory=dict)
# Runtime statistics (dynamically updated)
execution_count: int = 0
success_rate: float = 1.0
avg_latency_ms: float = 0.0
last_used: datetime | None = None
author: str = ""
source_path: str = ""
17.5 Parameter Binding Mechanism
Parameter binding is one of the most critical steps in Skill execution. Hermes supports a three-tier binding strategy with the following priority order (highest to lowest):
Explicit parameters (provided directly by user/Agent)
> Context variables
> Schema defaults
Three-Tier Binding in Action
# Tier 1: Explicit parameters from Agent intent extraction
skill_call = {
"skill": "web_research",
"params": {
"query": "Hermes 4 vs GPT-4o Function Calling performance",
"depth": "deep",
"language": "en-US"
}
}
# Tier 2: Context variables (shared session state)
context = AgentContext(
variables={
"user_language": "en-US", # Auto-binds to `language` param
"current_project": "hermes-guide",
"working_directory": "/workspace",
},
history=[...],
active_tools=[...],
)
# Tier 3: Schema defaults (from SKILL.md parameter definitions)
# language defaults to "en-US" if not provided by tiers 1 or 2
17.6 Skill Chains and Error Handling
Complex tasks often require multiple Skills to execute in sequence, forming a Skill Chain.
Defining a Skill Chain
# Chain example: competitive research + analysis report
skill_chain = SkillChain(
name="competitive_analysis",
steps=[
SkillStep(
skill="web_research",
params={"query": "{product_name} competitive analysis"},
output_var="raw_research",
),
SkillStep(
skill="data_analysis",
params={
"data": "{raw_research.key_findings}",
"analysis_type": "comparison",
},
output_var="analysis_result",
depends_on=["web_research"],
),
SkillStep(
skill="report_generation",
params={
"data": "{analysis_result}",
"format": "markdown",
},
output_var="final_report",
depends_on=["data_analysis"],
),
]
)
Four Error Handling Strategies
class ErrorStrategy(Enum):
FAIL_FAST = "fail_fast" # Fail immediately, propagate upward
RETRY = "retry" # Auto-retry (uses max_retries)
FALLBACK = "fallback" # Switch to a backup Skill
CONTINUE = "continue" # Log error but continue chain execution
# Example with full error handling configuration
SkillStep(
skill="web_research",
params={"query": "{query}"},
error_strategy=ErrorStrategy.FALLBACK,
fallback_skill="cached_search",
fallback_params={"query": "{query}", "max_age_days": 7},
retry_on=[NetworkTimeoutError, RateLimitError],
max_retries=3,
retry_backoff_seconds=2.0,
)
Execution Trace Log
{
"trace_id": "trace_7f3a9b2c",
"chain_name": "competitive_analysis",
"steps": [
{
"step": 1,
"skill": "web_research",
"status": "success",
"duration_ms": 8432,
"tokens_used": 2341
},
{
"step": 2,
"skill": "data_analysis",
"status": "retried_success",
"attempt": 2,
"error_on_attempt_1": "TimeoutError: exceeded 30s",
"duration_ms": 4218,
"tokens_used": 1876
}
],
"total_duration_ms": 12650,
"total_tokens": 4217
}
17.7 Summary
This chapter systematically covered the Hermes Agent Skill mechanism:
- Five-phase lifecycle: Register → Index → Retrieve → Execute → Feedback, forming a self-optimizing loop
- SKILL.md specification: YAML Front Matter + Markdown body for declarative capability description
- Metadata structure:
SkillMetadatacovers identity, classification, constraints, permissions, and runtime statistics - Three-tier parameter binding: Explicit params > Context variables > Schema defaults, with automatic type coercion
- Skill chains and errors:
SkillChainsupports dependency declaration; four error strategies cover all failure scenarios
The Skill mechanism elevates Hermes Agent from a "tool caller" to a "capability orchestrator" — the key abstraction layer for building enterprise-grade Agent applications.
Review Questions
-
If a Skill's failure rate exceeds 20%, how would Hermes's feedback mechanism affect its retrieval weight? How would you design an alerting system around this?
-
In a Skill chain where a middle step's output format doesn't match the next step's input schema, how would you design a "format adapter" Skill to bridge the gap?
-
The
priorityfield is statically configured, but in real-world applications priority may change based on time of day or user role. How would you design a dynamic priority system?