Generic Agent + Summarizer Skill via Skillberry Store
This guide explains how to use Rossoctl's external skill registry support to:
- publish the example
summarizerskill to a running skillberry-store instance, - register the skill in Rossoctl as an external skill reference pointing to that registry,
- import the example
generic_agentand link the external skill, - and verify in chat that the skill is fetched from the registry at agent startup and used correctly.
This flow differs from the local skill demo: the skill files are never uploaded into Rossoctl. Instead, Rossoctl stores only a pointer (URL + metadata) to the skillberry-store instance. When the agent pod starts, an init container fetches the skill archive from the registry and mounts it at the same path that a local skill would occupy. The agent runtime is unaware of the difference.
Two ways to provide the registry
You can point Rossoctl at the skillberry-store in one of two ways:
-
In-cluster store (simplest).
--with-skillsdeploys a skillberry-store pod inside the cluster and auto-enables autosync against it — no external instance and no--skill-registry-allowed-hostsneeded (the in-cluster*.svcURL is trusted by the autosync loop). The store UI is browsable athttp://skillberry-store.<domain>:8080. Override the image with theSKILLBERRY_STORE_IMAGE/SKILLBERRY_STORE_TAGenv vars (default tag0.2.0). With this path, skip the external-instance prerequisites below and publish your skill to the in-cluster store (its API is reachable in-cluster athttp://skillberry-store.rossoctl-system.svc.cluster.local:8000). skillberry-store's plugins — which manage the skills in the store (creating, evaluating, optimizing, deduplicating, and security-scanning them) — call an LLM and read their configuration from environment variables on the store pod. To enable those plugins, inject the LLM provider/model and API keys viaskillberryStore.extraEnv— see Configuring skillberry-store Environment Variables. -
External instance (this guide's main flow). Run skillberry-store yourself somewhere reachable, register it as an external skill reference, and (for private/LAN addresses) allow-list it via
--skill-registry-allowed-hosts. The rest of this guide walks through this path.
What this demo shows
- The skill content lives in an external skillberry-store registry, not in a Rossoctl ConfigMap.
- Rossoctl holds a lightweight external skill reference (a ConfigMap with
rossoctl.io/source=external) instead of the full skill content. - At agent pod startup, an
alpine:3init container fetches the skill from the registry and mounts it under/app/skills/. - The agent's
SKILL_FOLDERSenv var is populated automatically, as in the local flow. - From the agent's perspective the skill is identical to a locally imported skill.
Prerequisites
Rossoctl
-
Rossoctl is installed and the UI is reachable, as described in
docs/install.md. -
You have access to a Rossoctl-enabled namespace, for example
team1. -
The cluster can build example agents from GitHub.
-
You have LLM credentials ready for the generic agent (
LLM_MODEL,LLM_API_BASE,LLM_API_KEY). -
Both
featureFlags.skillsandfeatureFlags.externalSkillsmust be enabled.When using the Kind setup script, use
--with-skills(enables both flags and auto-enables backend and UI):scripts/kind/setup-rossoctl.sh --with-skills --with-buildsTo also build images from source:
scripts/kind/setup-rossoctl.sh --with-skills --with-builds --build-images --skip-clusterWhen using the Ansible installer, add to your values file:
charts:rossoctl:values:featureFlags:skills: trueexternalSkills: trueWhen enabling on an already-running cluster with Helm:
helm upgrade rossoctl ./charts/rossoctl/ \--reuse-values \--set featureFlags.skills=true \--set featureFlags.externalSkills=true \-n rossoctl-system
Skillberry store
- A running instance of skillberry-store accessible at:
- UI:
http://localhost:8002/ - FastAPI / REST API:
http://localhost:8000/
- UI:
- You have credentials or access to publish a skill to that instance (follow skillberry-store's own onboarding documentation and CLI guide).
- Kind cluster note: the
sbsCLI andcurlcommands in this guide run from your workstation and usehttp://localhost:8000. However, the registry URL you register in Rossoctl (Step 2) is fetched by an init container running inside the Kind cluster — it cannot reachlocalhoston the host. Usehttp://host.docker.internal:8000(Docker Desktop / WSL2) or your host's LAN IP (e.g.http://192.168.1.10:8000) for that field. - Private/LAN registry note (SSRF allow-list): the backend validates registry URLs and rejects ones that resolve to private/internal addresses (RFC-1918, loopback, link-local) to prevent SSRF. A LAN IP like
192.168.1.10or an in-cluster*.svcname is private, so you must explicitly allow it via theSKILL_REGISTRY_ALLOWED_HOSTSsetting (comma-separated hostnames, IPs, or CIDRs). Empty by default — public registries need no configuration. Set it one of these ways:- Kind installer: pass
--skill-registry-allowed-hosts "192.168.1.10"(accepts a comma-separated list / CIDRs) toscripts/kind/setup-rossoctl.sh. - Helm: set
ui.backend.skillRegistryAllowedHosts(e.g."192.168.1.10"or"192.168.0.0/16"). - Existing deployment: set the
SKILL_REGISTRY_ALLOWED_HOSTSenv var on the backend and restart, e.g.kubectl set env deploy/rossoctl-backend -n rossoctl-system SKILL_REGISTRY_ALLOWED_HOSTS=192.168.1.10.
- Kind installer: pass
Repositories and paths used in this demo
| Resource | Value |
|---|---|
| Example agent repository | https://github.com/rossoctl/examples |
| Skill source path | skills/summarizer |
| Agent source path | a2a/generic_agent |
| Skillberry UI | http://localhost:8002/ |
Skillberry API (FastAPI / sbs CLI) | http://localhost:8000/ |
| Registry URL for Kind init container | http://host.docker.internal:8000 or host LAN IP |
| Skill name in registry | summarizer |
| Skill version | 1.0.0 |
Step 1: Publish the summarizer skill to skillberry-store
Clone the agent-examples repository and locate the summarizer skill:
git clone https://github.com/rossoctl/examples
cd agent-examples/skills/summarizer
ls
# SKILL.md (and any additional files)
Use curl to import the skill into skillberry-store via the POST /skills/import-anthropic endpoint:
curl -s -X POST "http://localhost:8000/skills/import-anthropic" \
-F "source_type=folder" \
-F "folder_path=/path/to/agent-examples/skills/summarizer" \
-F "treat_all_as_documents=true"
Replace /path/to/agent-examples with the actual path where you cloned the repository. A successful response looks like:
{
"success": true,
"message": "Successfully imported Anthropic skill 'summarizer' (created)",
"skill_name": "summarizer",
"tools_created": 29,
"snippets_created": 2
}
Optional form fields:
| Field | Default | Description |
|---|---|---|
snippet_mode | file | How text files are split: file (one snippet per file) or paragraph |
tags | [] | Additional tags to attach to all imported objects |
treat_all_as_documents | false | Treat all files as documents (set to true in this demo) |
After importing, verify the skill is visible in the skillberry-store UI at http://localhost:8002/.
You can also verify via the export endpoint, which returns a ZIP archive:
curl -fsSL "http://localhost:8000/skills/summarizer/export-anthropic" -o /tmp/test-summarizer.zip
unzip -l /tmp/test-summarizer.zip
# Expected: summarizer/SKILL.md and other skill files listed
Step 2: Register the external skill reference in the Rossoctl UI
The Rossoctl UI "From Registry" tab creates a lightweight ConfigMap that points to your skillberry-store instance. No skill content is uploaded.
-
Open the Rossoctl UI.
-
Navigate to Skills.
-
Click Import Skill.
-
Select the From Registry tab.
This tab is visible only when the
externalSkillsfeature flag is enabled. -
In Namespace, select the namespace you will also use for the agent, for example
team1. -
In Registry Type, select
skillberry. -
In Registry URL, enter the skillberry-store API URL that is reachable from inside the Kind cluster (not from your workstation). On Docker Desktop or WSL2 use:
http://host.docker.internal:8000If
host.docker.internaldoes not resolve in your environment, use your host's LAN IP instead (e.g.http://172.26.89.33:8000). The init container that fetches the skill archive at pod startup must be able to reach this URL.Important: The URL must include the
http://prefix (e.g.http://172.26.89.33:8000, not172.26.89.33:8000). The form shows a hint as a reminder.Once you enter a valid URL, the Skill Name in Registry field automatically becomes a combobox populated with all skills available in the registry. The remaining fields stay disabled until you select a skill.
-
In Skill Name in Registry, open the combobox and select
summarizer(or type to filter the list).As soon as you select a skill, the following fields are filled in automatically:
Field Auto-filled value Version skill version from the registry (e.g. 1.0.0)Display Name skill name (e.g. summarizer)Description skill description from the registry You can edit any auto-filled value before registering. Category is not populated automatically (skillberry does not have a category field) — enter
summarizationmanually if desired. -
Review the auto-filled fields and adjust if needed.
-
Click Register External Skill.
After the reference is created, the skill appears in the skill catalog with an External badge. If you open the skill detail page, you will see a Registry Information card rather than a file tree — the file content is not stored locally.
Alternative: register via API
If you prefer the API:
# Use the URL reachable from inside the Kind cluster, not localhost
curl -s -X POST "${ROSSOCTL_URL}/api/v1/skills/external" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{
"name": "summarizer",
"namespace": "team1",
"description": "Summarization skill for converting long source text into concise structured summaries.",
"category": "summarization",
"registryType": "skillberry",
"registryUrl": "http://host.docker.internal:8000",
"registrySkillName": "summarizer",
"registrySkillVersion": "1.0.0"
}'
Step 3: Import the generic agent in the UI
-
Navigate to Agents.
-
Click Import New Agent.
-
In Namespace, select the same namespace where you registered the skill.
-
Leave Deployment Method as Build from Source.
-
In Git Repository URL, use:
https://github.com/rossoctl/examples -
In Git Branch or Tag, use
main. -
In Select Agent, choose Generic Agent. This fills the source path with:
a2a/generic_agent -
Confirm the agent name. For this demo,
generic-agentis a good choice. -
Set Protocol to
a2a. -
Set Framework to
LangGraph.
Step 4: Configure the generic agent environment variables
In the Environment Variables section, provide the LLM configuration:
LLM_MODELLLM_API_BASELLM_API_KEY
Do not set SKILL_FOLDERS manually. Rossoctl sets it automatically based on the linked skills, regardless of whether they are local or external registry references.
Step 5: Link the external summarizer skill to the agent
In the Linked Skills section of the import form:
- Find the
summarizerskill (marked External) in the list. - Enable the checkbox for
summarizer.
Rossoctl records the skill linkage. At agent pod startup, an alpine:3 init container will:
- fetch
<registry-url>/skills/summarizer/export-anthropic(the URL registered in Step 2, e.g.http://host.docker.internal:8000/skills/summarizer/export-anthropic), - extract the archive to
/app/skills/summarizer/, - and allow the main agent container to mount the result read-only.
The agent receives SKILL_FOLDERS=/app/skills/summarizer automatically.
Step 6: Build and deploy the agent
- Review the remaining defaults.
- Click Create / Build & Deploy.
- Wait for the Shipwright build to complete.
- Open the agent details page when the deployment finishes.
Step 7: Verify that the skill was fetched at startup
On the agent details page:
- Confirm the agent status is healthy.
- Verify that
summarizerappears in the agent's listed skills.
To confirm the init container fetched the skill successfully, inspect the pod:
kubectl logs <agent-pod-name> -n team1 -c fetch-skill-0
# Expected output includes:
# Fetching summarizer from http://host.docker.internal:8000/skills/summarizer/export-anthropic
# OK: summarizer -> /app/skills/summarizer
You can also verify the mounted files and environment variable:
kubectl exec <agent-pod-name> -n team1 -- ls /app/skills/summarizer/
# Expected: SKILL.md (and any other published files)
kubectl exec <agent-pod-name> -n team1 -- env | grep SKILL_FOLDERS
# Expected: SKILL_FOLDERS=/app/skills/summarizer
This confirms the skill was fetched from the external registry and wired identically to a local skill.
Step 8: Open the chat and test the summarizer skill
From the agent details page, open the chat UI.
Paste the following demo prompt:
Use your summarizer skill to summarize the following project update into:
1. a one-sentence executive summary,
2. exactly 5 bullet points,
3. a short risk list,
4. and 3 clear action items.
Project update:
During the last two sprints, the platform team completed the first end-to-end integration between the Rossoctl UI and the example generic agent. The team also imported the summarizer skill into the namespace and linked it to the agent during the UI import flow. Initial testing showed that the agent can accept long-form text and respond with a concise structured summary. However, several follow-up items remain: the team needs to improve documentation, verify the build flow in a fresh namespace, and confirm that the agent card correctly displays linked skills after deployment. There is also an open concern that users may forget to provide the required LLM environment variables, which leads to startup failures that are not always obvious from the UI alone. If the remaining validation passes, the team plans to use this demo in the next stakeholder walkthrough to show how Rossoctl can manage both reusable skills and example agents through the same UI.
Expected result
A successful response should be a structured summary, not a free-form essay.
Executive summary:
The team successfully connected the Rossoctl UI, the generic agent, and the summarizer skill, and now needs to complete validation and documentation before using the flow in a stakeholder demo.
Key points:
- The team completed an end-to-end integration between the Rossoctl UI and the generic agent.
- The summarizer skill was registered from the skillberry-store and linked during agent import.
- Initial testing showed the agent can summarize long-form text into a concise structure.
- Documentation and fresh-namespace validation are still pending.
- Missing LLM environment variables remain a usability risk during startup.
Risks:
- Users may omit required LLM configuration.
- The skillberry-store instance must be reachable from the cluster at pod startup.
- Fresh-environment validation may reveal deployment issues.
Action items:
1. Finalize the step-by-step documentation.
2. Validate the full flow in a new namespace.
3. Confirm agent-card skill visibility before the stakeholder demo.
The wording does not need to match exactly. The structure and behavior should clearly reflect summarization rather than general chat.
How to tell that the skill is working
The skill is working if all of the following are true:
- the
summarizerskill is visible with an External badge in the skill catalog, - the
fetch-skill-0init container log shows a successful fetch from skillberry-store, /app/skills/summarizer/SKILL.mdexists in the agent pod,SKILL_FOLDERSis set to/app/skills/summarizerwithout manual configuration,- and the agent responds to the long-form prompt with a structured summary.
Recommended demo narrative
For a live demo:
- Show the skillberry-store UI at
http://localhost:8002/confirming thesummarizerskill is published, or runcurl -o /dev/null -w "%{http_code}" http://localhost:8000/skills/summarizer/export-anthropicto confirm200. - Show the Import Skill → From Registry tab. Enter the registry URL and watch the Skill Name in Registry field become a combobox populated from the registry. Select
summarizerand show the other fields auto-filling. - Point out the External badge in the skill catalog, the View ↗ link in the Registry column, and open the detail page to show the Registry Information card instead of a file tree.
- Show the Import New Agent page, select
a2a/generic_agent, and checksummarizerin Linked Skills. - After deployment, show the
kubectl logs ... -c fetch-skill-0output confirming the fetch. - Open chat and paste the long project-update prompt.
- Point out that the response is structured exactly as a summary, which demonstrates the external registry skill flow.
Troubleshooting
The "From Registry" tab is not visible
The tab is hidden when featureFlags.externalSkills is false. Verify both flags are enabled:
kubectl get deployment rossoctl-backend -n rossoctl-system \
-o jsonpath='{.spec.template.spec.containers[0].env}' \
| python3 -m json.tool | grep -A1 "FEATURE_FLAG_SKILLS\|FEATURE_FLAG_EXTERNAL"
If either flag shows "false", enable both with:
helm upgrade rossoctl ./charts/rossoctl/ \
--reuse-values \
--set featureFlags.skills=true \
--set featureFlags.externalSkills=true \
-n rossoctl-system
Wait for the pods to restart, then refresh the page. If you deployed with the Kind setup script, use --with-skills on the next run.
The skill reference was created but the agent pod fails to start
The init container (fetch-skill-0) could not reach the registry. Check:
kubectl logs <agent-pod-name> -n team1 -c fetch-skill-0
Common causes:
- The skillberry-store URL is not reachable from inside the cluster. The registered URL must be reachable from the Kind pod, not just from your workstation.
localhost:8000does not resolve inside a Kind pod — usehttp://host.docker.internal:8000(Docker Desktop / WSL2) or your host's LAN IP. Verify from a test pod in the same namespace:kubectl run -it --rm nettest --image=alpine --restart=Never -n team1 -- \wget -qO- http://host.docker.internal:8000/skills/summarizer/export-anthropic | wc -c - The skill does not exist in the registry. Verify from your workstation:
curl -o /dev/null -w "%{http_code}" "http://localhost:8000/skills/summarizer/export-anthropic"— expect200. - The downloaded archive is not a valid ZIP file. Verify the export endpoint returns a ZIP:
curl -fsSL "http://localhost:8000/skills/summarizer/export-anthropic" -o /tmp/test.zip && file /tmp/test.zip— should sayZip archive data.
The external skill does not appear in the Linked Skills list
Check that:
- the feature flags
ROSSOCTL_FEATURE_FLAG_SKILLSandROSSOCTL_FEATURE_FLAG_EXTERNAL_SKILLSare both true, - the external skill reference was created in the same namespace as the agent,
- and the skill appears in the skill catalog before opening the agent import form.
The agent deploys but responses are poor or fail
Check that LLM_MODEL, LLM_API_BASE, and LLM_API_KEY are set correctly and the model endpoint is reachable from the agent pod.
The skill appears to be linked but is not used
Check that:
- the init container completed successfully (see logs above),
SKILL_FOLDERSis set in the agent pod (kubectl exec ... env | grep SKILL_FOLDERS),- and the files under
/app/skills/summarizer/includeSKILL.md.
Cleanup
- Go to Agents and delete the generic agent.
- Go to Skills and delete the
summarizerexternal skill reference. - Optionally remove the skill from the skillberry-store registry if no longer needed.
Difference from the local skill demo
| Local skill demo | This demo | |
|---|---|---|
| Skill content stored in | Rossoctl ConfigMap (data: field) | skillberry-store archive |
| Rossoctl ConfigMap type | rossoctl.io/source absent (local) | rossoctl.io/source=external |
| Skill content visible in UI | File tree on skill detail page | Registry information card |
| Skill catalog badge | None | External |
| Pod skill delivery | ConfigMap volume mount | alpine:3 init container fetch |
| Registry reachability required | No | Yes, at pod startup |
| Feature flags required | featureFlags.skills | featureFlags.skills + featureFlags.externalSkills |
Related references
docs/demos/demo-generic-agent-skill.md— local skill variant of this demodocs/demos/demo-generic-agent.mddocs/skills.md— skills feature overview and feature flag configurationdocs/superpowers/specs/2026-05-27-external-skill-registries-design.md— design spec for the external skill registry feature- skillberry-store — the external skill registry used in this demo
docs/install.mddocs/local-models.md