-
Notifications
You must be signed in to change notification settings - Fork 0
Creating Executable Skills
Executable Skills are skills that can run Python code, used to expand the actions that Kodo has access to. Skills can either be static or dynamic, this means that their associated documentation is the same, or can be generated at runtime.
Executable Skills must define the actions associated with them as well as their entry file. The entry file is the Python file that is executed when the action is called.
Your Python code will run inside a Python Virtual Environment, and external dependencies will be identified automatically through the imports, but it is recommended that you also define your dependencies under the dependencies key of your skill definition.
The folder structure of a static skill with actions looks like this
Static skill with actions:
skills/my-tool/
skill.json
actor_skill.md
planner_skill.md
skill.py
planner_skill.md and actor_skill.md contain the documentation necessary on how to use the skill and how to call your action and what the action does. Allowing the LLM to know what actions are defined with your skill and what arguments are needed.
When your action is called, it is passed to the skill orchestrator, which will find and install the required dependencies using the dependencies key in your skill.json and the Python imports your app makes.
After dependencies are installed, the LLM's action JSON is passed as an argument.
Skills will communicate with Kodo through stdout and stderr. If your skill encounters errors in execution, they should be placed inside stderr, and the result of your skill will be placed inside stdout.
Skills are blocking and if the user wishes, it can be set under a specific timeout. If your skill does not finish its execution under the user's specified timeout, it is killed automatically and the LLM is notified.
{
"name": "my-skill",
"description": "Short description shown to the skill installation model when deciding what to load",
"actions": ["action_name"],
"entry": "skill.py",
"enabled": true,
}You can define multiple actions.
import sys, json
if __name__ == "__main__":
args = json.loads(sys.argv[1])Here is an example of how a skill will be called, this example is based on the clipboard skill, as it has multiple associated actions. clipboard_read and clipboard_write
Below is the skill.json associated with the app. Since the Clipboard skill has no associated dependencies, there is no dependencies key, dependencies is a list of all the Pip packages your skill will need to run. Your required dependencies will be installed before the skill runs.
{
"name": "clipboard",
"description": "Read from and write text to the Windows clipboard.",
"actions": ["clipboard_read", "clipboard_write"],
"entry": "skill.py"
}The Skill Orchestrator will then register your actions with the specified entry file. When the LLM calls the action, it will be routed to the entry.py file
{"action": "clipboard_write", "text": "Hello, World!"}The Skill orchestrator will run your specified entry file, with the JSON above as your first argument, allowing you to route internally based on the action.
Dynamic Skills are fundamentally the same as static skills, with the only difference being a lack of a planner_skill.md file and an actor_skill.md file.
The entry point runs with a --generate flag at load time and produces documentation as a JSON string rather than reading from static files. The skill generates its own context based on the current system state, or whatever you would like to do to modify the documentation before providing Kodo and the LLM with it.
Your skill must return the documentation in stdout as JSON, which will be picked up and parsed by the skill orchestrator.
Basically, print out the JSON documentation, yes, the
print()print. That is how skills communicate as your skill runs in a separate process, such that it crashes it does not affect Kodo.
The --generate output must look like this:
{
"planner": "## My Skill\nPlanner documentation here...",
"actor": "## My Skill\nActor documentation here..."
}launch-windows-app is the example here. It scans the Start Menu at runtime to find every installed Windows app, then injects the real list of launchable apps into both the planner and actor prompts. The model always sees your actual installed apps rather than a hardcoded list.
Your Skill Definition must look like this
{
"name": "my-skill",
"description": "Short description shown to the skill installation model when deciding what to load",
"actions": ["action_name"],
"entry": "skill.py",
"enabled": true,
"dynamic_context": true,
"generated_for_actor": true,
"generated_for_planner": true
}The dynamic_context field tell Kodo's Skill Orchestrator that your skill generates it's prompts at runtime, while the generated_for_actor and generated_for_planner field define who it is generated for.
Here is the folder structure
Dynamic skill:
skills/my-dynamic-tool/
skill.json
skill.py <- must handle --generate
You can include base actor and planner files to extend at runtime, Kodo will not pick them up as it is told to use the --generate flag to get the required prompts.