Skip to Content
AI EmployeesCreating Skills

Creating Skills

When does making a skill yourself make sense?

The autonomous skill system handles most things on its own, but building a skill directly is worth it when:

  • You need exact repeatability: the same procedure runs identically every time it’s triggered.
  • You’re turning know-how into an asset: formalise training material or recurring processes as a skill.

Outside these cases, you don’t need to create skills at all; your AI employee finds and uses the right ones automatically.

Skills you create are yours alone. There’s no way to publish them to other users or share them by link (if you belong to an organization, you can share them to it). The only skills available to everyone are the official skills UpServe supports; find them in Installing Skills & Templates.


Try it first, then save what worked

UpServe’s recommended flow for creating a skill:

[1] Instruct the employee "Scrape this site's prices every day and tabulate them" │ ▼ [2] Employee completes the task with whatever tools fit (browser / file write / code execution, freely combined) │ ▼ [3] Happy with the result? Ask to save it as a skill "Save the workflow you just ran as a skill" │ ▼ [4] The employee automatically: · collects the execution code and files · writes an AgentSkills-compatible SKILL.md (including required fields like a summary and when to use it) · auto-normalises spec violations (spaces, uppercase, etc.) · creates a draft skill and posts a card in the chat │ ▼ [5] Open the card whenever you like to review and save

Why this works well:

  • Only workflows that actually worked get saved: you save a flow only after seeing it succeed, so you never end up with a skill that turns out not to run.
  • The employee handles the messy parts: you just say “save the workflow you just ran as a skill”. You don’t need to know what files are created or how they’re organised.
  • Refine it through chat until you’re happy: “show the results as a table”, “make the name shorter”, “handle this edge case too”. Keep asking in plain conversation.
  • You can edit it later at any time: making a skill isn’t a one-shot decision. Come back and ask the employee to tweak, extend, or fix specific parts whenever you want.

If the employee can’t fill in required information (like a summary or “when should this trigger”), no draft is created at all. It’s told what’s missing and fills that in before trying again. So by the time a card shows up in chat, everything needed for review is already there.


Phrases you can use with the employee

SituationWhat to say
Save the workflow you just ran“Save the workflow you just ran as a skill”
Save only one step“Make a skill out of just the price extraction part”
Specify when the skill should be used“Make a skill that fires when the user says ‘check competitor prices’”
Pick the name yourself“Name it competitor-price-tracker and make it a skill”

Reviewing the draft and saving

Creating a skill doesn’t pause the employee. The moment it builds a draft, a card appears in the chat and the employee moves straight on to whatever’s next. Open the card whenever you’re ready (web, iOS, and Android all offer a review screen). It lets you check and edit the skill name, description, category, the body (SKILL.md), and the file list before publishing. On web, the screen is organized into three steps: Basic Info → Content → Files.

  • Step 1 · Basic Info: fields for name, description, category, and type, plus a read-only summary of the summary, when-to-use phrases, required connections, and (for executable skills) the entry script the employee already filled into SKILL.md. To change these, edit the settings block at the top of SKILL.md in Step 2.
  • Step 2 · Content: edit the SKILL.md body directly.
  • Step 3 · Files: review bundled files and choose any to exclude.

Saving is always something you do yourself; the employee can’t save on your behalf. Once you’re happy, click Save. The skill is stored as a private skill in your library: only your own employees can install and run it, and other users can’t find it.

If a bundled file looks like it contains personal information or sensitive data, the review screen flags it with a warning. You can uncheck a flagged file to exclude it from the skill. Excluded files are actually deleted once you publish. You can also run Validate before publishing to check whether the draft would pass, without committing to it yet.

Cancelling or closing the save dialog discards the draft; otherwise it stays put until you save or discard it.


Reviewing improvement proposals

When your employee hits a defect while running one of your skills and reports it, the report is filed as an improvement proposal. Multiple reports describing the same underlying issue are deduplicated into a single proposal.

Where to find them: open your skill from the Skills tab. The skill detail page shows an Improvement Proposals section further down. It is visible only to the skill’s author. Defect reports on official skills don’t appear here; they go to the UpServe team for review.

For each proposal you have four options:

ActionMeaning
Mark as reviewedOnly marks the proposal as reviewed. It does not change the skill content and does not lead to a separate edit screen afterward. Use it when you want to close the proposal without shipping a fix.
Edit & publishEdit the skill content right inside the proposal card and publish it as a new version. If you actually want to ship the fix, use this instead of Mark as reviewed.
RejectFor proposals that aren’t valid. You can leave an optional note explaining why.
Leave pendingNo action taken; stays as a pending proposal until you decide.

