Agent Skills
Install SKILL.md skill packages for your tenant, have them vetted before they run, and attach them to managed agents that load each one only when it is relevant.
- Install a skill and read its scan
- Approve or reject a version waiting for review
- Trust a publisher's signing key
- Attach skills to an agent
- Explain what an agent sees before and after it loads a skill
A skill is a folder of instructions an agent can pick up when a task needs it, in the open Agent Skills format: a SKILL.md file with a short YAML header, and optional references/, assets/ and scripts/ files beside it.
---
name: refund-triage
description: Decide whether a refund request is in policy. Use for refund or chargeback tickets.
license: Apache-2.0
allowed-tools: servicenow/get_order
---
# Refund triage
Check the order, then read references/policy.md before answering.How an agent uses a skill
Skills load in stages, so a long skill costs nothing until it is needed:
- The agent's prompt lists each attached skill by name and description only.
- When the model decides a skill is relevant it calls
skill_load, which returns the instructions inSKILL.mdand the list of the skill's other files. - If those instructions point to a file, the model calls
skill_readfor that file.
Each load is recorded in the audit log as agent.skill.load, with the skill, the version's digest and the file. The text itself is not copied into the log. Skill text reaches the model as a tool result, fenced like any other tool result.
A skill gives the agent no new permissions. Its allowed-tools list is a declaration: reviewers see it, and attaching checks it against the agent's tools. The agent still calls tools with its own tool list and Cedar policies.
Install a skill
Send the package's files as text to POST /api/skills (needs governance.write):
{"files": {"SKILL.md": "---\nname: refund-triage\n...", "references/policy.md": "..."},
"signature": {"kid": "acme-2026", "signature": "<base64 Ed25519>"},
"source": "git@github.com:acme/skills.git#v1.2"}To check a package without installing it, send the same body to POST /api/skills/scan. Skills are stored per tenant: a skill installed in one tenant is not visible in another.
What is checked before a skill runs
| Check | What it looks for | Result |
|---|---|---|
| Format | The spec's header fields and limits; text files only; plain relative paths | Refused |
| Hidden text | Invisible characters inside words, bidirectional overrides | Critical: blocked |
| Remote execution | A download or decoded blob piped into a shell | Critical: blocked |
| Prompt injection | "Ignore previous instructions" and the injection phrasings Liyagent already screens tools for | High: held for review |
| Secrets and exfiltration | Credential files (.env, SSH keys, cloud credentials), request-capture hosts, URLs filled from variables | High: held for review |
| Memory tampering, encoded blobs, scripts | Asks to rewrite memory or instructions; long base64; executable files (never run by Liyagent) | Shown to the reviewer |
| Signature | Ed25519 over the package digest by a key the tenant trusts | A bad or untrusted signature blocks |
Settings › skills_review decides who approves:
warn(default): a version with no critical or high finding and no bad signature is approved on install (skill.approvedbyauto-review). A version with a high finding waits for an administrator.enforce: every version waits for an administrator, a version not signed by a trusted key is blocked, and attaching a skill whoseallowed-toolsthe agent lacks is refused.
Installing a new version never changes what agents run. The approved version stays in use until the new one is approved.
Review a waiting version
GET /api/skills/{name}shows the current version and the candidate, with the scan findings, signature status, manifest and files.POST /api/skills/{name}/approvewith{"digest": "<the candidate's digest>", "reason": "..."}approves it. If the candidate changed since you read it, the digest no longer matches and the approval is refused. A blocked version cannot be approved.POST /api/skills/{name}/rejectrejects it.DELETE /api/skills/{name}removes the skill.
Every install, approval, rejection and removal is in the audit log (skill.*), with the scan verdict, findings, signature status and declared tools.
Trust a publisher's key
POST /api/skills-trust with {"kid": "acme-2026", "public_key": "<base64 raw Ed25519 public key>", "label": "Acme platform team"}. The publisher signs liyagent-skill-v1: followed by the package digest, the SHA-256 shown by the scan. DELETE /api/skills-trust/{kid} stops trusting a key.
Attach skills to an agent
PUT /api/agents/{agent}/skills with {"skills": ["refund-triage"]} (needs agents.update and Cedar update on the agent). Only skills with an approved version can be attached. The answer lists gaps: tools a skill declares that the agent does not have. Under warn the gaps are reported and audited. Under enforce the attach is refused. GET /api/agents/{agent}/skills lists what is attached and active.
Agents with no skills attached are unchanged: no skill tools, no skill text in the prompt. skills_enabled turns the feature off everywhere.