feat(skillpack): lazy BundleStager for bundled files in skill_use
executus CI / test (pull_request) Successful in 2m19s

Replace Activate's stagedDir string with a BundleStager callback invoked
lazily inside skill_use: when the model loads a pack with bundled files, the
host stages them (mort: into run-scoped file storage) and the returned note is
appended to the body so the model knows how to reach them. A nil stager (or a
stager error) degrades gracefully to just listing the file names.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 20:56:05 -04:00
parent 9bb5d143f7
commit 29598df814
2 changed files with 49 additions and 22 deletions
+32 -16
View File
@@ -66,17 +66,26 @@ type skillUseArgs struct {
Name string `json:"name" description:"the exact name of the skill to load, from the Available skills list"` Name string `json:"name" description:"the exact name of the skill to load, from the Available skills list"`
} }
// BundleStager makes a pack's bundled files available to the current run and
// returns a short note the model can act on (e.g. where the files are and how to
// reference them). It is called LAZILY, inside the skill_use tool, so a pack's
// files are staged only when the model actually loads that pack — not for every
// subscribed pack on every run. A host implements it over its own file plumbing
// (mort saves the files to run-scoped storage and returns their file_ids). nil =
// no staging: skill_use just lists the bundled file names.
type BundleStager func(ctx context.Context, p *Pack) (string, error)
// Activate turns a set of resolved packs into a majordomo agent.Skill: its // Activate turns a set of resolved packs into a majordomo agent.Skill: its
// Instructions are the Catalog, and it contributes a single skill_use tool that // Instructions are the Catalog, and it contributes a single skill_use tool that
// returns a named pack's full body (progressive disclosure). Attach the result // returns a named pack's full body (progressive disclosure). Attach the result
// to an agent with agent.WithSkill. Returns nil when there are no packs, which // to an agent with agent.WithSkill. Returns nil when there are no packs, which
// agent.WithSkill tolerates (a nil skill contributes nothing). // agent.WithSkill tolerates (a nil skill contributes nothing).
// //
// stagedDir, if non-empty, is the directory a host has staged the packs' bundled // stager, if non-nil, is invoked when skill_use loads a pack with bundled files;
// files into (see Stage); skill_use appends the concrete path so the model knows // its returned note is appended to the body so the model knows how to reach the
// where to read scripts/references with its file tools. Leave it empty when the // staged scripts/references. A stager error degrades gracefully (the
// host has no staging. // instructions still return, with a note that the files are unavailable).
func Activate(packs []*Pack, stagedDir string) mdagent.Skill { func Activate(packs []*Pack, stager BundleStager) mdagent.Skill {
byName := make(map[string]*Pack, len(packs)) byName := make(map[string]*Pack, len(packs))
for _, p := range packs { for _, p := range packs {
if p != nil && p.Manifest != nil { if p != nil && p.Manifest != nil {
@@ -88,13 +97,23 @@ func Activate(packs []*Pack, stagedDir string) mdagent.Skill {
} }
tool := llm.DefineTool("skill_use", tool := llm.DefineTool("skill_use",
"Load the full instructions for a skill by name before doing a task it covers. Returns the skill's instructions and a list of any bundled files.", "Load the full instructions for a skill by name before doing a task it covers. Returns the skill's instructions and, if it has bundled files, how to access them.",
func(_ context.Context, args skillUseArgs) (any, error) { func(ctx context.Context, args skillUseArgs) (any, error) {
p, ok := byName[strings.TrimSpace(args.Name)] p, ok := byName[strings.TrimSpace(args.Name)]
if !ok { if !ok {
return fmt.Sprintf("No skill named %q. Use one of the names from the Available skills list.", args.Name), nil return fmt.Sprintf("No skill named %q. Use one of the names from the Available skills list.", args.Name), nil
} }
return renderPackBody(p, stagedDir), nil body := renderPackBody(p)
if stager != nil && len(p.Bundled) > 0 {
note, err := stager(ctx, p)
switch {
case err != nil:
body += "\n\n(bundled files could not be staged: " + err.Error() + ")"
case note != "":
body += "\n\n" + note
}
}
return body, nil
}) })
tb := llm.NewToolbox("skillpack", tool) tb := llm.NewToolbox("skillpack", tool)
@@ -104,20 +123,17 @@ func Activate(packs []*Pack, stagedDir string) mdagent.Skill {
) )
} }
// renderPackBody is what skill_use returns: the pack's instructions plus a // renderPackBody is the base skill_use payload: the pack's instructions plus, if
// pointer to its bundled files (with the staged path when known). // it has any, a list of its bundled file names. A stager (see Activate) appends
func renderPackBody(p *Pack, stagedDir string) string { // the concrete access note.
func renderPackBody(p *Pack) string {
if p == nil || p.Manifest == nil { if p == nil || p.Manifest == nil {
return "Error: invalid skill pack." return "Error: invalid skill pack."
} }
var b strings.Builder var b strings.Builder
fmt.Fprintf(&b, "# Skill: %s\n\n%s\n", p.Manifest.Name, p.Manifest.Body) fmt.Fprintf(&b, "# Skill: %s\n\n%s\n", p.Manifest.Name, p.Manifest.Body)
if len(p.Bundled) > 0 { if len(p.Bundled) > 0 {
b.WriteString("\nBundled files") b.WriteString("\nBundled files:\n")
if stagedDir != "" {
fmt.Fprintf(&b, " (under %s)", strings.TrimRight(stagedDir, "/")+"/"+p.Manifest.Name)
}
b.WriteString(":\n")
for _, f := range p.Bundled { for _, f := range p.Bundled {
fmt.Fprintf(&b, "- %s\n", f) fmt.Fprintf(&b, "- %s\n", f)
} }
+17 -6
View File
@@ -44,7 +44,12 @@ func TestActivate_SkillUseTool(t *testing.T) {
packs := []*Pack{ packs := []*Pack{
mustPack(t, "pdf", "Use pdfplumber.", map[string]string{"scripts/x.py": "print()"}), mustPack(t, "pdf", "Use pdfplumber.", map[string]string{"scripts/x.py": "print()"}),
} }
sk := Activate(packs, "/stage") staged := 0
stager := func(_ context.Context, p *Pack) (string, error) {
staged++
return "staged " + p.Manifest.Name + " (file_id=abc)", nil
}
sk := Activate(packs, stager)
if sk == nil { if sk == nil {
t.Fatal("expected a non-nil skill") t.Fatal("expected a non-nil skill")
} }
@@ -56,6 +61,9 @@ func TestActivate_SkillUseTool(t *testing.T) {
if !ok { if !ok {
t.Fatal("skill_use tool missing from toolbox") t.Fatal("skill_use tool missing from toolbox")
} }
if staged != 0 {
t.Error("stager must be lazy — not called until skill_use runs")
}
// load an existing pack // load an existing pack
out, err := tool.Handler(ctx, json.RawMessage(`{"name":"pdf"}`)) out, err := tool.Handler(ctx, json.RawMessage(`{"name":"pdf"}`))
@@ -66,8 +74,11 @@ func TestActivate_SkillUseTool(t *testing.T) {
if !strings.Contains(body, "Use pdfplumber.") { if !strings.Contains(body, "Use pdfplumber.") {
t.Errorf("skill_use body missing instructions: %q", body) t.Errorf("skill_use body missing instructions: %q", body)
} }
if !strings.Contains(body, "scripts/x.py") || !strings.Contains(body, "/stage/pdf") { if !strings.Contains(body, "scripts/x.py") {
t.Errorf("skill_use should list bundled files under the staged dir: %q", body) t.Errorf("skill_use should list bundled files: %q", body)
}
if staged != 1 || !strings.Contains(body, "file_id=abc") {
t.Errorf("stager should run on load and its note append to the body: staged=%d body=%q", staged, body)
} }
// unknown pack returns guidance, not an error // unknown pack returns guidance, not an error
@@ -81,7 +92,7 @@ func TestActivate_SkillUseTool(t *testing.T) {
} }
func TestActivate_Empty(t *testing.T) { func TestActivate_Empty(t *testing.T) {
if Activate(nil, "") != nil { if Activate(nil, nil) != nil {
t.Error("no packs should activate to a nil skill") t.Error("no packs should activate to a nil skill")
} }
} }
@@ -92,7 +103,7 @@ func TestNilPackElementsAreSafe(t *testing.T) {
if got := Catalog(packs); !strings.Contains(got, "real") { if got := Catalog(packs); !strings.Contains(got, "real") {
t.Errorf("catalog should include the valid pack and skip nils: %q", got) t.Errorf("catalog should include the valid pack and skip nils: %q", got)
} }
sk := Activate(packs, "") sk := Activate(packs, nil)
if sk == nil { if sk == nil {
t.Fatal("a valid pack among nils should still activate") t.Fatal("a valid pack among nils should still activate")
} }
@@ -100,7 +111,7 @@ func TestNilPackElementsAreSafe(t *testing.T) {
t.Error("skill_use missing") t.Error("skill_use missing")
} }
// All-nil activates to nothing rather than panicking. // All-nil activates to nothing rather than panicking.
if Activate([]*Pack{nil, {Manifest: nil}}, "") != nil { if Activate([]*Pack{nil, {Manifest: nil}}, nil) != nil {
t.Error("only-nil packs should activate to nil") t.Error("only-nil packs should activate to nil")
} }
} }