Best for
- Execution stall at the action/write boundary (BEHAVIORAL) — the agent
- Mis-selection — the agent calls the wrong tool, or calls none when one
- Bad argument-filling — the right tool, wrong arguments: a missing required
skillberry-ai/cap-evolve/skills/capabilities/tools/SKILL.md
Optimize an agent's OWN tool surface (tools it implements, not an external MCP server). Use when the agent mis-selects tools, fills arguments wrong, or has a confusing/redundant toolset. You may edit tool names, descriptions, parameter docs, in-description examples, the JSON schema/API, the tool code itself, ADD tools (including composite tools that call existing tools), and REMOVE tools — all under an action policy so risky edits can be locked off.
Decision brief
This capability treats the agent's entire tool surface as the optimizable artifact. When an agent owns its tools — it implements the handlers, defines the wire schema, and controls every caller — then names, descriptions, parameter docs, in-description examples, the JSON Schema,…
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/skillberry-ai/cap-evolve --skill "skills/capabilities/tools"Inspect the Agent Skill "tools" from https://github.com/skillberry-ai/cap-evolve/blob/4bb97c4e190c4795326d1834b3a5cea3cd3d499a/skills/capabilities/tools/SKILL.md at commit 4bb97c4e190c4795326d1834b3a5cea3cd3d499a. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Review the “How to run” section in the pinned source before continuing.
The tool's docstring AND its return value are what the agent SEES — make both clear and recovery-oriented. The doc surface (description, important-notes, per-param, Raises:, examples) drives which tool the model calls and how it fills the arguments; the return value (and especia…
Start here. A deterministic guard in code beats a sentence in the prompt. A docstring or system-prompt rule only makes the model more likely to comply — it can be forgotten, mis-read, or out-reasoned on the next task. Code (a precondition check, a normalization, a loop) makes th…
Map the trace symptom to the code-bearing edit. Each row is a failure the model could "know" how to avoid yet keeps producing — so the fix is code, not prose:
Reach for tools when a trace shows one of these failure signatures:
Permission review
The documentation asks the agent to run terminal commands or scripts.
python scripts/check.pyThe documentation asks the agent to run terminal commands or scripts.
python scripts/run.py --path <capability_dir> # candidate + policy + validityEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 88/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 36 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
This capability treats the agent's entire tool surface as the optimizable artifact. When an agent owns its tools — it implements the handlers, defines the wire schema, and controls every caller — then names, descriptions, parameter docs, in-description examples, the JSON Schema, and the implementation code are all fair game.
Use this capability when the agent OWNS its tools — it implements the handlers and controls the wire schema, so the code itself is editable. (When the tools come from an external server you can only re-describe, not re-implement, the action policy here is tightened to documentation-only edits.)
The tool's docstring AND its return value are what the agent SEES — make both
clear and recovery-oriented. The doc surface (description, important-notes,
per-param, Raises:, examples) drives which tool the model calls and how it
fills the arguments; the return value (and especially the error text) steers the
next turn. Each lever below is an edit class; in ONE pass, apply EVERY edit class
the traces call for — a validation wrapper AND a loop tool AND enriched
returns/errors AND doc fixes across all implicated tools can and should all ship in
the same candidate. (1-line generic examples; worked bodies in
references/examples.md, depth below and in
references/concepts.md.)
Read this skill in full before editing. Ship MULTIPLE fixes per iteration — but every one must be REAL (targets a currently-failing task), SAFE (cannot change a passing task's behavior), and VERIFIED (proven to fix its target). Several such fixes beat a long list that includes a speculative edit: one edit that regresses a passing task can sink the whole candidate at the gate. Quality over churn — never add an edit to hit a count, and never re-add a rule/tool the run already tried and rejected.
Per-change SAFETY (the rule that makes multi-change work). Scope every guard to fire ONLY on the exact violating condition, and check its blast radius: run it on the args of 1–2 currently-PASSING tasks that use the same tool and confirm it does NOT fire. A guard that fires on a passing task is a regression — rescope or drop it. This is how you ship many changes without net-zero churn.
Pick the lever by failure type — the in-body guard is the DEFAULT strong move:
Edit the BODY of an EXISTING tool (reach for this FIRST for a rule violation). When the agent VIOLATES a rule a tool already owns (a wrong field value, an id not on file, an action on a record whose state forbids it), convert the prose rule into a scoped in-body guard. This is the highest-yield, lowest-regression edit; expect to touch SEVERAL existing bodies in one iteration.
ADD a NEW code-bearing tool — for a genuine CAPABILITY GAP or action STALL. A composite atomic-WRITE tool for a multi-step action the agent narrates/confirms then fails to execute is the canonical case (the primitive is what it skips; the composite makes the action un-skippable; then REMOVE the raw primitives). New tools are available and encouraged WHEN they close a real gap — but add one ONLY if the agent will actually call it AND it changes the graded outcome. Do NOT add read/compute/summary helper tools that a guard or a prompt line would subsume, and never add a tool just to "ship a new tool" — that is churn the gate punishes.
DECISION / PERMISSION cluster → a discriminating-predicate guard (the BOUNDED-blast- radius alternative to a prompt change). When a cluster is about ACT-vs-REFUSE (the agent acted where it should have refused/escalated, or vice versa), the WRONG fix is loosening a global decision rule in the prompt — that has UNBOUNDED blast radius and regresses every task where the original behavior was gold. The RIGHT fix lives here: an in-body guard on the tool that owns the action, expressing the EXACT policy predicate, that refuses/raises ONLY when the qualifying condition is/isn't met. It fires only on the narrow violating condition, so its blast radius is bounded to the failing inputs — the SAFEST edit, preferred over any prompt/permission change.
HARD-ZERO / capability-gap cluster → a REAL targeted tool, never prose. A task scoring 0.00 that needs a compute / composite / discriminating-predicate tool stays 0.00 after any docstring or prompt reword. Ship a tool the agent will CALL that changes the graded state.
The two failure modes to avoid: (1) leaving a rule the agent keeps breaking as loose prose instead of a guard, or loosening a global permission rule (unbounded regression) instead of a scoped guard; (2) padding the candidate with low-value helper tools or cosmetic rewrites that move no graded task.
if not rec["cancellable"]: raise ValueError("not cancellable; reason=...; do X instead") to the existing
cancel_record body. Expect to touch the BODIES of SEVERAL existing tools per
iteration — one per violated rule.search_logs returns only
the relevant lines instead of a raw dump; or a find_duplicate_records the agent
has no way to compute today. For a STALL or capability-gap cluster this is the
right move even when a primitive exists — see item 7 (composite atomic-WRITE).find_record+charge_payment behind one
charge_record(record_id) that resolves then charges.Raises: / per-param docs / examples; rename for least surprise. Ex:
lookup(record) → get_record(record_id: str) with "returns an error object if
not found."get_records(ids: [...]) replaces N× get_record(id).remove the raw primitives so the action is
un-skippable. Ex: apply_change_plan(record_id, steps) validates → applies each
→ returns final state as one reliable call. Reach for this whenever a cluster
STALLS at the action boundary — do not settle for a prose "be sure to act" rule.query once
get_record + search_records cover it.Before/after — convert a violated prose rule into an in-body guard (the default
edit). The rule "a record can only be cancelled when it is cancellable" lives as
prose in the prompt and the agent keeps breaking it. Don't add a tool — edit the
EXISTING cancel_record body:
def cancel_record(record_id):
+ rec = get_record(record_id)
+ if not rec["cancellable"]:
+ raise ValueError(
+ "not cancellable; reason=" + rec.get("status", "unknown")
+ + "; do X instead (e.g. offer a change_record)")
return _backend.cancel(record_id)
And the rule "amounts are in whole cents and the method must be on file" — edit the
EXISTING book (or charge) body to normalize the field then raise an actionable
error:
def book(record_id, amount, payment_id):
+ amount = int(round(amount)) # normalize: callers pass dollars
+ methods = {m["id"] for m in get_record(record_id)["payment_methods"]}
+ if payment_id not in methods:
+ raise ValueError(
+ f"payment method {payment_id!r} not on file; "
+ f"available={sorted(methods)} — pass one of these")
return _backend.book(record_id, amount, payment_id)
Both fixes touch a tool that ALREADY exists; no new tool is needed. A docstring-only or new-tool-only iteration that leaves these rules as prose is under-used.
Guardrails (depth below): encode deterministic logic in code, not prose (a
tool body the model cannot skip beats a sentence it can forget); keep the toolset
small and namespaced (aim < ~20 active tools); ship correct, bug-free code
(every code edit needs validation + a validate run); and never remove a tool
without a capability-preserving replacement (add → verify → swap, see the SAFE
TOOL-REPLACEMENT PROTOCOL).
Generalize, never hardcode. Every in-code guard must fire on the GENERAL
condition that defines the failure class, never on a literal value from one task.
Good: if payment_id not in user_payment_methods: raise .... Bad:
if record_id == "<TASK_SPECIFIC_ID>": raise ... — that overfits to one task, gets
rejected by the held-out gate, and helps nothing else. Use a failing task's
specifics only to identify the class, then write the general check.
A discriminating-predicate guard for a decision/permission cluster must encode the
GENERAL policy condition that separates the qualifying cases from the rest (e.g.
if record.tier == "restricted" and action == "modify": raise ...), NOT a global
behavior flip and NOT a task literal. The guard NARROWS — it fires only on the cases
the policy actually governs — so passing tasks outside that condition keep their
behavior unchanged.
Start here. A deterministic guard in code beats a sentence in the prompt. A docstring or system-prompt rule only makes the model more likely to comply — it can be forgotten, mis-read, or out-reasoned on the next task. Code (a precondition check, a normalization, a loop) makes the right behavior the only thing that can happen — it cannot be "forgotten." When the traces show a rule the agent keeps breaking, a multi-step action it keeps fumbling, or — most importantly — an action it stalls on and never executes, do not just reword a description — put the behavior in code.
Two code-bearing edits, chosen by failure type — both first-class. For a rule
VIOLATION, enforce the rule in the body of the EXISTING tool that owns it — "only
cancel a cancellable record" governs cancel_record, "amounts in whole cents"
governs book/charge; add an in-body guard there and expect to touch SEVERAL
existing bodies per iteration. For a CAPABILITY GAP or an action STALL, write a NEW
code-bearing tool — a loop tool to collapse a multi-call chain, or (the big one) a
composite atomic-WRITE tool to encapsulate a multi-step write the agent keeps
skipping. Do not treat the new tool as a last resort: when a cluster stalls at the
action boundary, the composite is the correct fix even though a write primitive
already exists, because the primitive is exactly what the agent declines to call.
(See the before/after diffs above, the three patterns below, and the worked bodies
in references/examples.md.)
Prose cannot fix a BEHAVIORAL failure. There is a sharp distinction the optimizer must make. If the agent does not know something (a format, a rule, a decision criterion), prose can teach it — that is a KNOWLEDGE gap, and it belongs in the prompt. But if the agent demonstrably knows what to do and still doesn't do it — it analyzes the situation, explains the plan, even gets the user's confirmation, and then simply fails to CALL the action tool and stops — that is a BEHAVIORAL failure, and more prose does not fix it. You cannot instruct a model out of a behavior it already "agreed" to and then skipped. The only reliable fix is to move the behavior into CODE: encapsulate the whole action in a tool whose body performs it, so executing it is no longer a choice the model can decline mid-conversation. Telling the agent to "be sure to act" is exactly the kind of edit the traces show failing.
Three patterns carry almost all the gain (worked bodies below and in
references/examples.md):
Validation / rule-enforcement tool (wrap, then delegate). When a rule or
precondition that today lives only in the prompt is GENERAL — it always
applies, not just to one task — implement it as code in a NEW tool that:
validates / normalizes the inputs → enforces the rule → calls the existing
primitive → returns a clear result (or a clean refusal). Then remove the raw
primitive from the exposed set if the agent should only ever reach it
through the safe path. Example: cancel_record_safely(record_id) reads the
record, refuses unless it is cancellable, then calls the raw cancel_record.
Workflow / loop tool (collapse a recurring multi-step sequence). When a
small multi-step workflow recurs, or the agent calls one primitive N times in
a row (and drops or mis-threads a result), implement it as ONE tool with real
loops/code that calls the existing tools internally and returns the finished
result. Example: a tool that loops over a list of ids calling get_record
once each and returns them aligned, instead of the agent issuing N calls.
Write / workflow COMPOSITE tool — make a stalled action un-skippable
(co-equal PRIMARY pattern). This is the fix for the single most common
BEHAVIORAL failure: the agent reliably stalls at the action/write boundary
— it analyzes, explains, even confirms with the user, then never issues the
write call and stops, leaving the task half-done. The cure is not a stronger
rule. Encapsulate the ENTIRE multi-step action (analyze → confirm → act) as
ONE composite tool whose body performs all the steps in code — calling the
existing primitives in the right sequence and looping where needed — so the
action completes the moment the tool is called and cannot be skipped
mid-conversation. Then remove the raw primitives so the composite is
the only path; the safe, complete behavior is then the only behavior reachable.
Generic example: an apply_change_plan(record_id, steps) that performs a
multi-step update atomically — validating each step, applying them in order via
the existing write primitives, and returning the final state — so the agent
hands over the plan in one call instead of narrating it and then failing to
execute. (Worked body in references/examples.md §3e.)
Lean caveat — replace, don't accumulate. Every exposed tool enters the
agent's context, and too many tools degrade selection (see §3 of concepts.md).
So PREFER consolidating over piling on: when you add a safer or looped tool,
remove the now-redundant primitive so the net tool count stays small and
sharp. Do not add many narrow tools. One sharp tool that subsumes a primitive
beats two overlapping ones.
SAFE TOOL-REPLACEMENT PROTOCOL (never bare-remove a tool). To replace or consolidate a tool, follow these steps in order — never delete a tool without a replacement that subsumes it:
validate; confirm the body actually calls the
primitive and returns a sane result).remove the raw primitive from the active
/ exposed set and register the wrapper as the path the agent uses.Bare-removing a primitive with no replacement strands every task that needed it ("no applicable tool"); adding a wrapper but leaving the primitive exposed lets the model route around the guard and reproduce the original failure. The add-verify-swap order is what makes the safe path the only path without a coverage gap.
You must write the BODY. A compose/add/code edit whose body is ...,
a bare pass, or docstring-only is NOT this edit — it does nothing. Emit a real
implementation: the loop, the precondition check, the calls to the existing
tools (get_record(i) — or self.get_record(i) if your adapter binds tools as
methods). Worked examples with full bodies are below under
Add tools that call existing tools.
SECONDARY (last resort): passthrough / "think" / reasoning-only tools. A tool
whose body just returns (or echoes) its argument, with the actual rule living only
in the docstring (e.g. a think(thought)/check_policy(text) tool that does no
real work), is the WEAKEST form of this edit — it is prose wearing a tool's
costume, and the model can ignore or mis-apply it exactly like any prompt sentence.
If a rule can be encoded as code, encode it as code — validate, normalize, and
enforce it in the body (patterns 1 and 2 above), don't leave it as docstring prose.
Reach for a reasoning-only tool only when the behavior genuinely cannot be made
deterministic (e.g. you want to prompt a planning step), never as a substitute
for a check you could have written in a few lines of code.
Map the trace symptom to the code-bearing edit. Each row is a failure the model could "know" how to avoid yet keeps producing — so the fix is code, not prose:
These four rows carry most of the recoverable gain — diagnose for them FIRST, and verify the fix you ship actually FIRES on the failing trace (run the new body on the exact arguments from that trajectory; a guard that never triggers on the failing task is dead code, not a fix). These rows are independent: fix as MANY of them as appear in the trajectories in one candidate, not just the first — each guarded tool is its own bounded fix.
| Trace symptom | Fix |
|---|---|
| Wrong ARGUMENT the tool could validate — a write whose id / reference / count / unit is not consistent with the agent-visible state (an id not in the record, a count exceeding what's available, the wrong unit). Right tool, bad argument; partial credit or a corrupted write. | Normalize-then-call wrapper: wrap the write in a body that RESOLVES / VALIDATES the argument against the current state, and on mismatch returns available=[...] (the valid options) or raises an actionable error naming what's wrong and what to pass instead — never let a write proceed on an unvalidated reference. Coerce units, resolve ids, check the field is on file, then delegate to the primitive. |
| Escalate / bail-out abandoning a REQUIRED, eligible action — the agent hands off or gives up when it could and should have completed the action itself; this is a behavioral STALL, not a missing capability. | Composite WRITE tool: encapsulate the eligible-action batch in ONE tool whose body executes the steps in code (skipping any ineligible item with a recorded reason), then remove the raw primitives so completing the batch is the only path. Do NOT add a "don't bail out" prose rule — the agent already chose to bail; only code removes the choice. |
| Recoverable error that strands the agent — a tool raises an opaque traceback / bare code, the agent retries the same bad call or gives up. | Enriched RETURN that aids recovery: on a recoverable error, return what's wrong + the valid options + the recommended next action (e.g. {"error": "id not found", "available": [...], "next": "call search_x to resolve the id"}), so the model self-corrects on the next turn instead of repeating the failure. |
| Execution stalls at the action boundary — the agent analyzes, explains, even confirms, then never calls the write tool and stops (the task is left half-done). | Composite WRITE tool (pattern 3): one tool whose body performs the whole analyze→confirm→act sequence, then remove the raw primitives so the action is un-skippable. |
| The same primitive called N times in a row — looping over a list in the agent's own context, dropping or mis-threading results. | Loop tool (pattern 2): one tool that takes the list and loops inside a single call. |
| A rule stated in the prompt but repeatedly violated — a required order ("read before write"), a precondition the API doesn't enforce. | Validation wrapper (pattern 1): enforce the rule in the tool body; remove the unguarded primitive. |
The throughline: a failure the agent knows better than but still commits is
behavioral, and behavioral failures are fixed by removing the choice — putting the
behavior in code and remove-ing the path that let it go wrong.
Reach for tools when a trace shows one of these failure signatures:
search → filter → fetch every time and keeps getting the order or the
glue wrong. A single well-named composite tool collapses the sequence.get_record(id) once per id, or search(a,b,date)
once per date/route combination), burning turns and often dropping or
mis-threading a result. A tool that takes the list and loops inside one
call collapses N calls into 1.If the problem is what the agent is told to do rather than what it can do, it is out of scope for this capability (it belongs to whatever capability edits the agent's instructions).
| Action | Changes | Why it moves the metric |
|---|---|---|
description | tool-level wording incl. in-desc examples | the single biggest lever on selection |
params | per-parameter descriptions / defaults | drives correct argument-filling |
examples | example call strings | shows concrete well-formed calls |
schema | the full JSON Schema (types, required, enum) | constrains/guides the model's output |
code | the handler body of an EXISTING tool | the default high-leverage edit — convert a violated prose rule into an in-body guard (precondition, normalization, actionable refusal); expect to edit SEVERAL existing bodies per iteration |
compose | add a code-bearing tool that calls existing tools | enforce a rule, collapse a multi-call chain, or perform a whole stalled WRITE action in code — use when no existing tool owns the rule |
add / remove | introduce / delete a tool | shape and shrink the toolset (replace primitives; keep it lean) |
The code row (editing an EXISTING tool's body) is the first edit to reach
for, with compose/add close behind — a deterministic guard beats a sentence
in a prompt (see below). For each violated rule, first ask "which EXISTING tool
governs this, and what in-body check enforces it?" — usually the answer is editing
that tool's body, not adding a new one. Reword descriptions after you've asked
"can this rule be code in the existing body instead?" In ONE pass, apply EVERY edit
class the traces call for — in-body guards across SEVERAL existing tools AND a loop
tool where needed AND enriched returns/errors AND doc fixes across all implicated
tools can and should all ship in the same candidate; do not stop after a single
edit.
Lock any of these off via inputs/policy.json. For example, in a frozen-API
deployment you might allow only ["description", "params", "examples"] so an
optimizer can reword tools but never change the wire contract or the code.
apply() refuses anything outside the allowed set and reports the refusal — it
never silently drops or silently applies a disallowed edit.
An LLM never sees your implementation. At call time it sees, for every available
tool, a serialized block of {name, description, parameters-schema, examples}
injected into its context (this is literally how the Anthropic and OpenAI tool
APIs work, and how an MCP host presents tools/list results). Two decisions
follow, and each is driven by a different part of that block:
lookup selects worse than
get_order_by_id.required, enum, descriptions) plus any
examples. An enum turns "guess a status string" into "pick from this
closed set"; prefer it for every closed value set, and use the provider's
strict / schema-validated mode where available so the model adheres to the
schema instead of guessing. A per-field description ("ISO-8601 date, e.g.
2025-06-14"; "amount in whole US cents") turns a malformed argument into a
correct one — always pin units, format, and default per parameter. Add
schema-validated input_examples for complex / nested / format-sensitive
params (a few help; long dumps hurt reasoning models). And don't make the
model fill arguments you already know — pass them in code (a wrapper) instead
of asking for them.Namespace by service/resource so selection stays unambiguous as the set grows
(github_list_prs, payments_charge), and keep the active toolset small — aim
for fewer than ~20 tools per turn (OpenAI's heuristic); selection degrades
sharply past that. This is the number behind the lean caveat above.
Scale the edit to WHO calls these tools at runtime (see the THE READER block in your
instructions, if present). For a mid/weak reader, push harder on this skill's
already-preferred code enforcement (in-body guards, composite atomic-write tools) — a
weak reader skips a prose rule but a guard fires regardless — and write literal,
example-bearing per-parameter slot-filling docs on every tool (name the exact format,
units, and one concrete valid value, e.g. date: ISO-8601 "2026-07-20"). A weak reader
mis-fills under-documented arguments far more often, so the marginal value of explicit
parameter docs and a smaller, less-confusable toolset is highest there. For a frontier
reader, terser parameter docs and fewer worked examples suffice; spend the budget on
removing redundant tools instead.
What a tool returns steers the next turn as much as its description steers selection. A bloated or opaque result causes hallucinated ids, wasted context, and redundant calls. Design the response:
get_order(order_id) projection should surface
order_id="A-1042" over 4f3c…-uuid. If the backend only has a UUID, attach a
readable handle alongside it.verbosity/response_format control (e.g. "concise" vs "full") so the
agent asks for detail only when needed instead of drowning in it."payment method not on file; available: ['card_1','gift_4'] — pass one of these"
or "date must be ISO-8601 YYYY-MM-DD, got '6/14/25'". The model reads the error
and self-corrects on the next call instead of retrying the same bad one. Wrappers
(patterns 1–3) are the natural place to produce these.A tool's documentation is its contract. Every tool — primitive or wrapper — needs all of these, or the model is left guessing:
The description is the model's contract, not flavor text. It is the only information the model has about which tool to call and what argument values are legal. A good description always states, in always-true terms (never one task's specifics):
YYYY-MM-DD" beats "the date".Raises:/error-condition text to make the
description "cleaner." Knowing a call raises ValueError: gift card balance too low is exactly what lets the model pick a different payment method instead
of failing the task. Stripping error info removes a guard rail; it does not
improve selection.Selection degrades as the toolset grows: benchmarks like the Berkeley Function-Calling Leaderboard include a dedicated "relevance detection" category precisely because models hallucinate calls when no tool fits, and ToolLLM had to add a retriever to cope with thousands of tools. The practical implication for this capability: fewer, sharper, non-overlapping tools beat many vague ones.
Selection fix (description). A trace shows the agent calling a generic
query tool for order lookups, then failing.
- "name": "query", "description": "Run a query."
+ "name": "get_order", "description": "Look up a single order by its ID and
+ return status, line items, and shipping. Use when the user references a
+ specific order (an ID, 'my last order', or an order in the current thread).
+ Do NOT use for searching across orders — use search_orders for that."
Argument-filling fix (schema + enum). The agent keeps sending
status="done" when the backend expects "fulfilled".
"parameters": { "type": "object", "properties": {
- "status": { "type": "string", "description": "the status" }
+ "status": { "type": "string", "enum": ["pending","fulfilled","cancelled"],
+ "description": "Order status to filter by." }
}, "required": ["status"] }
Collapse a fumbled chain (compose). The agent must search_orders then
get_order on the first hit, and often forgets the second call.
{ "kind": "compose", "value": {
"name": "find_order",
"description": "Search orders by free text and return the full record of the
best match. Use this instead of search_orders+get_order when you want one order.",
"code": "def find_order(q):\n hit = search_orders(q)[0]\n return get_order(hit['id'])"
}}
A docstring edit can only make the model more likely to do the right thing. A new tool whose body calls existing tools can make the right thing the only thing the model can do, and can turn many calls into one. These are the two PRIMARY patterns (§"highest-leverage edit" above) plus the normalize variant — all benchmark-agnostic, and each shows a REAL body you are expected to write:
Workflow / loop — collapse repeated primitive calls into one list call. If the agent calls
get_record(id) once per id, or search(origin, dest, date) once per
route/date combination, add a tool that takes the list and loops inside a
single call, returning all results together. The agent makes one call instead
of N; nothing is dropped or mis-threaded.
{ "kind": "compose", "value": {
"name": "get_records",
"description": "Fetch the FULL details of EVERY record in `ids` in one call. Use this instead of calling get_record once per id when you have several ids (e.g. all of a user's records). Returns a list aligned with `ids`; an entry is an error object if that id is not found.",
"parameters": {"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}}},"required":["ids"]},
"code": "def get_records(ids):\n out = []\n for i in ids:\n try:\n out.append(get_record(i))\n except Exception as e:\n out.append({'id': i, 'error': str(e)})\n return out" }}
Validation / rule-enforcement — enforce a rule or required order
deterministically (wrap, then delegate). If a write must be preceded by a
read, or a precondition the API does not itself check must hold, put the check
in code: validate/normalize the inputs, enforce the rule, then call the
existing primitive — so a violation returns a clear refusal instead of
corrupting state. The model literally cannot skip the step. Then remove
the raw primitive so the only path is the safe one.
{ "kind": "compose", "value": {
"name": "cancel_record_safely",
"description": "Cancel a record after verifying it is cancellable. Reads the record first and REFUSES (returns an error) if the cancellation preconditions are not met, so you never need to call get_record yourself before cancelling. Use this for every cancellation.",
"parameters": {"type":"object","properties":{"record_id":{"type":"string"}},"required":["record_id"]},
"code": "def cancel_record_safely(record_id):\n rec = get_record(record_id)\n if not rec.get('cancellable'):\n return {'error': 'not cancellable', 'record': rec}\n return cancel_record(record_id)" }}
...paired with a { "tool": "cancel_record", "kind": "remove" } so the unsafe
primitive leaves the choice set entirely.
Normalize / return richer, ready-to-use results. Have the new tool do the glue the model otherwise improvises (resolve an id, attach the related record, coerce units), so the model gets a result it can act on directly.
Then remove the error-prone original deliberately (the lean caveat). This
remove step is not optional polish — it is what makes the safe/complete tool the
only path. A wrapper that enforces a rule, or a composite that performs a whole
write, achieves nothing if the raw primitive is still exposed: the model can (and
under pressure will) route around the guard straight to the primitive and
reproduce the exact failure. Observed in real runs, optimizers add wrappers but
never remove the primitives they wrap, so the unsafe path survives and the
metric barely moves. To replace a confusing or now-redundant tool,
add/compose the clearer one and remove the old name so it leaves the choice
set — don't keep both, or selection gets harder (§3 of concepts.md). Net tool
count should stay small and sharp: prefer one tool that subsumes a primitive over
two that overlap. Pair every wrapper/composite with the matching remove unless
the primitive is still independently needed for a different, safe purpose.
Drawn from real runs where the optimizer left most of the gain on the table.
Bad — what under-performs (do not stop here):
Raises: / error info "to clean up" the docstring. Observed: an
accepted candidate deleted every Raises: section. It barely moved the metric
and left the model blind to why calls fail. Error conditions are guidance, not
clutter — keep them.Good — what actually moves accuracy and cuts calls:
remove the
error-prone original so the surface stays small and sharp.The test: would this edit help on a task the optimizer has never seen? A loop
tool, a precondition check, and a unit-pinned argument description pass. A comma
and a deleted Raises: line do not.
code
edit and a schema edit must stay in sync — change both in one batch, then run
validate. In a frozen-API setting, lock schema/code off via policy.inputs/policy.json is the safety boundary between "reword the docs" and "rewrite
the program." It exists because the same artifact is edited in very different
trust settings: an optimizer you trust to polish descriptions should not be free
to change the wire schema of a tool other systems depend on, or to inject
arbitrary handler code. The default here is the full set; tighten it to match
your deployment's blast radius. Every refused edit is reported, so a policy that's
too tight surfaces as visible refusals rather than silent no-ops.
tools.json — a list of {name, description, parameters, examples, code?}.
scripts/abstract.py provides:
materialize(dir) — flatten the surface into named text components
(tool.<name>.description, .parameters, .examples) for a text optimizer.apply(dir, edits) — policy-enforced edits incl. schema/code/compose;
returns {changed, refused}.validate(dir) — schema well-formedness, empty-description and duplicate-name
checks.python scripts/check.py
python scripts/run.py --path <capability_dir> # candidate + policy + validity
references/concepts.md — the mental model (select vs.
fill, toolset design, the policy) with cited sources.references/examples.md — worked before/after edits.references/pitfalls.md — failure modes and how to detect them.references/optimizer-playbook.md — what the
authored optimizer INSTRUCTIONS must demand when tools is selected: the
existing-tool-code mandate, the depth mandate's tools wording, and the two-phase
(diagnose fan-out → implement fan-out → merge) subagent pattern. intake points
here rather than inlining it.Alternatives
huggingface/skills
AI demos and GPU compute with Gradio Spaces and Hugging Face Spaces ZeroGPU. Use when writing or reviewing code that uses `@spaces.GPU`, configuring `python_version` or `requirements.txt` for a ZeroGPU Space, or handling ZeroGPU-specific code constraints — pickle-based process isolation, `gr.State` semantics across the worker boundary, no `torch.compile` (use AoTI instead), CUDA wheel-only builds (no `nvcc` at build or runtime), large vs xlarge sizing, and dynamic duration callables. Make sure t
K-Dense-AI/scientific-agent-skills
Use when working directly with the `esm` Python SDK, ESM3 or ESMC model IDs, Forge/Biohub inference clients, or ESMFold2 folding workflows.
event4u-app/agent-config
ONLY when user asks for single-pass tech-stack detection or `agents/evidence/analysis/` write-up. Deep multi-pass audit → `universal-project-analysis`. Raw primitives → `project-analysis-core`.
mgiovani/cc-arsenal
Multi-agent review team: architecture, security, performance, testing, style, docs/UX, plus an adversary that cross-examines the other 6, for security-sensitive, architectural, or large PRs (15+ files) where a single-agent pass risks missing cross-cutting issues. Use for auth/payments/PII changes, schema/pattern changes, compliance sign-off, or when asked to 'get the review team on this' / 'multi-agent review' / 'thorough review before merge'. For a standard PR or a quick pre-merge check, use /r