Agent & Skills
Skills, permission modes, the agent workspace, browser automation, multi-step tasks, and the audit log.
Overview
Luna's agent layer is built on an OpenClaw-style permission model. Every action Luna can take — searching the web, launching an app, reading a file — is a registered tool. Tools are grouped into skills and each has an individually-configurable permission mode.
The Agent page in the Luna sidebar shows all installed skills, current permissions, workspace files, browser status, active tasks, and the live audit stream.
Skills
A skill is a package that extends Luna with new capabilities. Skills live in two locations:
skills/— skills shipped with the repo (version-controlled).data/workspace/skills/— user-created or agent-created skills (gitignored).
Each skill directory contains two files:
| File | Purpose |
|---|---|
skill.json | Machine-readable manifest — name, description, version, and registered commands. |
SKILL.md | Human-readable description. Luna reads this to understand what the skill does and when to use it. |
List all installed skills via the API:
curl http://localhost:8899/api/agent/skillsCreate a skill
Skills follow a simple two-file structure. Here is a minimal example:
{
"name": "my-skill",
"version": "1.0.0",
"description": "A short description of what this skill does.",
"commands": [
{
"name": "do_thing",
"description": "Does the thing with the given input.",
"parameters": {
"input": { "type": "string", "description": "What to process." }
}
}
]
}# My Skill
This skill enables Luna to do the thing.
## When to use
Call `do_thing` when the user asks to process something.
## Examples
- "Do the thing with this text"
- "Can you process X for me?"Commands declared in skill.json must be registered inbackend/services/tool_registry.py with matching names and handler functions. The manifest describes the schema; the registry provides the implementation.
After adding a skill, restart the backend. Luna will load it on startup and make it available to the LLM as a tool call option.
Permission modes
Every registered tool has a permission mode. Modes are stored per-user indata/permissions.json and are configurable from the Agent page in the UI.
| Mode | Behaviour | Suitable for |
|---|---|---|
allow | Tool executes immediately without any user prompt. | Safe, idempotent tools — web search, reading files, weather lookup. |
confirm | Luna pauses and shows a confirmation banner in the UI. You must approve or reject before execution continues. | Destructive or irreversible actions — writing files, launching apps, Spotify control. |
block | The tool call is silently dropped. Luna is told the tool is unavailable. | Tools you want to disable entirely — e.g. camera, browser automation. |
Update a tool's permission via the API:
curl -X POST http://localhost:8899/api/agent/permissions/web_search -H "Content-Type: application/json" -d '{"mode": "allow"}'Workspace
Agent-created files are restricted to data/workspace/. This acts as a sandbox — Luna can read and write files within the workspace but cannot access the rest of your filesystem without explicit OS-level permission escalation.
Read and write workspace files via the API:
# List workspace contents
GET /api/agent/workspace
# Read a file
GET /api/agent/workspace/read?path=notes/ideas.md
# Write a file
POST /api/agent/workspace/write
{"path": "notes/ideas.md", "content": "..."}data/workspace/ is gitignored. Files created by Luna live here and are never committed to the repository.
Browser automation
Luna's default browser layer uses HTTP requests via httpx — it can fetch and parse public web pages without a real browser. This is fast and lightweight.
For pages that require JavaScript rendering, Luna supports optional Playwrightintegration. Install it separately if needed:
pip install playwright
playwright install chromiumBrowser automation routes:
# Check browser status
GET /api/agent/browser/status
# Open a URL (Playwright required for JS-rendered pages)
POST /api/agent/browser/open
{"url": "https://example.com"}
# Read page content
POST /api/agent/browser/read
{"url": "https://example.com"}Agent tasks
Luna supports multi-step agent tasks — goals that require multiple tool calls planned and executed over time. Tasks are created, planned, and tracked in the database.
# List all tasks
GET /api/agent/tasks
# Create a new task
POST /api/agent/tasks
{"title": "Research competitors", "description": "..."}From the chat UI, tell Luna to start a task:
"Start a research task: find the top 5 competitors to Notion and summarise their pricing."Luna will break this into steps, plan an execution sequence, and work through it — asking for confirmation at each confirm-mode tool call.
Audit log
Every tool call Luna executes is appended to data/audit.log with a timestamp, tool name, input parameters, and outcome. This gives you full visibility into what Luna has done.
# Stream the live audit log via the API
GET /api/agent/auditThe Agent page in the sidebar shows the audit stream in real time. Each entry shows the tool, whether it was auto-allowed or user-confirmed, and the result summary.
Open data/audit.log directly to review the full history. Entries are newline-delimited JSON objects, easy to parse or grep.