API Reference
Protocols
Section titled “Protocols”SkillExecutorProtocol
Section titled “SkillExecutorProtocol”Protocol for executing skills with lifecycle management.
Handles skill selection, validation, execution, retry, caching, permission checking, and observability.
async def execute( skill_name: str, params: dict[str, Any], user_id: str | None = None, session_id: str | None = None ) -> Result[SkillResult, SkillError]
Execute a skill with full lifecycle management.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill to execute |
| `params` | dict[str, Any] | Parameters for the skill |
| `user_id` | str | None | Optional user ID for permission checks |
| `session_id` | str | None | Optional session ID for context |
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Result with SkillResult on success or SkillError on failure |
SkillProtocol
Section titled “SkillProtocol”Protocol for a composable skill.
A skill is an async-callable capability that can be registered, discovered, and executed with validation and error handling.
property definition() -> SkillDefinition
Get the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | The skill's definition including parameters and metadata |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Execute the skill.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Result with SkillResult on success or SkillError on failure |
Validate parameters against the definition.
| Parameter | Type | Description |
|---|---|---|
| `params` | dict[str, Any] | Parameters to validate |
| Type | Description |
|---|---|
| list[str] | List of validation errors (empty if valid) |
SkillRegistryProtocol
Section titled “SkillRegistryProtocol”Protocol for registering and discovering skills.
Maintains a registry of available skills with support for filtering by category and permissions.
def register(skill: SkillProtocol) -> None
Register a skill in the registry.
| Parameter | Type | Description |
|---|---|---|
| `skill` | SkillProtocol | The skill to register |
def get(name: str) -> SkillProtocol | None
Get a skill by name.
| Parameter | Type | Description |
|---|---|---|
| `name` | str | The skill name |
| Type | Description |
|---|---|
| SkillProtocol | None | The skill, or None if not found |
def list_skills( category: str | None = None, permissions: list[str] | None = None ) -> list[SkillDefinition]
List available skills with optional filtering.
| Parameter | Type | Description |
|---|---|---|
| `category` | str | None | Filter by skill category |
| `permissions` | list[str] | None | Filter to skills that match any of these permissions |
| Type | Description |
|---|---|
| list[SkillDefinition] | List of skill definitions matching the criteria |
Get OpenAI function-calling compatible schemas.
| Type | Description |
|---|---|
| list[dict[str, Any]] | List of skill schemas in OpenAI function calling format |
Classes
Section titled “Classes”AbstractSkill
Section titled “AbstractSkill”Abstract base class for class-based skill definitions.
Subclass this and define a definition class attribute plus an
execute method. Parameter validation default uses the JSON schema
stored on the definition; override validate for custom rules.
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Execute the skill with the provided keyword arguments.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Result wrapping SkillResult on success or SkillError on failure. |
Validate params against the skill definition’s parameter schema.
| Parameter | Type | Description |
|---|---|---|
| `params` | dict[str, Any] | Parameters to validate. |
| Type | Description |
|---|---|
| list[str] | List of validation error messages (empty list means valid). |
Convert this skill to a ToolProtocol for use in Lexigram agents.
| Type | Description |
|---|---|
| SkillToolAdapter | A SkillToolAdapter that implements ToolProtocol. |
CodeExecutionSkill
Section titled “CodeExecutionSkill”Execute code in a sandboxed environment and return the output.
This is a stub implementation. For production use, replace with a proper sandboxed execution backend (e.g. Docker, WASM, a remote code execution service).
Required permission: code.execute.
property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the code_execute skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Return a stub result indicating execution is not implemented.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok stub result with ``output=""``, ``stderr=""``, ``exit_code=0``, and ``stub=True``. |
DatabaseQuerySkill
Section titled “DatabaseQuerySkill”Execute read-only SELECT statements and return row dicts.
Only SELECT statements are accepted. A LIMIT clause is
automatically appended when the query does not already contain one,
capped at max_rows (default 100) to prevent runaway reads.
| Parameter | Type | Description |
|---|---|---|
| `db` | A DatabaseProviderProtocol instance. | |
| `max_rows` | Maximum rows returned per query. |
Initialise the skill with a database provider.
| Parameter | Type | Description |
|---|---|---|
| `db` | DatabaseProviderProtocol | DatabaseProviderProtocol for query execution. |
| `max_rows` | int | Hard cap on returned rows. |
property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the database_query skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Execute the SELECT query and return up to max_rows rows.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok result with ``rows`` and ``row_count``, or Err if the query is not a SELECT or execution fails. |
DateTimeSkill
Section titled “DateTimeSkill”Return the current UTC date, time, and Unix timestamp.
Parameters
Section titled “Parameters”timezone : str, optional
IANA timezone name (e.g. "America/New_York"). Defaults to
"UTC". Only UTC is supported without the zoneinfo stdlib
module (Python 3.9+); unknown timezones fall back to UTC.
Example output
{ "datetime": "2026-01-15T14:32:00+00:00", "date": "2026-01-15", "time": "14:32:00", "timestamp": 1736951520.0, "timezone": "UTC"}property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the current_datetime skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Execute the skill and return the current datetime.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok result containing a datetime dict. |
FileReadSkill
Section titled “FileReadSkill”Read a file and return its content as a string.
Files are only accessible within base_dir (defaults to the current working directory). Directory traversal attempts return an error.
Required permission: files.read.
Initialise with an optional sandbox directory.
| Parameter | Type | Description |
|---|---|---|
| `base_dir` | str | None | Base directory constraint. Defaults to ``os.getcwd()``. |
property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the file_read skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Read and return file content.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok result with ``content``, ``path``, and ``size_bytes``, or Err. |
FileWriteSkill
Section titled “FileWriteSkill”Write text content to a local file.
Files are only writable within base_dir. The parent directory must exist; write will not create intermediate directories.
Required permission: files.write.
Initialise with an optional sandbox directory.
| Parameter | Type | Description |
|---|---|---|
| `base_dir` | str | None | Base directory constraint. Defaults to ``os.getcwd()``. |
property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the file_write skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Write content to the specified path.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok result with ``path`` and ``bytes_written``, or Err. |
FunctionSkill
Section titled “FunctionSkill”Wraps an async function decorated with ``@skill`` as a SkillProtocol.
Created automatically by the @skill decorator — not intended for
direct instantiation.
def __init__( fn: Callable[Ellipsis, Awaitable[Any]], definition: SkillDefinition, param_names: list[str] | None = None ) -> None
Initialise a FunctionSkill.
| Parameter | Type | Description |
|---|---|---|
| `fn` | Callable[Ellipsis, Awaitable[Any]] | The underlying async callable. |
| `definition` | SkillDefinition | The skill's definition metadata. |
| `param_names` | list[str] | None | Ordered list of declared parameter names from ``@skill_param`` decorators (used for schema building). |
property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | The SkillDefinition for this function skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Call the wrapped async function and wrap its return value.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Result wrapping SkillResult on success or SkillError on failure. |
Validate params against the JSON schema in the definition.
| Parameter | Type | Description |
|---|---|---|
| `params` | dict[str, Any] | Parameters to validate. |
| Type | Description |
|---|---|
| list[str] | List of validation error messages. |
Convert this skill to a ToolProtocol for use in Lexigram agents.
| Type | Description |
|---|---|
| SkillToolAdapter | A SkillToolAdapter that implements ToolProtocol. |
HTTPRequestSkill
Section titled “HTTPRequestSkill”Make outbound HTTP requests and return the response body.
By default the skill uses urllib.request (stdlib) to avoid
requiring an extra HTTP client dependency. For production workloads
integrate with the lexigram-http HTTPClientProtocol.
Required permission: http.request.
property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the http_request skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Execute the HTTP request (stdlib urllib, sync-in-thread).
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok result with ``status_code``, ``body``, and ``url``, or Err on network/validation failure. |
MCPSkillBridge
Section titled “MCPSkillBridge”Import MCP tools as Lexigram skills and export skills as MCP tools.
This bridge allows a skill registry to expose its skills to MCP-aware callers and consume MCP tools as if they were first-class skills.
Note
The MCP integration uses lexigram.ai.mcp when available. This class is a stub that gracefully degrades when the MCP package is not installed.
def __init__(registry: SkillRegistry) -> None
Initialise the bridge with the backing registry.
| Parameter | Type | Description |
|---|---|---|
| `registry` | SkillRegistry | The skill registry to import into / export from. |
Register all tools exposed by an MCP client as skills.
| Parameter | Type | Description |
|---|---|---|
| `mcp_client` | Any | An object implementing MCPClientProtocol (from ``lexigram.ai.mcp``). |
| Type | Description |
|---|---|
| int | Number of tools successfully imported as skills. |
Export all registered skills as MCP tool definitions.
| Type | Description |
|---|---|
| list[dict[str, Any]] | List of dicts following the MCP tool definition schema. |
MathSkill
Section titled “MathSkill”Evaluate safe arithmetic expressions.
Supports the operators +, -, *, /, //, %, and
**. No functions, names, or string literals are permitted.
Example output
{"result": 1024.0, "expression": "2 ** 10"}property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the math_calculate skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Evaluate the expression and return the result.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok result with ``result`` and ``expression`` keys, or Err on invalid expression. |
ModuleScanner
Section titled “ModuleScanner”Discover and auto-register skills from Python modules.
The scanner walks every attribute of the target module. Attributes that are instances of BaseSkill (or its subclasses, including FunctionSkill) are registered into the provided SkillRegistry.
Example
scanner = ModuleScanner(container)await scanner.scan(registry, "myapp.skills.builtin")def __init__(container: ContainerProtocol | None = None) -> None
Initialise the scanner.
| Parameter | Type | Description |
|---|---|---|
| `container` | ContainerProtocol | None | Optional DI container for resolving class-based skills. |
async def scan( registry: SkillRegistry, module_path: str ) -> int
Import module_path and register all discovered skills.
| Parameter | Type | Description |
|---|---|---|
| `registry` | SkillRegistry | The SkillRegistry to register discovered skills into. |
| `module_path` | str | Dotted import path of the module to scan. |
| Type | Description |
|---|---|
| int | Number of skills successfully registered. |
async def scan_package( registry: SkillRegistry, package_path: str ) -> int
Recursively scan all modules within a package.
| Parameter | Type | Description |
|---|---|---|
| `registry` | SkillRegistry | The SkillRegistry to register discovered skills into. |
| `package_path` | str | Dotted import path of the package to scan. |
| Type | Description |
|---|---|
| int | Total number of skills registered across all sub-modules. |
ParallelSkills
Section titled “ParallelSkills”Execute multiple skills concurrently and aggregate their outputs.
All skills receive the same params. Errors from individual skills do
not abort the fan-out; they are collected and returned as part of the
aggregated output dict under an "_errors" key.
Example
parallel = ParallelSkills(["sentiment_analysis", "entity_extraction"])result = await parallel.execute(executor, {"text": "Hello world"})combined = result.unwrap().output# combined == {"sentiment_analysis": {...}, "entity_extraction": {...}}Initialise with the skills to run in parallel.
| Parameter | Type | Description |
|---|---|---|
| `skill_names` | list[str] | Names of skills to execute concurrently. |
async def execute( executor: Any, params: dict[str, Any] ) -> Result[SkillResult, SkillError]
Run all skills concurrently and aggregate results.
| Parameter | Type | Description |
|---|---|---|
| `executor` | Any | SkillExecutorProtocol instance. |
| `params` | dict[str, Any] | Input parameters forwarded to every skill. |
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | A SkillResult whose ``output`` is a dict mapping each skill name to its output (or an error string if that skill failed). |
PermissionChecker
Section titled “PermissionChecker”Grant and verify per-user permission sets for skill execution.
Permissions are plain strings (e.g. "files.read", "db.query").
A user with no registered permissions is treated as having no permissions.
Example
checker = PermissionChecker()checker.grant("user-123", {"files.read", "web.search"})allowed = checker.check("user-123", {"files.read"}) # Truedenied = checker.check("user-123", {"db.write"}) # FalseInitialise an empty permission store.
Add permissions for a user.
| Parameter | Type | Description |
|---|---|---|
| `user_id` | str | The user identifier. |
| `permissions` | set[str] | Set of permission strings to grant. |
Remove permissions for a user.
| Parameter | Type | Description |
|---|---|---|
| `user_id` | str | The user identifier. |
| `permissions` | set[str] | Set of permission strings to revoke. |
Replace all permissions for a user with the given set.
| Parameter | Type | Description |
|---|---|---|
| `user_id` | str | The user identifier. |
| `permissions` | set[str] | Complete replacement permission set. |
Return the current permission set for a user.
| Parameter | Type | Description |
|---|---|---|
| `user_id` | str | The user identifier. |
| Type | Description |
|---|---|
| set[str] | Set of permission strings (may be empty). |
Check whether a user possesses all required permissions.
| Parameter | Type | Description |
|---|---|---|
| `user_id` | str | The user to check. |
| `required` | set[str] | Permissions that must all be present. |
| Type | Description |
|---|---|
| bool | ``True`` if every required permission is granted; ``False`` otherwise (including when *required* is empty — returns ``True``). |
SkillChain
Section titled “SkillChain”Execute skills sequentially, piping each output into the next input.
Each step is a (skill_name, output_mapping) tuple where
output_mapping maps keys from the previous output dict to parameter
names for the next skill. An empty mapping passes all keys unchanged.
Example
chain = SkillChain([ ("web_search", {"results": "documents"}), ("text_summarize", {}),])result = await chain.execute(executor, {"query": "AI trends 2026"})Initialise the chain with its steps.
| Parameter | Type | Description |
|---|---|---|
| `steps` | list[tuple[str, dict[str, str]]] | List of ``(skill_name, output_to_input_mapping)`` tuples. |
async def execute( executor: Any, initial_params: dict[str, Any] ) -> Result[SkillResult, SkillError]
Execute the chain from initial_params.
| Parameter | Type | Description |
|---|---|---|
| `executor` | Any | SkillExecutorProtocol instance used to run each step. |
| `initial_params` | dict[str, Any] | Parameters passed to the first skill. |
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Result from the final step, or the first error encountered. |
SkillDefinition
Section titled “SkillDefinition”Definition of a skill's interface and behavior.
Attributes: name: Unique skill name description: What the skill does parameters_schema: JSON Schema for parameters returns_schema: JSON Schema for return value category: Skill category for organization requires_confirmation: If True, requires user approval before execution cacheable: Whether results can be cached max_retries: Maximum retry attempts on failure timeout_seconds: Execution timeout in seconds permissions: Required permissions to execute
SkillExecutedEvent
Section titled “SkillExecutedEvent”Emitted when a skill execution completes (success or failure).
Consumed by: audit, analytics, skill performance monitoring.
SkillExecutedHook
Section titled “SkillExecutedHook”Payload fired when a skill executor completes a skill call.
SkillExecutionFailedHook
Section titled “SkillExecutionFailedHook”Payload fired when a skill executor records a failed skill call.
SkillExecutor
Section titled “SkillExecutor”Executes skills with the full production lifecycle.
Handles skill resolution, permission checking, parameter validation, result caching, retry with exponential backoff, timeout enforcement, and observability logging.
def __init__( registry: SkillRegistryProtocol, *, cache: CacheBackendProtocol | None = None, permission_checker: PermissionCheckerProtocol | None = None, semaphore: asyncio.Semaphore | None = None ) -> None
Initialise the executor.
| Parameter | Type | Description |
|---|---|---|
| `registry` | SkillRegistryProtocol | SkillRegistryProtocol implementation. |
| `cache` | CacheBackendProtocol | None | Optional CacheBackendProtocol for caching deterministic results. |
| `permission_checker` | PermissionCheckerProtocol | None | Optional PermissionCheckerProtocol for access control. |
| `semaphore` | asyncio.Semaphore | None | Optional semaphore limiting concurrent executions. |
async def execute( skill_name: str, params: dict[str, Any], user_id: str | None = None, session_id: str | None = None ) -> Result[SkillResult, SkillError]
Execute a skill with full lifecycle management.
Steps: resolve → check permissions → validate → check cache → execute with retry → store cache → return.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Registered name of the skill to execute. |
| `params` | dict[str, Any] | Skill parameters. |
| `user_id` | str | None | Optional caller identity for permission checks. |
| `session_id` | str | None | Optional session context (passed through to metadata). |
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Result wrapping SkillResult on success or SkillError on failure. |
SkillLoader
Section titled “SkillLoader”Handles loading bundled files and executing skill scripts.
Features:
- Reading reference.md, forms.md, and other bundled context files
- Executing scripts (Python, Shell, JavaScript) with parameters
- Sandboxed execution with path validation
- Timeout enforcement
- Environment variable injection
def __init__( sandbox: bool = True, timeout_seconds: int = 30, max_file_size: int = 1024 * 1024 ) -> None
Initialize the loader.
| Parameter | Type | Description |
|---|---|---|
| `sandbox` | bool | Whether to enable sandboxing (default: True). |
| `timeout_seconds` | int | Script execution timeout (default: 30s). |
| `max_file_size` | int | Maximum file size for context loading (default: 1MB). |
Load a bundled context file with size limit.
Load multiple bundled context files.
Execute a skill script with parameters.
SkillPipeline
Section titled “SkillPipeline”Apply a sequence of skills as transformation stages to the same payload.
Unlike SkillChain which passes the output of one skill as the input of the next, a pipeline enriches a single mutable context dict; each stage may read from and write to that shared context.
Example
pipeline = SkillPipeline()pipeline.add_stage("normalise_text", output_key="clean")pipeline.add_stage("extract_entities", output_key="entities")result = await pipeline.execute(executor, {"raw_text": "..."})# result.unwrap().output == {"raw_text": ..., "clean": ..., "entities": ...}Initialise an empty pipeline.
Append a stage to the pipeline.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Skill to invoke at this stage. |
| `output_key` | str | None | If given, the skill's output is stored in the shared context under this key. If ``None`` the output dict is merged into the context (ignored for non-dict outputs). |
async def execute( executor: Any, initial_context: dict[str, Any] ) -> Result[SkillResult, SkillError]
Run the pipeline.
| Parameter | Type | Description |
|---|---|---|
| `executor` | Any | SkillExecutorProtocol instance. |
| `initial_context` | dict[str, Any] | Shared context passed to (and enriched by) each stage. |
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | A SkillResult whose ``output`` is the final enriched context, or the first error encountered. |
SkillRegisteredHook
Section titled “SkillRegisteredHook”Payload fired when a skill registry adds a skill definition.
SkillRegistry
Section titled “SkillRegistry”Central registry for all available skills.
Supports registration, lookup by name, category-based listing, permission-filtered listing, and OpenAI function-calling schema export.
Initialise an empty registry.
def register(skill: SkillProtocol) -> None
Register a skill.
| Parameter | Type | Description |
|---|---|---|
| `skill` | SkillProtocol | The skill to register. |
| Exception | Description |
|---|---|
| SkillAlreadyRegisteredError | If a skill with the same name is already registered. |
def register_tool(tool: ToolProtocol) -> None
Wrap tool as a ToolSkillAdapter and register it.
| Parameter | Type | Description |
|---|---|---|
| `tool` | ToolProtocol | Any object satisfying ToolProtocol. |
def get(name: str) -> SkillProtocol | None
Return the skill registered under name, or None.
| Parameter | Type | Description |
|---|---|---|
| `name` | str | Skill name to look up. |
| Type | Description |
|---|---|
| SkillProtocol | None | The skill or None if not found. |
def list_skills( category: str | None = None, permissions: list[str] | None = None ) -> list[SkillDefinition]
List registered skill definitions with optional filters.
| Parameter | Type | Description |
|---|---|---|
| `category` | str | None | Return only skills in this category. |
| `permissions` | list[str] | None | Return only skills whose required permissions are a subset of the supplied permission set. |
| Type | Description |
|---|---|
| list[SkillDefinition] | Matching skill definitions. |
Return OpenAI function-calling compatible schemas for all skills.
| Type | Description |
|---|---|
| list[dict[str, Any]] | List of schema dicts in OpenAI ``tools`` format. |
SkillResult
Section titled “SkillResult”Result of a skill execution.
Attributes: skill_name: Name of the executed skill success: Whether execution succeeded output: The output value (if successful) error: Error message (if failed) duration_ms: Time taken to execute cached: Whether result came from cache metadata: Additional execution metadata
SkillResultCache
Section titled “SkillResultCache”Two-tier result cache for skill executions.
The first tier is an in-process dict; the second tier is an optional
CacheBackendProtocol (e.g. Redis). Lookups check the in-process dict
first; on a miss they query the backend and populate the in-process dict.
| Parameter | Type | Description |
|---|---|---|
| `backend` | Optional async cache backend for cross-process caching. | |
| `ttl_seconds` | Time-to-live for backend entries in seconds. |
Initialise the cache.
| Parameter | Type | Description |
|---|---|---|
| `backend` | CacheBackendProtocol | None | Optional CacheBackendProtocol for distributed caching. |
| `ttl_seconds` | int | TTL for backend cache entries. |
async def get( skill_name: str, params: dict[str, Any] ) -> SkillResult | None
Return a cached result for the given skill invocation.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill. |
| `params` | dict[str, Any] | Parameters the skill was called with. |
| Type | Description |
|---|---|
| SkillResult | None | The cached SkillResult or ``None`` when not cached. |
async def set( skill_name: str, params: dict[str, Any], result: SkillResult ) -> None
Store a skill result in both cache tiers.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill. |
| `params` | dict[str, Any] | Parameters the skill was called with. |
| `result` | SkillResult | The SkillResult to cache. |
Remove a single entry from the local in-process cache.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill. |
| `params` | dict[str, Any] | Parameters identifying the entry to remove. |
Remove all entries from the local in-process cache.
SkillRouter
Section titled “SkillRouter”Route an input to one of several skills depending on runtime conditions.
Routes are evaluated in registration order; the first match wins. An optional fallback skill name is used when no route matches.
Example
router = SkillRouter(fallback="default_handler")router.add_route( skill_name="premium_search", condition=lambda p: p.get("tier") == "premium",)router.add_route( skill_name="basic_search", condition=lambda p: True, # catch-all)result = await router.execute(executor, {"query": "...", "tier": "free"})Initialise the router.
| Parameter | Type | Description |
|---|---|---|
| `fallback` | str | None | Skill name to use when no route matches. If ``None`` and no route matches, the execution returns an error. |
Register a route.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill to invoke if *condition* returns True. |
| `condition` | Condition | Callable receiving the input ``dict`` returning ``bool``. |
async def execute( executor: Any, params: dict[str, Any] ) -> Result[SkillResult, SkillError]
Dispatch params to the first matching skill.
| Parameter | Type | Description |
|---|---|---|
| `executor` | Any | SkillExecutorProtocol instance. |
| `params` | dict[str, Any] | Input parameters used both for condition evaluation and forwarded to the resolved skill. |
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Result from the matched skill, or a SkillRoutingError when no route matches and no fallback is configured. |
SkillSourceScanner
Section titled “SkillSourceScanner”Discovers and registers SKILL.md-based skills.
Features:
- YAML frontmatter parsing (name, description, version, author, tags)
- $ARGUMENTS placeholder substitution
- Instruction-only skills (skill body as instructions)
- Executable skills (scripts/main.py)
- Bundled context files (reference.md, forms.md, etc.)
- Configurable max depth for nested discovery
def __init__( loader: SkillLoader | None = None, max_depth: int | None = 5 ) -> None
Initialize the scanner.
| Parameter | Type | Description |
|---|---|---|
| `loader` | SkillLoader | None | Optional SkillLoader for executing scripts. |
| `max_depth` | int | None | Maximum directory depth to scan (None for unlimited). |
async def scan( registry: SkillRegistry, root: str | Path ) -> int
Scan a directory tree for SKILL.md folders and register them.
| Parameter | Type | Description |
|---|---|---|
| `registry` | SkillRegistry | The SkillRegistry to register discovered skills. |
| `root` | str | Path | Root directory to scan. |
| Type | Description |
|---|---|
| int | Number of skills successfully registered. |
SkillsConfig
Section titled “SkillsConfig”Configuration for the skills subsystem.
Controls execution defaults, caching behaviour, permission enforcement, auto-discovery settings, and which built-in skills are enabled.
Attributes:
name: Logical name used for DI registration keys.
default_timeout_seconds: Default execution timeout per skill.
max_retries: Default maximum retry attempts for skill execution.
max_concurrent_executions: Semaphore cap on concurrent executions.
cache_enabled: Whether result caching is globally enabled.
cache_ttl_seconds: Default TTL for cached skill results.
cache_backend: Which cache backend to use (in_memory, cache).
enforce_permissions: Whether permission checks are enforced.
auto_discover: Whether to auto-scan packages on boot.
scan_packages: Fully-qualified package names to scan for skills.
enable_builtin: Whether built-in skills are registered on boot.
builtin_skills: Names of built-in skills to register.
SkillsModule
Section titled “SkillsModule”Application-level façade for the skills subsystem.
Provides a configure factory that creates a pre-configured
SkillsProvider ready for registration with the application
container.
Usage
from lexigram.ai.skills import SkillsModulefrom lexigram.ai.skills.config import SkillsConfig
@module( imports=[SkillsModule.configure( SkillsConfig( enable_builtin=True, builtin_skills=["current_datetime", "math_calculate"], ) )])class AppModule(Module): passdef configure( cls, config: SkillsConfig | None = None, enable_tool_bridge: bool = False, **kwargs: Any ) -> DynamicModule
Create a SkillsModule with explicit configuration.
| Parameter | Type | Description |
|---|---|---|
| `config` | SkillsConfig | None | SkillsConfig or ``None`` to use defaults. |
| `enable_tool_bridge` | bool | Register the tool-bridge adapter so agent tool registries can invoke skills as first-class tools. Defaults to ``False``. **kwargs: Additional keyword arguments forwarded to SkillsProvider. |
| Type | Description |
|---|---|
| DynamicModule | A DynamicModule descriptor. |
def stub( cls, config: SkillsConfig | None = None ) -> DynamicModule
Create a SkillsModule suitable for unit and integration testing.
Uses in-memory or no-op skill implementations with minimal side effects. Built-in skill registration is disabled by default to keep the test container lightweight.
| Parameter | Type | Description |
|---|---|---|
| `config` | SkillsConfig | None | Optional SkillsConfig override. Uses safe test defaults when ``None``. |
| Type | Description |
|---|---|
| DynamicModule | A DynamicModule descriptor. |
SkillsProvider
Section titled “SkillsProvider”Register and bootstrap the skills subsystem.
def __init__( config: SkillsConfig | None = None, enable_tool_bridge: bool = False, **kwargs: Any ) -> None
Initialise the provider with optional configuration.
| Parameter | Type | Description |
|---|---|---|
| `config` | SkillsConfig | None | Skills configuration. Defaults to ``SkillsConfig()``. |
| `enable_tool_bridge` | bool | Register the tool-bridge adapter so agent tool registries can invoke skills as first-class tools. **kwargs: Reserved for future keyword arguments. |
async def register(container: ContainerRegistrarProtocol) -> None
Register all skills services into the container.
async def boot(container: ContainerResolverProtocol) -> None
Register built-in and auto-discovered skills into the registry.
Perform any cleanup on shutdown (no-op for the skills provider).
Health check — always healthy (in-process domain provider).
No external backend to ping.
| Parameter | Type | Description |
|---|---|---|
| `timeout` | float | Ignored for in-process providers. |
| Type | Description |
|---|---|
| HealthCheckResult | Always HEALTHY — no external backend to ping. |
TextSummarizeSkill
Section titled “TextSummarizeSkill”Return a simple extractive summary of the provided text.
This built-in provides a deterministic word-count truncation summary. For production use, replace or extend with an LLM-backed implementation.
Example output
{"summary": "First 50 words of the input...", "word_count": 200}property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the text_summarize skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Summarise text by truncating to max_words.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok result with ``summary`` and ``word_count`` keys. |
TextTranslateSkill
Section titled “TextTranslateSkill”Stub skill that echoes text with a language annotation.
Replace with an LLM or translation API backend for real translations.
Example output
{"translated": "...", "source_language": "auto", "target_language": "es"}property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the text_translate skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Return the input text unchanged with metadata (stub).
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok result with ``translated``, ``source_language``, and ``target_language`` keys. |
ToolSkillAdapter
Section titled “ToolSkillAdapter”Adapts a ``ToolProtocol`` into a ``SkillProtocol``.
Allows existing tool-based registries to participate in the skill system without modification.
def __init__(tool: ToolProtocol) -> None
Wrap tool as a skill.
| Parameter | Type | Description |
|---|---|---|
| `tool` | ToolProtocol | ToolProtocol-compliant object with name, description, parameters_schema, and execute() method. |
property definition() -> SkillDefinition
Return the adapted skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition derived from the wrapped tool. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Delegate to the wrapped tool’s execute method.
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Result wrapping SkillResult on success or SkillError on failure. |
Tools have no built-in validation — always returns empty list.
| Parameter | Type | Description |
|---|---|---|
| `params` | dict[str, Any] | Ignored. |
| Type | Description |
|---|---|
| list[str] | Empty list. |
WebSearchSkill
Section titled “WebSearchSkill”Search the web and return result snippets.
This is a stub implementation. Integrate a real search API (e.g. Brave, Bing, SerpAPI) by overriding execute.
Example output
{ "query": "AI trends 2026", "results": [], "stub": true}property definition() -> SkillDefinition
Return the skill definition.
| Type | Description |
|---|---|
| SkillDefinition | SkillDefinition for the web_search skill. |
async def execute(**kwargs: Any) -> Result[SkillResult, SkillError]
Return an empty result set (stub).
| Parameter | Type | Description |
|---|
| Type | Description |
|---|---|
| Result[SkillResult, SkillError] | Ok stub result with empty ``results`` list and ``stub=True``. |
Functions
Section titled “Functions”
def skill( name: str, description: str, *, category: str = 'general', cacheable: bool = False, max_retries: int = 0, timeout_seconds: float = 30.0, requires_confirmation: bool = False, permissions: list[str] | None = None ) -> Callable
Convert an async function into a FunctionSkill.
| Parameter | Type | Description |
|---|---|---|
| `name` | str | Unique skill name. |
| `description` | str | What the skill does. |
| `category` | str | Logical grouping for the skill. |
| `cacheable` | bool | Whether results can be cached. |
| `max_retries` | int | Retry attempts on failure (0 = no retry). |
| `timeout_seconds` | float | Execution timeout. |
| `requires_confirmation` | bool | If True, consumers may prompt for confirmation. |
| `permissions` | list[str] | None | Required permission strings. |
| Type | Description |
|---|---|
| Callable | Decorator that wraps the function as a FunctionSkill. |
skill_param
Section titled “skill_param”
def skill_param( name: str, *, type: str = 'string', description: str = '', required: bool = True, default: Any = None, enum: list[Any] | None = None, min_value: float | None = None, max_value: float | None = None, max_length: int | None = None ) -> Callable
Declare a parameter on a skill function.
Must be applied before @skill. Multiple @skill_param decorators
are accumulated in declaration order.
| Parameter | Type | Description |
|---|---|---|
| `name` | str | Parameter name. |
| `type` | str | JSON Schema type (e.g. ``"string"``, ``"integer"``, ``"boolean"``). |
| `description` | str | Human-readable description. |
| `required` | bool | Whether the parameter is required. |
| `default` | Any | Default value when not supplied. |
| `enum` | list[Any] | None | Restricted set of allowed values. |
| `min_value` | float | None | Numeric minimum. |
| `max_value` | float | None | Numeric maximum. |
| `max_length` | int | None | String maximum length. |
| Type | Description |
|---|---|
| Callable | Decorator that annotates the function with parameter metadata. |
validate_non_empty_string
Section titled “validate_non_empty_string”
Validate that value is a non-empty string.
| Parameter | Type | Description |
|---|---|---|
| `value` | Any | Value to check. |
| `name` | str | Parameter name for error messages. |
| Type | Description |
|---|---|
| list[str] | List of validation errors. |
validate_params
Section titled “validate_params”
Validate params against a JSON Schema object descriptor.
Supports: required fields, type checking, enum, minimum/maximum, minLength/maxLength, and nested object/array types.
| Parameter | Type | Description |
|---|---|---|
| `params` | dict[str, Any] | The parameter dict supplied by the caller. |
| `schema` | dict[str, Any] | JSON Schema ``object`` definition from SkillDefinition. |
| Type | Description |
|---|---|
| list[str] | List of validation error messages. Empty list means valid. |
validate_positive_int
Section titled “validate_positive_int”
Validate that value is a positive integer.
| Parameter | Type | Description |
|---|---|---|
| `value` | Any | Value to check. |
| `name` | str | Parameter name for error messages. |
| Type | Description |
|---|---|
| list[str] | List of validation errors. |
validate_range
Section titled “validate_range”
def validate_range( value: Any, name: str, *, minimum: float | None = None, maximum: float | None = None ) -> list[str]
Validate that value falls within a numeric range.
| Parameter | Type | Description |
|---|---|---|
| `value` | Any | Value to check. |
| `name` | str | Parameter name for error messages. |
| `minimum` | float | None | Inclusive lower bound. |
| `maximum` | float | None | Inclusive upper bound. |
| Type | Description |
|---|---|
| list[str] | List of validation errors. |
Exceptions
Section titled “Exceptions”SkillAlreadyRegisteredError
Section titled “SkillAlreadyRegisteredError”Raised when a skill is registered under a name that already exists.
Initialise with the duplicate skill name.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill that was already registered. |
SkillError
Section titled “SkillError”Base for skill execution errors.
Extended in lexigram-ai-skills with specific failures like skill not found, execution failure, parameter validation, etc.
SkillExecutionError
Section titled “SkillExecutionError”Raised when a skill execution fails after all retry attempts.
Initialise with an error message and optional cause.
| Parameter | Type | Description |
|---|---|---|
| `message` | str | Human-readable error description. |
| `cause` | Exception | None | The underlying exception, if any. |
| `skill_name` | str | None | Name of the skill that failed (optional). |
SkillNotFoundError
Section titled “SkillNotFoundError”Raised when a requested skill is not registered.
Initialise with the missing skill name.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill that was not found. |
SkillPermissionDeniedError
Section titled “SkillPermissionDeniedError”Raised when the caller lacks required permissions for a skill.
Initialise with permission details.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill that requires permissions. |
| `required` | list[str] | Required permission strings. |
SkillRoutingError
Section titled “SkillRoutingError”Raised when a SkillRouter finds no matching route.
Initialise with an optional detail message.
| Parameter | Type | Description |
|---|---|---|
| `message` | str | Human-readable description of the routing failure. |
SkillTimeoutError
Section titled “SkillTimeoutError”Raised when skill execution exceeds the configured timeout.
Initialise with timeout context.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill that timed out. |
| `timeout_seconds` | float | The timeout that was exceeded. |
SkillValidationError
Section titled “SkillValidationError”Raised when skill parameter validation fails.
Initialise with validation error details.
| Parameter | Type | Description |
|---|---|---|
| `skill_name` | str | Name of the skill that failed validation. |
| `errors` | list[str] | List of human-readable validation error messages. |