Custom skills

Custom skills are reusable playbooks: a short description (when to use it) plus a markdown body (the steps). The agent sees every visible skill's name + description and loads the body only when relevant.

Slash-invoke (force a skill)

Type /slug in chat (or pass skill="slug" on POST /runs / reply) to force that playbook. The agent must load it via the Skill tool before doing anything else. The composer picker lists:

  • Platform commands: curated built-ins: /make-skill turns the current workflow into a new skill via create_skill (legacy alias: /skillify); /own-task turns the run into a standing task via create_task; /feedback sends product feedback to the m8tes team (optionally attach this run)
  • Your custom skills: account- or mate-scoped playbooks
  • Repo skills: for a mate bound to a repository, the skills that repository commits (the ones its coding run mounts). GET /skills/invokable?teammate_id= returns them with kind: "repo"; a saved skill of the same slug is replaced by the repository's, as it is in the run. End-user scoped runs never have them

It never lists the ~100 baked snapshot skills (noise + internal playbooks).

Only a /slug at the start of the message forces a skill. Anywhere else it is plain text the agent reads. An unknown slug is a 422. When a repository's skills cannot be read from GitHub, a typed /slug still starts the run with the message unchanged, and an explicit skill= answers 503 with Retry-After.

Python
# Platform commands need account-level runs: end-user runs never mount create_skill / create_task.
# Personal development only: this disables strict user_id checks account-wide.
# This persists. For customer-facing apps, keep strict mode on and pass user_id.
client.settings.update(require_end_user_id=False)
bot = client.agents.create(name="skills bot")  # account-level agent, no user_id

# Platform command (available only when skill creation is enabled for the run). Custom slugs need a skill you created first.
client.runs.create(teammate_id=bot.id, message="/make-skill turn this workflow into a skill")
# or
client.runs.create(teammate_id=bot.id, message="turn this into a skill", skill="make-skill")
# Standing task from this run:
client.runs.create(teammate_id=bot.id, message="/own-task weekly ads review")
# Send feedback about a run (also: client.feedback.create(...)):
client.runs.create(teammate_id=bot.id, message="/feedback this run stalled on connect")

for s in client.skills.list_invokable(teammate_id=bot.id):
    print(s.slug, s.kind, s.description)

How skills work

  1. You author a skill via the API/SDK (or an agent authors one mid-run)
  2. At the start of each run, visible skills are materialized into the workspace
  3. When the task matches a skill's description, the agent loads the body

A skill created mid-run applies from the next run (skills load at process start), like memories. v1 is markdown-only. Tool calls the skill suggests still go through the normal permission gate.

Scope

A skill is scoped like memory:

  • account (default): visible to all your agents.
  • teammate: visible to one agent only (pass scope="teammate" and teammate_id).

When an account skill and an agent-scoped skill share a slug, the agent-scoped one wins for that agent.

Create a skill

Python
from m8tes import M8tes

client = M8tes()

client.skills.create(
    name="cut wasted ad spend",
    description="Use when reviewing a Google Ads account for wasted spend before a weekly report.",
    body="""# Steps
1. Pull search terms from the last 30 days
2. Flag terms with spend and no conversions
3. Add them as negative keywords""",
    user_id="cust_123",
)

The slug (the SKILL.md handle) is derived from name server-side and stays stable across renames. To scope a skill to one agent, pass scope="teammate" and teammate_id:

Python
client.skills.create(
    name="bot playbook",
    description="Steps only the PPC bot should follow.",
    body="# Do this\n...",
    scope="teammate",
    teammate_id=bot.id,
    user_id="cust_123",
)

Manage skills

The slug is immutable; rename, edit the body, disable (stops loading it without deleting), or delete:

Python
for skill in client.skills.list(user_id="customer_123"):
    print(f"[{skill.id}] {skill.name}: {skill.scope} ({skill.source})")

one = client.skills.get(7, user_id="customer_123")
client.skills.update(7, body="# Updated steps\n...", user_id="customer_123")
client.skills.update(7, status="disabled", user_id="customer_123")  # stop loading it; re-enable with status="active"
client.skills.delete(7, user_id="customer_123")

The source field is "user" for skills you author, or "agent" for skills an agent authored itself. For an agent's skill, created_by_teammate_id names that agent, even when the skill is shared with every agent (teammate_id is then null). It is null for a skill a person wrote. The app shows it as Made by beside each skill.

Per-end-user skills (multi-tenancy)

Pass user_id to scope a skill to one of your end-users. Isolation is strict: an end-user's runs see only that end-user's skills, never your account-level ones. When you pass user_id to get/update/delete, it must match the skill's end-user or you get a 404.

Python
client.skills.create(user_id="cust_123", name="acme refund playbook", description="...", body="...")
client.skills.list(user_id="cust_123")
client.skills.delete(7, user_id="cust_123")

Agent-authored skills (built-in tool)

An agent can codify a repeatable workflow mid-run with the built-in create_skill tool. Creating one runs without an approval prompt: a skill only guides the agent, and every real action it suggests still follows the run's permission policy. Updating or deleting one asks first. Edit, disable, or delete them in Apps → Custom skills, where Made by names the agent (source: "agent", created_by_teammate_id). Applies from the agent's next run.

Limits
  • Name: max 200 characters
  • Description: max 500 characters (this is what tells an agent the skill is relevant; keep it specific and trigger-oriented)
  • Body: max 20,000 characters (markdown only in v1, no bundled scripts/assets)
  • Per account: max 50 skills per user_id scope
  • Scoping: account (all agents) or teammate (one agent); strictly isolated per user_id

Next: Memories · Custom tools · Users

Was this page helpful?