Skip to main content
ClaudeWave
ES, Spanish
Skill2.4k estrellas del repoactualizado 12d ago

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.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/UnicomAI/wanwu /tmp/customize && cp -r /tmp/customize/configs/microservice/bff-service/configs/agent-skills/claude-science/customize ~/.claude/skills/customize
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# 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)