Skip to content

Discover examples for remotely-loaded skills - #253

Merged
brandomr merged 3 commits into
devfrom
remote-skill-examples
Jul 22, 2026
Merged

Discover examples for remotely-loaded skills#253
brandomr merged 3 commits into
devfrom
remote-skill-examples

Conversation

@brandomr

Copy link
Copy Markdown
Contributor

Problem

A skill loaded from a URL exposes no examples at all. _discover_examples scans the examples/ directory, which only works for a local skill:

if source_type == "local" and base_path:
    ...
# For remote skills, examples must be declared in the frontmatter (not yet implemented).

So a remote skill gives the agent instructions and reference files, and silently drops every worked example the author shipped. That's the tier the agent most wants before writing code — and the loss is invisible. The prompt reports has_code_examples: false, which reads as "this skill has no examples" rather than "this skill's examples could not be seen".

Reproduced against two published skills served from raw.githubusercontent.com:

slug='rosetta'   source=remote  files(5)  examples(0)
slug='deepscale' source=remote  files(5)  examples(0)

Both ship four runnable examples.

Approach

Take examples from the body rather than from the filesystem.

Skill authors already publish an example listing as markdown links — the convention across skills I looked at is

- [examples/basic_fetch.py](examples/basic_fetch.py) — obs + hindcast fetch, save to NetCDF

and _build_skill_integration already has the parsed body in hand. A new extract_example_references() pulls (path, title, description) out of those links: titles from the link text (falling back to the filename when the author wrote the path as the text), descriptions from the text following the link.

Notably this costs no extra network requests — discovery stays free and content is still fetched on demand at tier 3. Declaring examples in frontmatter, the originally-sketched approach, would either need one request per example up front or duplicate every title and description into the frontmatter.

Local skills keep scanning the directory, which stays authoritative. This is additive: a remote skill with no example links behaves exactly as before.

Result

Same two skills, after:

== rosetta: 4 examples
   basic_fetch.py            desc='obs + hindcast fetch, save to NetCDF/GeoTIFF'
   multi_model_assemble.py   desc='`assemble()` roster → deepscale-ready arrays'
   shapefile_region.py       desc='country clipping, center vs cover'
   s2s_fetch.py              desc='sub-seasonal issuance + on-the-fly reforecasts'
   -> fetch examples/basic_fetch.py: 1916 chars OK
== deepscale: 4 examples
   end_to_end_forecast.py    desc='optimize → forecast → honest CV verification → PDF report'
   seasonal_mme_pipeline.py  desc='one-call multi-model MME with `seasonal_mme`'
   calibration.py            desc='eReg multi-model calibration + logistic/WVG index calibration'
   ensemble_and_reporting.py desc='strategies, safeguards, skill comparison, plots'
   -> fetch examples/end_to_end_forecast.py: 3029 chars OK

Tests

15 new tests covering the extractor (listing form, descriptive link text, separator stripping, dedup, nested paths, non-example links ignored) and end-to-end remote discovery (descriptions preserved, content not fetched during discovery, exactly one request made, examples not double-counted as file resources, skills without example links unaffected).

Full suite: 489 passed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01555XSwMPRxBZFAEsvubUMz

A skill loaded from a URL exposed no examples at all. `_discover_examples`
scanned the `examples/` directory, which only works for a local skill --
the remote branch was a comment saying examples "must be declared in the
frontmatter (not yet implemented)".

So a remote skill gave the agent instructions and reference files, and
silently dropped every worked example the author shipped. That is the tier
the agent most wants before writing code, and the loss is invisible: the
prompt reports `has_code_examples: false` and nothing indicates that the
examples exist but could not be seen.

Take them from the body instead of the filesystem. Skill authors already
publish an example listing as markdown links -- a bulleted `[examples/x.py]
(examples/x.py) - what it shows` is the convention -- and `_build_skill_
integration` already has the parsed body in hand. Titles come from the link
text, descriptions from the text following the link, and content is still
fetched on demand, so discovery costs no additional requests.

Local skills keep scanning the directory, which stays authoritative.

Verified against two published skills served from raw.githubusercontent.com:
all eight examples are now discovered with their descriptions intact, and
loading one fetches correctly from the skill's base URL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01555XSwMPRxBZFAEsvubUMz

