feat: first-class skill packs on agents + ship gifsmith builtin
executus CI / test (push) Successful in 3m21s
executus CI / test (push) Successful in 3m21s
Lifts the 'an agent uses a SKILL.md pack' concept out of a host and into the harness: - run.Ports.SkillPacks (SkillPackActivator) — nil-safe port; the executor folds a loaded agent's pack catalog into the system prompt and adds a skill_use loader tool to the toolbox (uses the existing ra.SystemPrompt + toolbox seams) - run.RunnableAgent.SkillPacks + persona.Agent.SkillPacks (+ skill_packs YAML, extends-inherit, ToRunnable) — the Agent noun is now pack-aware - skillpack.Activator — the battery's default port impl (resolve names → packs → catalog + skill_use), with a per-run BundleStager factory the host plumbs; satisfies the port structurally (no import of run) - agentbuiltins: ships gifsmith, a portable focused GIF/MP4 render agent that uses the gif pack — references tool/tier/pack NAMES only, no host coupling A host now wires run.Ports.SkillPacks instead of carrying its own activation glue. Tests: Activator resolution + gifsmith loads through persona→RunnableAgent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
# gifsmith — a portable, focused render agent that makes animated GIFs/MP4s via
|
||||
# the `gif` skill pack. Shipped by executus (agentbuiltins), run by any host that
|
||||
# provides tools with these names, a `thinking` model tier, and the `gif` pack.
|
||||
# Nothing here is host-specific — the names are the contract the host binds.
|
||||
name: gifsmith
|
||||
description: >-
|
||||
Makes a funny animated GIF (or an MP4 when the piece is long or a GIF is too
|
||||
big) from a description, via the gif skill pack. A single-purpose render agent
|
||||
— use it for any request to draw/animate/gif something, including multi-minute
|
||||
bits about people or things that happened.
|
||||
model_tier: thinking
|
||||
system_prompt: |
|
||||
You make funny animated GIFs and MP4s from a description — often caricatures of
|
||||
the people in the channel or a bit about something that happened. Work by
|
||||
calling tools; do NOT introduce yourself or list capabilities.
|
||||
|
||||
Load the `gif` skill FIRST: call skill_use with name `gif` to get the full
|
||||
recipe (scene/cast planning, the code_exec workspace rules, the bundled encode
|
||||
helper, and the GIF-vs-MP4 size/length decision), then follow it exactly to
|
||||
render and deliver the result. The skill also bundles an encode helper that
|
||||
picks GIF vs MP4 and guarantees a Discord-playable MP4 — use it, don't hand-roll
|
||||
the encode.
|
||||
|
||||
Reference images: the render is blind to attachments, so YOU are the eyes —
|
||||
study any attached/linked image and weave its visual details into the frames.
|
||||
If you can't make it out, proceed from the words.
|
||||
low_level_tools:
|
||||
- code_exec
|
||||
- image_describe
|
||||
- send_attachments
|
||||
- file_get_metadata
|
||||
- file_save
|
||||
- think
|
||||
skill_packs:
|
||||
- gif
|
||||
execution_lane: animate
|
||||
max_iterations: 50
|
||||
max_tool_calls: 80
|
||||
max_runtime_seconds: 1800
|
||||
critic_enabled: true
|
||||
default_emoji: "🎬"
|
||||
state_react:
|
||||
__start__: "🎬"
|
||||
code_exec: "🐍"
|
||||
image_describe: "🖼️"
|
||||
think: "🧠"
|
||||
send_attachments: "📎"
|
||||
__end__: "✅"
|
||||
__error__: "❌"
|
||||
@@ -0,0 +1,24 @@
|
||||
// Package agentbuiltins ships executus's canonical builtin agent definitions as
|
||||
// an embedded filesystem. They are portable persona manifests
|
||||
// (agents/<name>/agent.yml): each references tool NAMES, a model-tier NAME, and
|
||||
// skill-pack names — the host binds those to implementations. Nothing here
|
||||
// imports a host or a battery, so any executus consumer can seed these via
|
||||
// persona.LoadBuiltinAgents (or its own loader that reads the same schema):
|
||||
//
|
||||
// persona.LoadBuiltinAgents(ctx, store, agentbuiltins.FS(), skillChecker)
|
||||
//
|
||||
// Ships:
|
||||
// - gifsmith — a focused GIF/MP4 render agent that uses the `gif` skill pack.
|
||||
package agentbuiltins
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
)
|
||||
|
||||
//go:embed agents
|
||||
var embedded embed.FS
|
||||
|
||||
// FS returns the builtin agents tree, rooted so that a loader finds each
|
||||
// definition at agents/<name>/agent.yml (the layout LoadBuiltinAgents expects).
|
||||
func FS() fs.FS { return embedded }
|
||||
@@ -0,0 +1,42 @@
|
||||
package agentbuiltins_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"gitea.stevedudenhoeffer.com/steve/executus/agentbuiltins"
|
||||
"gitea.stevedudenhoeffer.com/steve/executus/persona"
|
||||
)
|
||||
|
||||
// TestGifsmithLoads proves executus's shipped gifsmith manifest flows through
|
||||
// the persona loader and lowers into a RunnableAgent carrying the gif pack — the
|
||||
// path a host uses to dogfood it.
|
||||
func TestGifsmithLoads(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
store := persona.NewMemory()
|
||||
n, err := persona.LoadBuiltinAgents(ctx, store, agentbuiltins.FS(), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n < 1 {
|
||||
t.Fatalf("expected gifsmith seeded, got %d", n)
|
||||
}
|
||||
a, err := store.GetAgentByName(ctx, persona.BuiltinAgentOwnerID, "gifsmith")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(a.SkillPacks) != 1 || a.SkillPacks[0] != "gif" {
|
||||
t.Errorf("skill_packs = %v", a.SkillPacks)
|
||||
}
|
||||
if a.ModelTier != "thinking" {
|
||||
t.Errorf("model_tier = %q (want a portable tier name)", a.ModelTier)
|
||||
}
|
||||
if !slices.Contains(a.LowLevelTools, "code_exec") || !slices.Contains(a.LowLevelTools, "send_attachments") {
|
||||
t.Errorf("low_level_tools missing render/deliver tools: %v", a.LowLevelTools)
|
||||
}
|
||||
// The pack must survive the lowering the executor consumes.
|
||||
if ra := a.ToRunnable(); len(ra.SkillPacks) != 1 || ra.SkillPacks[0] != "gif" {
|
||||
t.Errorf("RunnableAgent.SkillPacks = %v", ra.SkillPacks)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user