Automatic patches the employee applies to skills you have imported are handled separately and do not appear on this page.


Uploading a new version from a zip

If you’ve edited one of your skills on your own computer, you can upload the edited zip as a new version of the same skill. No second skill is created, and the skill keeps its history and name.

  1. Open the skill from the Skills tab to go to its detail page.
  2. Click the upload icon (Update from zip) next to the title.
  3. Pick your edited zip file and upload it.

After the upload, you’ll see one of these:

  • The content changed: an “uploaded as a new version” message, plus the new version number and file count.
  • The content matches the current version: a message saying nothing changed, and the version number stays the same. If you expected a change, check that you picked the right file.
  • The name (name) in the zip’s SKILL.md differs from this skill: the skill’s unique name stays as it is, and a warning asks you to confirm you picked the skill you meant to update.
  • The upload contains secrets such as API keys, or unsafe content: the upload is rejected and the current version stays in place.

Which skills show this button: only active skills you own (created or imported). The button doesn’t appear for:

  • Archived skills: click Restore first, then upload.
  • Drafts you haven’t saved yet, and official UpServe skills.

To import a brand-new skill from a zip, use the Import zip button in the Skills tab. Uploading a new version is currently available on the web only.


Deleting a skill

You can delete any skill you created at any time (official skills can’t be deleted). Open the skill’s card, click Delete, and confirm.

One of two things happens:

  • A skill that has never run: it’s deleted permanently. This can’t be undone.
  • A skill that has run at least once, been copied and edited, or used by a team: instead of erasing it, UpServe archives it. This protects traces the skill already left behind elsewhere (work files your employee produced with it, things it remembered, conversation history) from suddenly pointing at something that no longer exists.

What changes once a skill is archived?

  • Its card stays in your list with an Archived badge, the same on web, iOS, and Android.
  • The confirmation you see after deleting correctly says “archived,” not “deleted.”
  • Your own employees stop using it. From their next run onward it drops out of their skill list, and you can’t attach it to a new employee either.
  • If you change your mind, click Restore on the skill’s detail page to bring it back as a private skill you can attach to your employees again.

Import from Official skills

Instead of building from scratch, you can install a skill UpServe supports from Official skills , under the Skills tab. Click Import on the skill detail page and it’s added to your skill library as a reference to the original, ready to attach to your employees. When you refine it through chat, your own version is created at that point.

For the full installation walkthrough, see Installing Skills & Templates.


Advanced

The material below is not required for everyday use. Refer to it only when you need to inspect skill internals, hand-edit a skill imported from outside, or exchange skills with other clients.

What an employee-built skill looks like

Directory layout

my-skill/ ├── SKILL.md # Required: frontmatter + body ├── scripts/ # Optional: executable code │ ├── main.py │ └── requirements.txt ├── references/ # Optional: docs the employee loads on demand │ └── api-spec.md └── assets/ # Optional: templates, schemas, lookup tables └── output-template.md

SKILL.md frontmatter

The standard requires only two fields.

--- name: my-skill # kebab-case, 1-64 chars, must match directory name description: Use this skill when ... # ≤1024 chars, imperative ---

Optional standard fields:

FieldPurpose
licenseLicense name or reference to a bundled LICENSE file
compatibilityEnvironment requirements (≤500 chars), e.g. “Requires Python 3.14+ and uv”
allowed-toolsPre-approved tools the skill may use (experimental)
metadataContainer for client-specific extensions

UpServe extensions live under metadata:

UpServe-specific fields (connection detail bindings, action menus, when-to-use hints) go under the standard metadata: namespace. This keeps your SKILL.md valid for any other compliant client.

--- name: notion description: Search, read, and write Notion pages and databases via OAuth. Use when the user asks to search Notion, read a page, query a database, or reference a Notion URL. metadata: display_name: Notion Integration when_to_use: - User asks to search their Notion workspace. - User references a Notion URL or page id. requires: - oauth: notion # → ${SKILL_DIR}/.env will receive NOTION_TOKEN entry_script: scripts/main.py actions: - search: "Search pages and databases by title/content" - read: "Read a page's content" files: - scripts/main.py load_before_use: true --- # Notion Integration ## When to use this skill ...

Progressive disclosure: the token-saving model

Skills load in three tiers.