@mattprintz mattprintz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch on a legitimate oversight. Suggested a potential different path below that I think is workable but would be cleaner and more maintainable overall.

Comment on lines +175 to +198
_EXAMPLE_LINK_PATTERN = re.compile(r'\[([^\]]*)\]\((examples/[^)\s]+)\)([^\n]*)')


def extract_example_references(body: str) -> list[tuple[str, str, str]]:
"""Extract examples declared as markdown links in the body.

Used for remote skills, where the ``examples/`` directory cannot be listed.
Local skills scan the directory instead, which stays authoritative.

Returns ``(relative_path, title, description)`` per example, deduplicated on
path and in document order. ``relative_path`` is relative to the skill root
(i.e. it retains the ``examples/`` prefix).
"""
examples: dict[str, tuple[str, str, str]] = {}
for match in _EXAMPLE_LINK_PATTERN.finditer(body):
link_text, path, trailing = match.group(1).strip(), match.group(2).strip(), match.group(3)
if path in examples:
continue
# Authors usually write the path as the link text; a filename reads
# better as a title than a repeated path does.
title = link_text if link_text and link_text != path else Path(path).name
description = trailing.strip().lstrip("-–—:*").strip()
examples[path] = (path, title, description)
return list(examples.values())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of manually extracting the examples separately, I think a better solution might be to remove the guard clause in the extract_file_references function above at lines 158-159.
This would keep the extraction consistent and that function is already being called and should handle this situation, I believe.

Doing so will likely mean that we have to dedupe examples detected via local path traversal (_discover_examples class method below, starting at line 507), but I think that should not be difficult.

Per review: drop the examples/ guard in extract_file_references rather than
adding a second regex pass over the same body, and dedupe the two example
sources where they meet.

Extraction is now one uniform pass; the caller decides what a path becomes.
_build_skill_integration routes examples/ paths to SkillExampleResources and
everything else to SkillFileResources, so examples still do not double as
reference files. A bare examples/ directory link names no file and is
dropped rather than becoming an unloadable resource. The backtick pattern
gained examples/ for the same consistency.

_discover_examples now takes the referenced paths and merges them with the
directory scan, keyed on filename, scan winning -- it carries a real parsed
title and description where a referenced path yields only a filename.

Losing the link glosses costs little: the agent must call
load_skill_instructions, which returns the whole body including the author's
own example listing, before it can ask for an example by name. Those
descriptions were duplicated context.

This also fixes local skills, which the first version did not. The scan
globs *.md, so a skill shipping examples/*.py was invisible whether loaded
locally or remotely. Both paths now see them.

487 passed. Verified against the two published skills: 4 examples each, none
leaking into file resources, content still fetched on demand.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01555XSwMPRxBZFAEsvubUMz
@brandomr

brandomr commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Good call — done in c8fe864. extract_example_references is gone.

Guard dropped from extract_file_references. _build_skill_integration routes examples/ paths to SkillExampleResource and the rest to SkillFileResource. _discover_examples merges the referenced paths with the directory scan on filename, scan winning since it has a real parsed title.

Two things your version catches that mine didn't:

  • Local skills had the same bug. The scan globs *.md, so examples/*.py was invisible locally too, not just remotely.
  • A bare examples/ link would have become a SkillFileResource that 404s once the guard came off. Dropped in the extractor now.

One loss worth flagging: I was scraping each link's trailing text into description. That's gone. Seems fine to me — load_skill_instructions returns the whole body including the author's example listing, and the agent has to call that before it can ask for an example by name, so the descriptions were already in context. Say the word if you'd rather keep them.

Tests: dropped TestExtractExampleReferences, inverted test_examples_paths_excluded, added TestExampleSourcesAreDeduped for the merge. 487 pass. Re-checked against the two published skills — 4 examples each, nothing leaking into file resources.

An example discovered from a reference in the body carries no title beyond
its own filename, so the listing rendered "- **basic_fetch.py**:
basic_fetch.py" -- which reads as a bug and spends tokens saying nothing.
Omit the title when it adds nothing to the filename.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01555XSwMPRxBZFAEsvubUMz

@mattprintz mattprintz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix looks good. Tested with the dump command and no issues.

@brandomr
brandomr merged commit 041381c into dev Jul 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants