Build Your First Skill in 30 Lines
A skill is the simplest way to extend your Life Savor agent. It's a program that reads a JSON request from stdin, does something useful, and writes a JSON response to stdout. That's it.
Let's build one.
What We're Building
A "word count" skill. You give it text, it tells you how many words are in it. Simple, but it demonstrates the full skill lifecycle — manifest, implementation, and installation.
The Manifest
Every skill needs a skill.json that tells the agent what it is and how to run it:
{
"skill_id": "word-count",
"name": "Word Count",
"version": "1.0.0",
"description": "Counts the number of words in a given text input",
"execution_tier": 1,
"entrypoint": {
"type": "node",
"command": "node",
"args": ["index.js"]
}
}
The key fields:
- skill_id — unique identifier (lowercase, hyphens only)
- execution_tier — resource limits (1 is the most restricted, 3 is the most permissive)
- entrypoint — how the agent launches your skill. This one runs
node index.js
The Implementation
Here's the complete skill in Node.js:
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });
rl.on('line', (line) => {
const request = JSON.parse(line);
let result;
if (request.operation === 'count') {
const text = request.payload.text || '';
const words = text.trim().split(/\s+/).filter(Boolean);
result = {
status: 'ok',
result: { word_count: words.length }
};
} else {
result = {
status: 'failed',
error: `Unknown operation: ${request.operation}`
};
}
process.stdout.write(JSON.stringify(result) + '\n');
});
That's 20 lines of actual logic. The agent sends a JSON object with an operation and payload, and your skill responds with a status and result.
The Same Thing in Python
import json
import sys
for line in sys.stdin:
request = json.loads(line.strip())
if request["operation"] == "count":
text = request.get("payload", {}).get("text", "")
words = text.split()
result = {"status": "ok", "result": {"word_count": len(words)}}
else:
result = {"status": "failed", "error": f"Unknown operation: {request['operation']}"}
print(json.dumps(result), flush=True)
Same protocol, different language. The agent doesn't care — it just speaks JSON over stdio.
Install and Test
Put your skill.json and index.js (or skill.py) in a directory, then install it locally:
lsai-cli component install ./word-count
Check that it registered:
lsai-cli component list
Your agent can now invoke the word-count skill whenever it needs to count words in a document.
Adding Configuration
What if your skill needs an API key or user preferences? Add a config_schema to your manifest:
{
"config_schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"include_characters": {
"type": "boolean",
"title": "Include Character Count",
"description": "Also return the character count alongside word count",
"default": false
}
}
}
}
The platform renders a setup wizard automatically from your schema — no custom UI needed. Users configure your skill through a clean, consistent interface across web, iOS, and desktop.
Adding Setup Steps
For skills that need credentials or multi-step configuration, define setup_steps:
{
"setup_steps": [
{
"step_id": "preferences",
"title": "Preferences",
"description": "Configure how the word counter behaves",
"fields": ["include_characters"]
}
]
}
Each step groups related fields into a focused screen. You can add a validation_command to any step if you need server-side validation (like testing an API key before proceeding).
What Happens at Runtime
When the agent invokes your skill:
- It spawns your process in a sandbox (cleared environment, restricted paths)
- Writes the JSON request to your stdin
- Waits up to 30 seconds for a response on stdout
- Caps output at 1MB
- Terminates the process if it exceeds limits
Your skill doesn't need to manage connections, authentication, or lifecycle — the agent handles all of that.
Next Steps
This was the simplest possible skill. From here you can:
- Add multiple operations (your skill can handle many different tools)
- Use the MCP protocol instead of raw JSON for richer tool definitions
- Access system components (like the knowledge store) via the bridge
- Publish to the marketplace for other users to install
In the next post, we'll look at the full SDK and how to build more complex components.