# Skill Protocol Reference The **Skill Protocol** defines the type contracts used for skill discovery, composition, execution, and error reporting within CleverAgents v3. All protocol types are frozen Pydantic `BaseModel` instances, ensuring immutability after construction. --- ## Overview | Type | Purpose | |------|---------| | `SkillErrorType` | `StrEnum` of all skill error categories | | `SkillError` | Structured error payload | | `SkillMetadata` | Lightweight discovery descriptor | | `SkillDefinition` | Full skill + resolved tools + metadata | | `SkillResult` | Outcome of a skill-tool invocation | --- ## SkillErrorType A `StrEnum` with the following members: | Value | Description | |-------|-------------| | `skill_not_found` | The requested skill does not exist | | `resolution_failure` | Skill resolution failed (missing include, etc.) | | `cycle_detected` | Circular dependency in skill includes | | `tool_activation_failure` | Tool could not be activated | | `tool_execution_failure` | Tool execution failed at runtime | | `validation_error` | Input/output schema validation failed | | `permission_denied` | Operation not permitted | --- ## SkillError Structured error payload for skill operations. ### Fields | Field | Type | Required | Description | |-------|------|----------|-------------| | `error_type` | `SkillErrorType` | Yes | Error category | | `message` | `str` | Yes | Human-readable description | | `details` | `dict[str, Any]` | No | Diagnostic context | | `skill_name` | `str` | Yes | Originating skill | | `tool_name` | `str \| None` | No | Originating tool | --- ## SkillMetadata Lightweight metadata for skill discovery and catalogue listings. ### Fields | Field | Type | Default | Description | |-------|------|---------|-------------| | `name` | `str` | — | Namespaced skill name | | `description` | `str` | — | Skill description | | `version` | `str` | `"0.0.0"` | Semantic version | | `tool_count` | `int` | `0` | Number of resolved tools | | `capability_summary` | `SkillCapabilitySummary` | empty | Aggregated capabilities | | `source_types` | `list[str]` | `[]` | Distinct source type labels | | `writes` | `bool` | `False` | Any tool can write | | `read_only` | `bool` | `True` | Entire skill is read-only | ### Factory: `from_skill()` ```python meta = SkillMetadata.from_skill(skill, resolved=resolved_entries, version="1.0.0") ``` Derives `writes` and `read_only` from the `SkillCapabilitySummary`: - `writes = True` when `write_tools > 0` or `has_side_effects` is true - `read_only = True` when `write_tools == 0` and no side effects ### Writes / Read-Only Gating The `writes` and `read_only` flags are propagated to the ToolRuntime gating layer. A skill marked `read_only=True` will never be allowed to trigger a write-capable tool at runtime. --- ## SkillDefinition Full skill definition combining the domain `Skill` model, resolved tools, and pre-computed metadata. ### Fields | Field | Type | Required | Description | |-------|------|----------|-------------| | `skill` | `Skill` | Yes | Domain-level Skill model | | `resolved_tools` | `list[ResolvedToolEntry]` | No | Flattened tool set | | `metadata` | `SkillMetadata` | Yes | Pre-computed metadata | | `input_schema` | `dict \| None` | No | JSON Schema for inputs | | `output_schema` | `dict \| None` | No | JSON Schema for outputs | ### JSON Schema Validation When `input_schema` or `output_schema` is provided, it **must** include a `"type"` key to be considered a valid JSON Schema object. The validator rejects schemas missing this key at construction time. ```json { "type": "object", "properties": { "query": {"type": "string"} } } ``` ### Writes Consistency The model validator checks that if `metadata.read_only` is `True`, none of the resolved inline tools declare `writes=True`. A mismatch raises a `ValidationError`. --- ## SkillResult Outcome of a single skill-tool invocation. ### Fields | Field | Type | Default | Description | |-------|------|---------|-------------| | `skill_name` | `str` | — | Invoked skill | | `tool_name` | `str` | — | Invoked tool | | `success` | `bool` | — | Whether invocation succeeded | | `output_data` | `Any` | `None` | Tool output | | `error` | `SkillError \| None` | `None` | Error on failure | | `duration_ms` | `float` | `0.0` | Execution time in ms | | `resource_changes` | `list[dict]` | `[]` | Resource change descriptors | --- ## Error Mapping The `map_tool_error()` helper normalises arbitrary exceptions into `SkillError` payloads: ```python from cleveragents.skills.protocol import map_tool_error try: run_tool(...) except Exception as exc: error = map_tool_error(exc, skill_name="local/my-skill", tool_name="local/my-tool") ``` ### Mapping Rules | Exception Type | Message Contains | Mapped To | |----------------|------------------|-----------| | `ValueError` | `"cycle"` | `CYCLE_DETECTED` | | `ValueError` | `"not found"` | `SKILL_NOT_FOUND` | | `ValueError` | (other) | `RESOLUTION_FAILURE` | | `PermissionError` | — | `PERMISSION_DENIED` | | `ValidationError` | — | `VALIDATION_ERROR` | | Any | `"activation"` | `TOOL_ACTIVATION_FAILURE` | | Any | (other) | `TOOL_EXECUTION_FAILURE` | --- ## JSON Schema Rules Summary 1. **Input/output schemas** on `SkillDefinition` must include `"type"`. 2. **Writes/read_only metadata** on `SkillMetadata` must be consistent with the resolved tool capabilities. 3. **Error payloads** always include `skill_name`; `tool_name` is optional but recommended. 4. All protocol types are **frozen** (immutable after construction).