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.

소스 정보

저장소
HughYau/AcademicForge
최근 소스 활동
2026년 7월 2일 10:54
감지된 SKILL.md 언어
영어
스타
2,575
포크
155

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
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
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기