pub trait SkillSurface: Send + Sync {
// Required methods
fn id(&self) -> &'static str;
fn supported_skill_scopes(&self) -> &'static [ScopeKind];
fn skill_status(
&self,
scope: &Scope,
name: &str,
expected_owner: &str,
) -> Result<StatusReport, AgentConfigError>;
fn plan_install_skill(
&self,
scope: &Scope,
spec: &SkillSpec,
) -> Result<InstallPlan, AgentConfigError>;
fn plan_uninstall_skill(
&self,
scope: &Scope,
name: &str,
owner_tag: &str,
) -> Result<UninstallPlan, AgentConfigError>;
fn install_skill(
&self,
scope: &Scope,
spec: &SkillSpec,
) -> Result<InstallReport, AgentConfigError>;
fn uninstall_skill(
&self,
scope: &Scope,
name: &str,
owner_tag: &str,
) -> Result<UninstallReport, AgentConfigError>;
// Provided methods
fn is_skill_installed(
&self,
scope: &Scope,
name: &str,
) -> Result<bool, AgentConfigError> { ... }
fn validate_skill(
&self,
scope: &Scope,
name: &str,
) -> Result<ValidationReport, AgentConfigError> { ... }
fn validate_skill_for_owner(
&self,
scope: &Scope,
name: &str,
expected_owner: Option<&str>,
) -> Result<ValidationReport, AgentConfigError> { ... }
}Expand description
One AI harness’s skill installer.
Skills are directory-scoped: each one is a folder under the harness’s
skills/ root containing a SKILL.md plus optional scripts/,
references/, and assets/ subdirectories. Implemented by harnesses with
upstream Agent Skills support.
Like McpSurface, ownership is tracked via a sidecar ledger so multiple
consumers can coexist and uninstall is refused on owner mismatch.
Required Methods§
Sourcefn id(&self) -> &'static str
fn id(&self) -> &'static str
Stable, kebab-case identifier matching Integration::id for the
same agent.
Sourcefn supported_skill_scopes(&self) -> &'static [ScopeKind]
fn supported_skill_scopes(&self) -> &'static [ScopeKind]
Which scopes this skill installer accepts.
Sourcefn skill_status(
&self,
scope: &Scope,
name: &str,
expected_owner: &str,
) -> Result<StatusReport, AgentConfigError>
fn skill_status( &self, scope: &Scope, name: &str, expected_owner: &str, ) -> Result<StatusReport, AgentConfigError>
Detailed installation state for the skill identified by name,
scored against expected_owner. See McpSurface::mcp_status for
the owner-comparison semantics.
§Errors
Same envelope as McpSurface::mcp_status.
Sourcefn plan_install_skill(
&self,
scope: &Scope,
spec: &SkillSpec,
) -> Result<InstallPlan, AgentConfigError>
fn plan_install_skill( &self, scope: &Scope, spec: &SkillSpec, ) -> Result<InstallPlan, AgentConfigError>
Plan a skill install without mutating user files.
§Errors
AgentConfigError::PathResolutionwhen the skill directory cannot be resolved.AgentConfigError::Io/AgentConfigError::ConfigTooLargewhen reading existing skill assets or the ledger fails.AgentConfigError::MissingSpecField/AgentConfigError::InvalidTagfromSkillSpecre-validation.
Predictable refusals (unsupported scope, owner mismatch) are encoded
as crate::plan::PlanStatus::Refused.
Sourcefn plan_uninstall_skill(
&self,
scope: &Scope,
name: &str,
owner_tag: &str,
) -> Result<UninstallPlan, AgentConfigError>
fn plan_uninstall_skill( &self, scope: &Scope, name: &str, owner_tag: &str, ) -> Result<UninstallPlan, AgentConfigError>
Sourcefn install_skill(
&self,
scope: &Scope,
spec: &SkillSpec,
) -> Result<InstallReport, AgentConfigError>
fn install_skill( &self, scope: &Scope, spec: &SkillSpec, ) -> Result<InstallReport, AgentConfigError>
Install (or update) the skill directory and record ownership. Repeated calls with byte-identical contents are a no-op after the first.
§Errors
AgentConfigError::PathResolutionwhen a target path escapes the scope root or contains a symlink component.AgentConfigError::UnsupportedScopewhen the scope is not insupported_skill_scopes.AgentConfigError::Iofor filesystem failures.AgentConfigError::JsonInvalidwhen the ownership ledger is malformed.AgentConfigError::ConfigTooLargewhen an input exceeds 8 MiB.AgentConfigError::BackupExistswhen a sibling.bakalready exists for a file we would back up.AgentConfigError::NotOwnedByCallerwhen the skill exists on disk under another owner (or unowned andadopt_unownedis false).AgentConfigError::MissingSpecField/AgentConfigError::InvalidTagfrom spec re-validation.
Sourcefn uninstall_skill(
&self,
scope: &Scope,
name: &str,
owner_tag: &str,
) -> Result<UninstallReport, AgentConfigError>
fn uninstall_skill( &self, scope: &Scope, name: &str, owner_tag: &str, ) -> Result<UninstallReport, AgentConfigError>
Uninstall the skill identified by name, owned by owner_tag.
Returns AgentConfigError::NotOwnedByCaller on owner mismatch or when
the skill exists on disk but is missing from the ledger.
§Errors
Same envelope as install_skill. The
owner-mismatch case is the typical one.
Provided Methods§
Sourcefn is_skill_installed(
&self,
scope: &Scope,
name: &str,
) -> Result<bool, AgentConfigError>
fn is_skill_installed( &self, scope: &Scope, name: &str, ) -> Result<bool, AgentConfigError>
Returns true if a skill named name is currently recorded in the
ownership ledger for this scope.
Default impl mirrors McpSurface::is_mcp_installed: both
InstallStatus::InstalledOwned and
InstallStatus::InstalledOtherOwner count as installed.
§Errors
Propagates whatever skill_status returns.
Sourcefn validate_skill(
&self,
scope: &Scope,
name: &str,
) -> Result<ValidationReport, AgentConfigError>
fn validate_skill( &self, scope: &Scope, name: &str, ) -> Result<ValidationReport, AgentConfigError>
Validate skill state without mutating user files.
§Errors
Equivalent to
validate_skill_for_owner
with expected_owner = None.
Sourcefn validate_skill_for_owner(
&self,
scope: &Scope,
name: &str,
expected_owner: Option<&str>,
) -> Result<ValidationReport, AgentConfigError>
fn validate_skill_for_owner( &self, scope: &Scope, name: &str, expected_owner: Option<&str>, ) -> Result<ValidationReport, AgentConfigError>
Validate skill state against a caller-supplied expected owner.
§Errors
AgentConfigError::InvalidTagwhennameviolates the kebab-case skill-name contract orexpected_owneris malformed.- Any error from
skill_statusother thanAgentConfigError::JsonInvalid, which is folded into the returnedValidationReportas malformed-ledger output.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".