Skills¶
Skill providers, configuration models, and the proposal request/response types used by the planner's skill subsystem.
skills
¶
Skills subsystem public exports.
SkillProviderFactory
module-attribute
¶
SkillProviderFactory = Callable[[SkillsConfig], SkillProvider]
SkillProvider
¶
Bases: Protocol
Extension point for retrieving, searching, and formatting skills.
Implementations back the skill-related tools (retrieval, search, listing, directory)
exposed to agents. Built-in implementations are :class:LocalSkillProvider (backed
by a local SQLite store) and :class:CompositeSkillProvider (fans out to multiple
providers). Custom implementations may wrap remote skill catalogs, alternate storage
backends, or additional filtering/ranking logic; they must implement every method
below since callers do not duck-type around missing methods.
get_relevant
async
¶
get_relevant(query: SkillQuery, *, tool_context: Mapping[str, object], capability_context: SkillCapabilityContext | None = None) -> RetrievalResponse
Retrieve skills relevant to a task query, ranked and token-budgeted for injection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
SkillQuery
|
Task description and retrieval parameters (search type, top_k, filters). |
required |
tool_context
|
Mapping[str, object]
|
Caller-scoped context (e.g. tenant_id, project_id) used to filter skills by scope. |
required |
capability_context
|
SkillCapabilityContext | None
|
Optional snapshot of allowed tools/namespaces/tags used to filter out and redact skills the caller cannot use. |
None
|
Returns:
| Type | Description |
|---|---|
RetrievalResponse
|
The ranked skills plus pre-formatted, token-budgeted context text. |
search
async
¶
search(query: SkillSearchQuery, *, tool_context: Mapping[str, object], capability_context: SkillCapabilityContext | None = None) -> SkillSearchResponse
Search skills by free-text query, returning lightweight ranked matches.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
SkillSearchQuery
|
Search text and parameters (search type, limit, filters). |
required |
tool_context
|
Mapping[str, object]
|
Caller-scoped context used to filter skills by scope. |
required |
capability_context
|
SkillCapabilityContext | None
|
Optional snapshot of allowed tools/namespaces/tags used to filter out results the caller cannot use. |
None
|
Returns:
| Type | Description |
|---|---|
SkillSearchResponse
|
Ranked, lightweight search results (name/title/trigger/score). |
get_by_name
async
¶
get_by_name(names: list[str], *, tool_context: Mapping[str, object], capability_context: SkillCapabilityContext | None = None) -> list[SkillResultDetailed]
Fetch full skill details for a set of known names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
names
|
list[str]
|
Skill names to fetch. |
required |
tool_context
|
Mapping[str, object]
|
Caller-scoped context used to filter skills by scope. |
required |
capability_context
|
SkillCapabilityContext | None
|
Optional snapshot of allowed tools/namespaces/tags used to filter out and redact skills the caller cannot use. |
None
|
Returns:
| Type | Description |
|---|---|
list[SkillResultDetailed]
|
Detailed skill records for the requested names that are applicable and found; |
list[SkillResultDetailed]
|
names that do not exist or are filtered out are silently omitted. |
list
async
¶
list(req: SkillListRequest, *, tool_context: Mapping[str, object], capability_context: SkillCapabilityContext | None = None) -> SkillListResponse
List skills with pagination, independent of any search query.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
req
|
SkillListRequest
|
Pagination and filter parameters (page, page_size, task_type, origin, tags, namespace). |
required |
tool_context
|
Mapping[str, object]
|
Caller-scoped context used to filter skills by scope. |
required |
capability_context
|
SkillCapabilityContext | None
|
Optional snapshot of allowed tools/namespaces/tags used to filter out skills the caller cannot use. |
None
|
Returns:
| Type | Description |
|---|---|
SkillListResponse
|
A page of lightweight skill entries plus the total applicable count. |
directory
async
¶
directory(config: SkillsDirectoryConfig, *, tool_context: Mapping[str, object], capability_context: SkillCapabilityContext | None = None) -> Sequence[SkillDirectoryEntry]
Build the always-available skills directory listing (pinned plus recent/top).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
SkillsDirectoryConfig
|
Directory configuration (enabled flag, max entries, selection strategy). |
required |
tool_context
|
Mapping[str, object]
|
Caller-scoped context used to filter skills by scope. |
required |
capability_context
|
SkillCapabilityContext | None
|
Optional snapshot of allowed tools/namespaces/tags used to filter out skills the caller cannot use. |
None
|
Returns:
| Type | Description |
|---|---|
Sequence[SkillDirectoryEntry]
|
Directory entries in priority order (pinned first), or an empty sequence |
Sequence[SkillDirectoryEntry]
|
when the directory is disabled. |
format_for_injection
async
¶
format_for_injection(skills: Sequence[SkillResultDetailed], *, max_tokens: int) -> tuple[str, int, int, bool]
Render skills into prompt-ready text within a token budget.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
skills
|
Sequence[SkillResultDetailed]
|
Skills to render, most relevant first. |
required |
max_tokens
|
int
|
Approximate token budget for the rendered text. |
required |
Returns:
| Type | Description |
|---|---|
str
|
A tuple of ``(formatted_text, raw_tokens_est, final_tokens_est, |
int
|
was_summarized) |
int
|
fit the budget. |
SkillsConfig
¶
Bases: BaseModel
Top-level configuration for the skills subsystem.
Controls whether skills are enabled, where they are cached, how retrieval results are budgeted/redacted, and which packs feed the local skill store.
enabled
class-attribute
instance-attribute
¶
enabled: bool = Field(default=False, description='Whether the skills subsystem is active.')
cache_dir
class-attribute
instance-attribute
¶
cache_dir: str = Field(default='.penguiflow', description='Directory used to store the local skills database.')
max_tokens
class-attribute
instance-attribute
¶
max_tokens: int = Field(default=2000, ge=200, le=10000, description='Token budget for formatted skill context injected into prompts.')
summarize
class-attribute
instance-attribute
¶
summarize: bool = Field(default=False, description='Whether to summarize skill content when it exceeds the token budget.')
redact_pii
class-attribute
instance-attribute
¶
redact_pii: bool = Field(default=True, description='Whether to redact PII from skill text before returning it to callers.')
scope_mode
class-attribute
instance-attribute
¶
scope_mode: SkillScopeMode = Field(default='project', description='Default visibility scope for skills without an explicit scope.')
skill_packs
class-attribute
instance-attribute
¶
skill_packs: list[SkillPackConfig] = Field(default_factory=list, description='Skill packs to load into the local store.')
directory
class-attribute
instance-attribute
¶
directory: SkillsDirectoryConfig = Field(default_factory=SkillsDirectoryConfig, description='Configuration for the always-available skills directory listing.')
proposal
class-attribute
instance-attribute
¶
proposal: SkillProposalConfig = Field(default_factory=SkillProposalConfig, description='Configuration for the skill-proposal (learn-a-skill) feature.')
fts_fallback_to_regex
class-attribute
instance-attribute
¶
fts_fallback_to_regex: bool = Field(default=True, description='Whether to fall back to regex search when full-text search (FTS) is unavailable.')
top_k
class-attribute
instance-attribute
¶
top_k: int = Field(default=6, ge=1, le=20, description='Default number of skills returned by relevance retrieval.')
prune_packs_not_in_config
class-attribute
instance-attribute
¶
prune_packs_not_in_config: bool = Field(default=True, description='Whether to remove pack-origin skills for packs no longer present (or disabled) in this config.')
SkillsDirectoryConfig
¶
Bases: BaseModel
Configuration for the always-available skills directory listing.
The directory is a lightweight summary of skills (pinned entries plus recent/top ones) surfaced to callers without requiring a search query.
enabled
class-attribute
instance-attribute
¶
enabled: bool = Field(default=True, description='Whether the skills directory listing is generated at all.')
max_entries
class-attribute
instance-attribute
¶
max_entries: int = Field(default=30, ge=1, le=200, description='Maximum number of entries returned in the directory.')
include_fields
class-attribute
instance-attribute
¶
include_fields: list[SkillDirectoryField] = Field(default_factory=_default_directory_fields, description='Which skill fields to include per directory entry.')
selection_strategy
class-attribute
instance-attribute
¶
selection_strategy: Literal['pinned_then_recent', 'pinned_then_top'] = Field(default='pinned_then_recent', description='How to fill directory slots beyond pinned skills: by most recently used (pinned_then_recent) or by highest use count (pinned_then_top).')
SkillPackConfig
¶
Bases: BaseModel
Configuration for a single skill pack loaded into the skills subsystem.
A skill pack is a file or directory of skill definitions (see
:class:SkillDefinition) ingested into the local skill store on load. Each pack is
tracked by name so it can be updated or pruned independently of other packs.
name
class-attribute
instance-attribute
¶
name: str = Field(description='Unique identifier for this pack, used for provenance tracking and pruning.')
path
class-attribute
instance-attribute
¶
path: str = Field(description='Filesystem path to the pack source (file or directory); interpreted per `format`.')
format
class-attribute
instance-attribute
¶
format: SkillPackFormat | None = Field(default=None, description='Serialization format of the pack contents (md/yaml/json/jsonl). None auto-detects from `path`.')
scope_mode
class-attribute
instance-attribute
¶
scope_mode: SkillScopeMode = Field(default='project', description='Visibility scope applied to skills loaded from this pack: project, tenant, or global.')
enabled
class-attribute
instance-attribute
¶
enabled: bool = Field(default=True, description='Whether this pack is actively loaded and kept in the store.')
update_existing_pack_skills
class-attribute
instance-attribute
¶
update_existing_pack_skills: bool = Field(default=True, description='Whether to overwrite already-stored skills from this pack with updated pack content on reload.')
prune_missing_pack_skills
class-attribute
instance-attribute
¶
prune_missing_pack_skills: bool = Field(default=True, description='Whether to delete stored skills from this pack no longer present in the pack source.')
pinned_skill_names
class-attribute
instance-attribute
¶
pinned_skill_names: list[str] = Field(default_factory=list, description='Skill names from this pack to always surface first in the skills directory listing.')
SkillProposalConfig
¶
Bases: BaseModel
Configuration for the skill-proposal (learn-a-skill) feature.
enabled
class-attribute
instance-attribute
¶
enabled: bool = Field(default=False, description='Whether skill proposal drafting is enabled.')
SkillProposalDraft
¶
Bases: BaseModel
A candidate skill produced by the proposal pipeline, pending review.
Callers typically show the draft to a human (or a higher-level agent) for approval
before persisting skill as a real, usable skill.
skill
class-attribute
instance-attribute
¶
skill: SkillDefinition = Field(description='The proposed skill definition, ready to persist if approved.')
warnings
class-attribute
instance-attribute
¶
warnings: list[str] = Field(default_factory=list, description='Non-fatal issues detected while drafting the skill (e.g. missing detail).')
assumptions
class-attribute
instance-attribute
¶
assumptions: list[str] = Field(default_factory=list, description='Assumptions made when the source material was ambiguous or incomplete.')
SkillProposeRequest
¶
Bases: BaseModel
Request to draft a new skill from unstructured source material.
source_material is the raw text (e.g. a transcript, log, or write-up) that the
proposal pipeline analyzes to synthesize a :class:SkillDefinition.
source_material
class-attribute
instance-attribute
¶
source_material: str = Field(description='Raw text analyzed to synthesize the skill draft. Must be non-empty.')
task_type
class-attribute
instance-attribute
¶
task_type: SkillTaskType | None = Field(default=None, description="Optional hint for the skill's task_type classification.")
title_hint
class-attribute
instance-attribute
¶
title_hint: str | None = Field(default=None, description='Optional suggested title for the drafted skill.')
trigger_hint
class-attribute
instance-attribute
¶
trigger_hint: str | None = Field(default=None, description='Optional suggested trigger phrase for the drafted skill.')
required_tool_names
class-attribute
instance-attribute
¶
required_tool_names: list[str] = Field(default_factory=list, description='Tool names the drafted skill should declare as required.')
required_namespaces
class-attribute
instance-attribute
¶
required_namespaces: list[str] = Field(default_factory=list, description='Tool namespaces the drafted skill should declare as required.')
required_tags
class-attribute
instance-attribute
¶
required_tags: list[str] = Field(default_factory=list, description='Tool tags the drafted skill should declare as required.')
SkillProposeResponse
¶
Bases: BaseModel
Response wrapping a drafted skill proposal.
draft
class-attribute
instance-attribute
¶
draft: SkillProposalDraft = Field(description='The drafted skill, warnings, and assumptions produced by the pipeline.')
SkillCapabilityContext
dataclass
¶
SkillCapabilityContext(all_tool_names: set[str] = set(), allowed_tool_names: set[str] = set(), allowed_namespaces: set[str] = set(), allowed_tool_tags: set[str] = set())
Snapshot of which tools/namespaces/tags a caller is currently allowed to use.
Used to filter and redact skills that reference tools the caller cannot invoke
(e.g. because a tool was disabled or scoped out for this request). Typically built
via :func:penguiflow.skills.provider.build_skill_capability_context.
Attributes:
| Name | Type | Description |
|---|---|---|
all_tool_names |
set[str]
|
Every tool name known in the current execution context. |
allowed_tool_names |
set[str]
|
Subset of |
allowed_namespaces |
set[str]
|
Tool namespaces (prefix before the first '.') derived from
|
allowed_tool_tags |
set[str]
|
Tags declared on tools in |
all_tool_names
class-attribute
instance-attribute
¶
all_tool_names: set[str] = field(default_factory=set)
allowed_tool_names
class-attribute
instance-attribute
¶
allowed_tool_names: set[str] = field(default_factory=set)
allowed_namespaces
class-attribute
instance-attribute
¶
allowed_namespaces: set[str] = field(default_factory=set)
allowed_tool_tags
class-attribute
instance-attribute
¶
allowed_tool_tags: set[str] = field(default_factory=set)