TierWhen loadedContentToken cost
1. CatalogEvery turnname + description only~50-100 tokens per skill
2. BodyOnce on first skill execution (re-delivered after conversation history is compacted)Full SKILL.md body< 5,000 tokens recommended
3. ResourcesWhen the body references a fileIndividual scripts / references / assetsVariable

Implication: with 20 skills installed, your employee’s behaviour instructions only carry 2-3KB. Only skills the employee actually uses expand to their full body.

[Loaded every turn] ~50-100 tokens/skill ┌─────────────────────────┐ │ Tier 1 · Catalog │ │ name + description │ └─────────────────────────┘ │ │ Employee decides "use this skill" ▼ (first skill execution) ┌─────────────────────────┐ │ Tier 2 · Body │ < 5,000 tokens │ Full SKILL.md │ └─────────────────────────┘ │ │ Body says "look at scripts/main.py" ▼ (per individual file read) ┌─────────────────────────┐ │ Tier 3 · Resources │ variable │ scripts / refs / assets│ └─────────────────────────┘

Connection detail injection

When a skill needs to call an external service, declare it in metadata.requires. At skill-execution time, UpServe writes the connection details into ${SKILL_DIR}/.env automatically. When the employee packages a skill, it auto-detects which connection details the work used and fills this field for you.

NotationInjected as
oauth: <provider><PROVIDER>_TOKEN=... in ${SKILL_DIR}/.env
vault: <NAME><NAME>=... (a connection detail saved to the employee)
scope: <scope>UPSERVE_AGENT_TOKEN + UPSERVE_API_BASE (UpServe internal API)

Scripts source the env with . ./.env && python3 scripts/main.py .... The .env file is scrubbed at the end of every turn (each time the employee finishes a response), and is automatically rewritten the next time the skill runs, so you don’t need to manage this yourself.

Script design principles the employee follows

When the employee authors skill scripts, it defaults to these nine principles. You don’t write them yourself, but you can use this checklist when reviewing a packaged skill.

PrincipleWhy
Non-interactiveEmployees can’t answer interactive TTY input. Accept all input via flags or env vars
Expose --helpThe primary way an employee learns your interface
Structured stdoutJSON / CSV / TSV, easy to parse
stderr for diagnosticsKeep data and progress separate
Helpful error messages“What went wrong / what was expected / what to try”
Idempotent“create-if-not-exists” beats “create-and-fail”, since employees retry
Distinct exit codesPer-failure-mode (404 / auth / validation)
Predictable output sizeDefault cap + --offset / --limit for pagination
PEP 723 inline deps (Python)uv run scripts/x.py runs anywhere with one command

If something needs fixing, just ask in chat: “add a --limit flag to the script”, “include suggested next actions in the error message”. See the AgentSkills script guide  for full detail.

Lenient normalisation

The standard is strict, but UpServe loads leniently and surfaces warnings instead of rejecting. Whether you import an external zip or have the employee author SKILL.md, minor spec violations are auto-corrected.

ViolationHandling
name contains uppercase / spaces / underscoresAuto-normalised (Notion Integration → notion-integration); original preserved as metadata.display_name
name exceeds 64 charsWarning + truncate
Unquoted colons in YAMLLenient parse retry
description missingRejected (required: without it the employee can’t tell when to use the skill)
description exceeds 1024 charsRejected

Import skills from other clients via zip

You can import skills built in Claude Code, Cursor, Goose, and any other compatible client as standard zips.

Import a skill from another client

curl -X POST https://api.upserve.app/api/skills/import \ -H "Authorization: Bearer $UPSERVE_TOKEN" \ -F "file=@my-skill.zip"

Safety limits: 200 files per zip, 5MB per file, 20MB total package size. Binary files such as images, audio, and fonts are preserved byte-for-byte.

Update an existing skill to a new version

Include the id of the skill you want to update in the import request, and the upload becomes a new version of that skill instead of a new skill. This works for both zip uploads and GitHub imports. The target must be an active skill you own; requests for archived or official skills are rejected.

# zip curl -X POST https://api.upserve.app/api/skills/import \ -H "Authorization: Bearer $UPSERVE_TOKEN" \ -F "file=@my-skill.zip" \ -F "target_skill_id=<skill-id>" # GitHub curl -X POST https://api.upserve.app/api/skills/import-github \ -H "Authorization: Bearer $UPSERVE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"url": "owner/repo", "target_skill_id": "<skill-id>"}'

In the response, updated_existing tells you whether an existing skill was updated, content_changed whether the content actually changed, and content_version the version number after the update. If the content is identical, content_changed is false and the version doesn’t go up.

Learn more