Skip to main content

customize

Create, configure, and maintain custom agent profiles and author new skills via the `repl` tool. Use when the user wants to create an agent profile, build a custom agent, modify agent capabilities, attach or detach skills/connectors on a profile, author a skill, or inspect which connectors and tools are available. Also use whenever you need the `host.agents.*` or `host.skills.*` Python SDK.

Zur Installation springen

Quellinformationen

Repository
HughYau/AcademicForge
Letzte Quellaktivität
2. Juli 2026 um 10:54
Erkannte Sprache von SKILL.md
Englisch
Sterne
2.549
Forks
152

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
2 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
customize
description
Create, configure, and maintain custom agent profiles and author new skills via the `repl` tool. Use when the user wants to create an agent profile, build a custom agent, modify agent capabilities, attach or detach skills/connectors on a profile, author a skill, or inspect which connectors and tools are available. Also use whenever you need the `host.agents.*` or `host.skills.*` Python SDK.
license
Apache-2.0
# Customize Build and maintain **agent profiles** and **skills** programmatically via the `repl` tool using `host.agents.*` and `host.skills.*`. A **profile** is a named bundle that shapes how an agent behaves: - **`system_prompt`** — the profile's **identity**. This is the opening of the agent's system prompt; it REPLACES the generic "You are Claude Science" base identity. Write it in second person, lead with `You are {display_name}, ...`, state what the agent specializes in and what it does NOT do. Everything else (tool-usage rules, working-style bullets, scope guardrail) is inherited automatically — don't restate it. - **`display_name` / `description` / `icon_key` / `color_key`** — picker metadata. - **`skill_names`** (optional restriction) — by default a profile sees the **full live skill catalog** via `search_skills` / `skill(...)`, same as the main agent. Pass an explicit list ONLY to deliberately restrict it; `[]` creates a zero-skill specialist. **Restricting skills also restricts connectors** — a single `unrestricted` flag governs both; passing `skill_names` flips the profile to curated mode and starts it with **zero** connectors (see next). - **Connector access** — an **unrestricted** profile (the default) reaches **every connector** (bundled + custom + authorized directory), same as the main agent; use `detach_connector` to subtract specific ones. A **curated** profile (one created with an explicit `skill_names` list, or flipped via `{"unrestricted": False}`) starts with **no connectors** — reach is exactly what you `attach_connector`. - **`excludedTools`** — per-tool blocklist applied *after* connectors resolve. Use to strip specific high-risk or irrelevant tools from an otherwise-useful connector. **Per-connector, not a profile field** — set via `attach_connector(..., include_tools_pattern=/exclude_tools_pattern=)`; the profile's `excludedTools` in `list()` is the read-only aggregation across all its attached connectors. Patterns match the connector's **bare** tool names (e.g. `'^list_marts$'`, as returned by `list_connectors(name)['tools']`); the aggregated `excludedTools` entries are stored fully-qualified as `mcp_<connector>_<tool>` since the list spans every attached connector. --- ## Python SDK All calls run via the **`repl` tool** (see "Runs via the `repl` tool" below). Return values are plain dicts/lists; errors raise `RuntimeError` with a `host.agents.*:` / `host.skills.*:` prefix. ### `host.agents` ```python host.agents.list() # → [{"name", "displayName", "description", "source", "enabled", # "systemPrompt", "iconKey", "colorKey", # "skillNames": ["skill", ...], "connectors": ["name", ...], # "excludedTools": [...]}, ...] # (Return-dict keys are camelCase — wire shape, not kwarg names.) # `connectors` is a list of connector names (strings, same as skillNames) — # pass one to attach_connector/detach_connector or list_connectors(name). host.agents.create(name, display_name, description, system_prompt="", skill_names=None) # name: 2–32 chars, UPPERCASE letters / digits / underscores only — # e.g. "RNASEQ_REVIEWER". Lowercase / dashes are rejected. # display_name is the human-friendly picker label. # skill_names controls catalog visibility: # - leave it unset → the profile sees the FULL live skill catalog, same as # the main agent — skills published later appear automatically. It also # gets every connector the main agent has, resolved dynamically — new # connectors added later appear automatically too. This is the default; # don't pass a list unless you mean to restrict. # - pass a list (including []) → restricts `search_skills`/`skill(...)` to # EXACTLY those names. [] creates a zero-skill specialist. # → the stored profile record (same shape as one list() entry) host.agents.update(name, patch) # patch: dict of fields to change — any of display_name, description, # system_prompt, skill_names, unrestricted, icon_key, color_key # (camelCase also OK). # patch["skill_names"] is an EXACT REPLACE of the whole skill list and flips # the profile to restricted mode — anything you omit is DETACHED. To add or # remove a few skills, use attach_skill / detach_skill — they work on both # restricted AND unrestricted profiles without changing the mode. # # If you do need a full-list replace, CHECK cur["unrestricted"] FIRST: on an # unrestricted profile cur["skillNames"] is the lossy disk-cache view (not # the full live catalog), so `cur["skillNames"] + ["x"]` would permanently # freeze the profile to that partial list. The safe pattern: # cur = [a for a in host.agents.list() if a["name"] == name][0] # if cur["unrestricted"]: # host.agents.attach_skill(name, "new-skill") # stays unrestricted # else: # host.agents.update(name, # {"skill_names": cur["skillNames"] + ["new-skill"]}) # (return-dict keys are camelCase — read "skillNames", write "skill_names") # patch["unrestricted"] = True → back to the full live catalog + all # connectors (undoes a skill_names restriction). # → updated profile record # (excludedTools is NOT a patch field — it's per-connector; use # attach_connector's include_tools_pattern/exclude_tools_pattern below.) host.agents.switch(name) # Ask to continue THIS conversation as `name`. Shows the user an approval # card; on Allow, the switch takes effect on their NEXT message (the current # turn finishes as the current profile). On decline, tell the user they can # select the profile from the session config popover on any new conversation. # → {"switched": True, "name", "displayName"} host.agents.delete(name) # → {"deleted": name} host.agents.attach_skill(name, skill) host.agents.detach_skill(name, skill) # → updated profile record host.agents.attach_connector(name, connector, include_tools_pattern=None, exclude_tools_pattern=None) host.agents.detach_connector(name, connector) # → updated profile record. Omit both patterns on a fresh attach to expose # every tool the connector offers; re-attaching an already-attached # connector without patterns preserves its existing exclusion list (pass # include_tools_pattern='.*' to clear it). Patterns match the connector's # BARE tool names (as returned by list_connectors(name)['tools'], e.g. # '^list_marts$'); the resulting excludedTools entries are stored # fully-qualified as mcp_<connector>_<tool>. host.agents.list_connectors(connector_name=None) # no arg → [{"name", "displayName", "source", "description", # "authState", "attachedAgents": [...]}, ...] # with connector_name → single dict with an extra # "tools": [{"name", "description"}, ...] ``` ### `host.skills` ```python host.skills.list() # → [{"name", "origin", "description"}, ...] # origin: "anthropic" (bundled, read-only — fork under a new name), # "organization"/"personal" (editable), "draft" (local, unpublished) host.skills.read(name, path="SKILL.md") # → {"name", "path", "content": "..."} host.skills.edit(name, path, content, old_string=None) # old_string=None → create `path` with `content` (fails if the file already # exists — read it, then edit with a non-empty old_string) # old_string=str → str_replace the single exact match (rejected unless it # matches exactly once — add surrounding context if needed) # → {"action", "path", "draft_path", "note"} host.skills.publish(name, overwrite=False) # publish takes NO content args — write SKILL.md via .edit() first. # → {"status": "published", "skill_id", "name", "note"} host.skills.delete(name) # draft → removes local dir; org/personal → unpublishes + removes local # cache; anthropic bundled → protected. # → {"deleted": name} (plus "unpublished": True for published skills) ``` ### Runs via the `repl` tool `host.agents.*` / `host.skills.*` execute in the **control-plane kernel** — a separate Python process from your `python` cells, reached via the **`repl` tool** (not the `python` tool). It shares your workspace directory (cwd) but **not** memory, so variables from `python` cells aren't visible there and vice-versa. To hand results across, write to a file — same pattern as Python↔R: ```python # repl tool import json, os os.makedirs("handoff", exist_ok=True) profiles = host.agents.list() json.dump(profiles, open("handoff/agents.json", "w")) ``` ```python # python tool import json, pandas as pd profiles = json.load(open("handoff/agents.json")) pd.DataFrame(profiles)[["name", "source", "enabled"]] ``` --- ## Workflow: scope → draft → review → create **Do not call `generate_plan` for profile CRUD.** This is a single scope→draft→confirm loop; `ask_user` (step 4) is the review gate. A plan adds a second approval that duplicates the `ask_user` confirmation and drags in step-status bookkeeping that fights this workflow. **User approval.** Most `host.agents.*` / `host.skills.*` calls apply immediately — `create`/`update` (including unrestricted), `attach_*`/`detach_*`, and `skills.publish`/`skills.edit` are pre-approved at session start and the cell does NOT pause. An approval card (cell pauses, resumes automatically on Allow — you don't retry) appears only for the calls that **hand off identity or free a granted name**: - `host.agents.switch(name)` — per-target; Allow covers this name only - `host.agents.update(name, {"name": ...})` (rename) — per-target - `host.agents.delete(name)` / `host.skills.delete(name)` — **one card per project**: the first delete shows a card; "Allow for this project" covers every subsequent delete in this project, including bulk teardown. Do NOT tell the user they'll see N cards for N deletes. The name is read from the runtime call for `switch` and rename, so both literal and variable names work (`host.agents.switch("FOO")` or `host.agents.switch(name_var)`); keep the `ask_user` review step so the click is a quick confirm, not a surprise. After the call returns, read back (`host.agents.list()`) to confirm the actual state — don't narrate an expected card. ### Reading existing profiles Call `host.agents.list()` to see the user's current profiles so you don't duplicate an existing agent. The main agent's bundled profile is protected — it cannot be renamed or deleted. ### 1. Scope first What is this agent *for*? A profile should have one job. Pick an UPPER_SNAKE name (`RNASEQ_REVIEWER`, not `RNA-seq review helper`). Use `ask_user` if the name or scope is unclear — profiles are user-visible in the picker. ### 2. Write the identity `system_prompt` is the agent's opening paragraph — it replaces the base identity, it's not an addendum. Lead with `You are {display_name}.` State the specialization and the boundaries ("You handle X, Y, Z. You do not handle ..."). Keep it under ~200 words; the heavy how-to lives in skills, not the prompt. ### 3. Ask: full access or a subset? Before creating, `ask_user` whether this profile should have **full access** (the live skill catalog and every connector — same reach as the main agent; new skills and connectors appear automatically) or a **restricted subset** (a fixed list you'll curate together). Don't infer this from the role description — a narrowly-described specialist may still want full reach, and a broadly-described one may want a tight loadout. Pair this with the name/prompt review in step 4 so it's one round-trip. ### 4. Review with the user Show the proposed name, display name, description, `system_prompt`, and the user's full-vs-subset choice from step 3. `ask_user` to confirm before writing. If they chose a subset, list the proposed skills/connectors here. ### 5. Create Call `host.agents.create(name, display_name, description, system_prompt=...)`. If the user chose **full access**, leave `skill_names` unset. If they chose a **subset**, pass `skill_names=[...]` with the agreed list — **this flips the profile to curated mode and starts it with zero connectors**, so attach the agreed connectors after create as in step 6. For edits to an existing profile, use `host.agents.update(name, {...})` with targeted fields; prefer `host.agents.attach_skill(...)` / `host.agents.detach_skill(...)` and `host.agents.attach_connector(...)` / `host.agents.detach_connector(...)` over wholesale `skill_names` replacement so you don't clobber the user's own edits. After the profile exists, **offer to switch to it**: `host.agents.switch(name)`. The user sees an approval card; on Allow, this conversation continues as the new specialist from their next message. If they decline, tell them they can select it from the session config popover on any new conversation. ### 6. Restricting the loadout (when the user chose a subset) If the user chose a subset in step 3, curate after create: - **Skills**: `host.agents.update(name, {"skill_names": [...]})` with the exact list, or `detach_skill` one at a time. Check `host.skills.list()` for available names. On `update`, `skill_names` is an exact replace — never send a partial list to "add"; fetch the current `skillNames` (camelCase in the return dict), modify, send back. - **Connectors**: a curated profile (created with an explicit `skill_names` list, or flipped via `{"unrestricted": False}`) starts with **NO connectors** — reach is exactly what you attach. Call `host.agents.list_connectors()` to see every available connector (bundled + directory + user-added MCP) with its auth state, then `host.agents.attach_connector(name, connector_name)` for **each** connector the user agreed to keep. Use `include_tools_pattern=`/`exclude_tools_pattern=` on the attach call to scope which tools the profile gets (omit both to expose every tool; re-attaching without patterns preserves the existing exclusion list — pass `include_tools_pattern='.*'` to clear). A connector with `authState` other than `"authorized"` or `"not-required"` must be connected via the Connectors panel before it can be attached. `detach_connector` only removes an explicit attachment; on a curated
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen