Use this file to discover all available pages before exploring further.
In addition to the built-in Skills, you can create custom Skills to extend Kubiya’s capabilities with organization-specific integrations, tools, or workflows.
Create a Python file (e.g., agno_impl.py) that implements your Skill’s functionality.Example Implementation:
# agno_impl.pyfrom agno.tools import Toolkitclass MyCustomSkill(Toolkit): """Custom skill for organization-specific operations""" def __init__(self, api_key: str, timeout: int = 30, **kwargs): """Initialize the skill with configuration Args: api_key: API key for external service (from configuration) timeout: Request timeout in seconds (from configuration) **kwargs: Additional configuration options """ super().__init__(name="my-custom-skill") self.api_key = api_key self.timeout = timeout def send_notification(self, message: str, recipient: str) -> str: """Send a notification via the external service Args: message: The notification message to send recipient: The recipient identifier Returns: Status message indicating success or failure """ # Implementation here # Use self.api_key to authenticate with external service return f"Notification sent to {recipient}: {message}" def query_data(self, query: str) -> dict: """Query data from the external service Args: query: The query string Returns: Dictionary containing query results """ # Implementation here return {"results": [], "count": 0}
Important: Custom Skills AvailabilityCustom skills must be available in both locations:
Worker Process: The worker that runs the agent/team must have access to the skill files in .kubiya/skills/
Control Plane API Server: The control plane must also have the skill files to register and manage the skill
Ensure you deploy your custom skills to both the worker nodes and the control plane server, or use a shared filesystem/volume mounted at both locations.
Custom Skills are automatically discovered when:
Control Plane starts: Skills in .kubiya/skills/ are scanned at startup
Worker initializes: Skills are loaded when a worker starts
Dynamic loading: Controlled by KUBIYA_ENABLE_DYNAMIC_SKILLS environment variable (default: true)
Once loaded, custom Skills appear in the Skills dashboard and CLI alongside built-in Skills:UI:
Navigate to Skills > New Skill
Select your custom Skill type from the dropdown
Configure the Skill instance
Assign to agents, teams, or environments
CLI:
# List all Skills (including custom)kubiya skill definitions# Create an instance of your custom Skillkubiya skill create --name "Prod Slack" --type slack-integration --config-json '{"default_channel":"#alerts","timeout":60}'# Assign to an agentkubiya skill associate agent <agent-id> <skill-id>
from agno.tools import Toolkitfrom github import Githubimport osclass GitHubSkill(Toolkit): """GitHub integration skill""" def __init__(self, default_org: str, allowed_repos: list = None, timeout: int = 30, **kwargs): super().__init__(name="github-helper") self.gh = Github(os.getenv("GITHUB_TOKEN"), timeout=timeout) self.default_org = default_org self.allowed_repos = allowed_repos or [] def list_repositories(self, org: str = None) -> list: """List repositories in an organization Args: org: Organization name (uses default if not specified) Returns: List of repository names """ org_name = org or self.default_org org_obj = self.gh.get_organization(org_name) repos = org_obj.get_repos() if self.allowed_repos: # Filter to allowed repos return [r.name for r in repos if r.name in self.allowed_repos] return [r.name for r in repos] def create_issue(self, repo: str, title: str, body: str) -> dict: """Create an issue in a repository Args: repo: Repository name title: Issue title body: Issue description Returns: Dictionary with issue details """ if self.allowed_repos and repo not in self.allowed_repos: raise PermissionError(f"Access to repository '{repo}' not allowed") full_repo = f"{self.default_org}/{repo}" repository = self.gh.get_repo(full_repo) issue = repository.create_issue(title=title, body=body) return { "number": issue.number, "url": issue.html_url, "state": issue.state }