For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Add skills to agents
Learn how to add skills to your agents to guide their behavior and tool usage.
Skills are descriptions of capabilities that help agents act more autonomously. They guide the agent’s tool usage and planning by orienting responses toward goals rather than just reacting to prompts.
In this guide, you learn how to add container-based skills to your agents in kagent.
Tip
Want to containerize and manage your skills? Try out the agentregistry project to build and push skills to a secure, AI-first container registry. Agentregistry also has a repo of example skills based on Claude Skills that you can use as a starting point.
Before you begin
Install kagent by following the quick start guide.
Review the concepts of agents and skills in kagent.
Container-based skills
Container-based skills are executable skill implementations packaged as container images. These skills contain instructions, scripts, and other resources that the agent can discover and use at runtime. This way, you can reuse skills across agents.
Step 1: Build a skill container
To create a container-based skill, package your skill files into a container image. This example creates a skill named k8s-deploy-skill that can deploy simple applications to Kubernetes. The skill takes an app name and container image (and optional replica count and port) from the user, runs a Python script that generates a combined Deployment and Service manifest, and then applies the generated manifest to the cluster.
Create a skill directory with your skill files.
mkdir k8s-deploy-skill cd k8s-deploy-skillCreate a
SKILL.mdfile with skill metadata and instructions. The file must start with---and include YAML frontmatter with the skill name and description, followed by---, then detailed instructions for the agent.cat > SKILL.md <<'EOF' --- name: k8s-deploy-skill description: Deploy simple applications to Kubernetes with customizable replicas and port --- # Kubernetes simple deploy skill Use this skill when users want to deploy a basic app on the Kubernetes cluster. ## Instructions - Expect the user to provide the name for an app they wish to deploy, along with a docker image reference. Optionally they may supply number of replicas and port number, but these are not required, and have defaults. - Call the script `scripts/deploy-app.py` passing the supplied name, image, and optional parameters (# of replicas and port number) if supplied, in that order. - The script generates a correct two-resource manifest (Deployment + Service) and writes it to the file `temp-manifest.yaml`. You, the **agent**, are expected to apply the generated manifest `temp-manifest.yaml` against the current Kubernetes context. ## Example User: Deploy an app called "nginx" using image "docker/nginx" with 2 replicas on port 8080. Agent: Invokes `scripts/deploy-app.py nginx docker/nginx 2 8080` The skill creates a manifest named `temp-manifest.yaml` consisting of a Deployment + Service in one shot. The agent in turn applies the generated temp-manifest.yaml to the cluster. EOFThe agent learns how to use the skill by reading this file. The instructions tell the agent when to use the skill, what parameters to expect, and how to invoke the scripts.
Add any scripts or resources your skill needs.
mkdir scripts cat > scripts/deploy-app.py <<'EOF' #!/usr/bin/env python3 # deploy-app.py import sys from pathlib import Path from textwrap import dedent def generate_manifest(app_name, image, replicas=1, port=80): """Generate valid Kubernetes YAML using only built-in Python""" manifest = f"""\ apiVersion: apps/v1 kind: Deployment metadata: name: {app_name} labels: app: {app_name} spec: replicas: {replicas} selector: matchLabels: app: {app_name} template: metadata: labels: app: {app_name} spec: containers: - name: {app_name} image: {image} ports: - containerPort: {port} --- apiVersion: v1 kind: Service metadata: name: {app_name} labels: app: {app_name} spec: type: ClusterIP selector: app: {app_name} ports: - port: 80 targetPort: {port} protocol: TCP """ # Clean dedent + write clean_yaml = dedent(manifest).strip() + "\n" file_path = Path("temp-manifest.yaml") file_path.write_text(clean_yaml, encoding="utf-8") return str(file_path) def print_usage(): print("""Kubernetes Zero-Dependency Deploy Usage: python deploy-app.py <name> <image> [replicas] [port] Examples: python deploy-app.py web nginx:latest python deploy-app.py api ghcr.io/myorg/api:v2 3 5000 python deploy-app.py redis redis:7.2 1 6379 No pip, no yaml, no problem. """) if __name__ == "__main__": args = sys.argv[1:] if not args or "-h" in args or "--help" in args: print_usage() sys.exit(0) if len(args) < 2: print("Error: Need <name> <image>") print_usage() sys.exit(1) app_name = args[0] image = args[1] replicas = 1 port = 80 # Parse optional positional numeric args: [replicas] [port] if len(args) > 2: if args[2].isdigit(): replicas = int(args[2]) else: print(f"Error: replicas must be a number, got '{args[2]}'") sys.exit(1) if len(args) > 3: if args[3].isdigit(): port = int(args[3]) else: print(f"Error: port must be a number, got '{args[3]}'") sys.exit(1) if len(args) > 4: print("Error: Too many arguments") print_usage() sys.exit(1) # Optional: validate reasonable ranges if replicas < 1: print("Error: replicas must be >= 1") sys.exit(1) if not (1 <= port <= 65535): print("Error: port must be between 1 and 65535") sys.exit(1) print(f"Deploying {app_name}") print(f" Image: {image}") print(f" Replicas: {replicas}") print(f" Container port: {port} → Service port: 80") print() path = generate_manifest(app_name, image, replicas, port) print(f"Manifest saved → {path}") print() print("Next:") print(f" kubectl apply -f {path}") EOF chmod +x scripts/deploy-app.pyThe scripts perform the actual work. In this example,
deploy-app.pygenerates Kubernetes manifests based on the parameters provided.Create a Dockerfile.
cat > Dockerfile <<'EOF' FROM scratch COPY . / EOFFor local testing, start a Docker registry on your local host. Before building and pushing to a localhost registry, check if you already have one running.
docker ps | grep registry- If you see a registry container, note the port mapping (for example,
127.0.0.1:5001->5000/tcpmeans the registry is accessible on port 5001). - If no registry is running, start one.
docker run -d -p 5000:5000 --restart=always --name local-registry registry:2If your registry is on a different port (like 5001), use that port in the following commands instead of 5000.
- If you see a registry container, note the port mapping (for example,
Build and push the image to a container registry. You can push skill containers to any container registry:
- Localhost registry:
localhost:PORT/skill-name:tag - Docker Hub:
docker.io/username/skill-name:tag - GitHub Container Registry:
ghcr.io/username/skill-name:tag - Google Container Registry:
gcr.io/project/skill-name:tag - Amazon ECR:
123456789012.dkr.ecr.region.amazonaws.com/skill-name:tag - Any private registry:
registry.example.com/skill-name:tag
docker build -t localhost:5000/k8s-deploy-skill:latest . docker push localhost:5000/k8s-deploy-skill:latest- Localhost registry:
Step 2: Use container-based skills in an agent
To load container-based skills into your agent, reference them in the spec.skills.refs field.
Tip
For development and testing such as in a local Docker registry, you can use the insecureSkipVerify option. Note that for Kind clusters, use kind-registry:5000 instead of localhost:5000.
kubectl apply -f - <<EOF
apiVersion: kagent.dev/v1alpha2
kind: Agent
metadata:
name: k8s-assistant-with-skills
namespace: kagent
spec:
description: A Kubernetes AI agent with deployment skills
type: Declarative
skills:
# Only for development/testing (e.g., localhost registry)
insecureSkipVerify: true
refs:
# For Kind clusters, use kind-registry:5000 instead of localhost:5000
- kind-registry:5000/k8s-deploy-skill:latest
declarative:
modelConfig: default-model-config
stream: true
tools:
- type: McpServer
mcpServer:
name: kagent-tool-server
kind: RemoteMCPServer
toolNames:
- k8s_get_resources
- k8s_describe_resource
- k8s_apply_manifest
systemMessage: |
You are a Kubernetes assistant that helps users deploy and manage applications.
You have access to skills that can help automate common tasks.
EOFWhen the agent starts, kagent automatically:
- Pulls the skill images using an init container.
- Extracts the skill files to
/skillsin the agent container. - Registers a tool with the name of the skill, plus tools
read_file,write_file,edit_file,bashwhich the agent can use to operate on files or run commands inside the skill folder
The agent can then discover and load skills using the skill’s tool, which reads the SKILL.md files and makes the skill instructions available to the LLM.
Step 3: Test container-based skills
After creating the agent, test it with queries that match your skills.
Ask the agent what skills it has.
kagent invoke --agent k8s-assistant-with-skills --task "What skills do you have?"Example output:
{"artifacts":[{"artifactId":"e6c480b4-244c-425a-a601-f6b1d8c6c556","parts":[{"kind":"text","text":"I have access to the following skill:\n\n**k8s-deploy-skill** - A skill that helps deploy basic apps on Kubernetes cluster with generated manifests\n\nThis skill provides specialized capabilities for deploying applications to Kubernetes clusters. It can help generate and apply Kubernetes manifests to get your apps up and running.\n\nAdditionally, I have access to several Kubernetes management tools that allow me to:\n- **Get Kubernetes resources** - Query and list pods, services, deployments, and other resources\n- **Describe Kubernetes resources** - Get detailed information about specific resources\n- **Apply manifests** - Deploy YAML manifests to the cluster\n\nWould you like me to help you deploy an application or manage your Kubernetes cluster?"}]}],"contextId":"6d26a8e8-897c-41f3-a95b-09f48a83250c","history":[{"contextId":"6d26a8e8-897c-41f3-a95b-09f48a83250c","kind":"message","messageId":"msg-669637fe-432c-499f-8ed4-f702c6c0eb7a","parts":[{"kind":"text","text":"What skills do you have?"}],"role":"user","taskId":"f074f718-4d79-4546-a6d7-546d40f7a2ea"},{"contextId":"6d26a8e8-897c-41f3-a95b-09f48a83250c","kind":"message","messageId":"msg-669637fe-432c-499f-8ed4-f702c6c0eb7a","parts":[{"kind":"text","text":"What skills do you have?"}],"role":"user","taskId":"f074f718-4d79-4546-a6d7-546d40f7a2ea"},{"kind":"message","messageId":"c8e68a8c-196d-4f4c-a26a-05f05f351eb7","metadata":{"adk_partial":false},"parts":[{"kind":"text","text":"I have access to the following skill:\n\n**k8s-deploy-skill** - A skill that helps deploy basic apps on Kubernetes cluster with generated manifests\n\nThis skill provides specialized capabilities for deploying applications to Kubernetes clusters. It can help generate and apply Kubernetes manifests to get your apps up and running.\n\nAdditionally, I have access to several Kubernetes management tools that allow me to:\n- **Get Kubernetes resources** - Query and list pods, services, deployments, and other resources\n- **Describe Kubernetes resources** - Get detailed information about specific resources\n- **Apply manifests** - Deploy YAML manifests to the cluster\n\nWould you like me to help you deploy an application or manage your Kubernetes cluster?"}],"role":"agent"}],"id":"f074f718-4d79-4546-a6d7-546d40f7a2ea","kind":"task","metadata":{"kagent_app_name":"kagent__NS__k8s_assistant_with_skills","kagent_author":"k8s_assistant_with_skills","kagent_invocation_id":"e-be6fb35c-b768-4581-89ad-97874582553e","kagent_session_id":"6d26a8e8-897c-41f3-a95b-09f48a83250c","kagent_usage_metadata":{"candidatesTokenCount":159,"promptTokenCount":2358,"totalTokenCount":2517},"kagent_user_id":"admin@kagent.dev"},"status":{"state":"completed","timestamp":"2026-02-02T20:37:55.041398+00:00"}}Invoke a skill, such as by asking it to deploy an app.
kagent invoke --agent k8s-assistant-with-skills --task "Use your skill to deploy an app named 'httpbin' using the image 'docker.io/mccutchen/go-httpbin:v2.15.0' on port 8080"The agent:
- Reviews the instructions in the skill’s
SKILL.mdfile. - Invokes the appropriate script with the correct parameters.
- Uses its tools to apply the generated resources (in this case, applying the Kubernetes manifest).
Example output:
{"artifacts":[{"artifactId":"9f7ad622-9e1a-4b6e-8c59-7b33846e6245","parts":[{"kind":"text","text":"The app named 'httpbin' has been deployed using the image 'docker.io/mccutchen/go-httpbin:v2.15.0' on port 8080. A deployment and a corresponding service have been created. Let me know if you need any other assistance with this deployment."}]}],"contextId":"6d25b097-ab63-4f9b-8c37-7481fe9a1098","history":[{"contextId":"6d25b097-ab63-4f9b-8c37-7481fe9a1098","kind":"message","messageId":"msg-7e6a6435-997b-4afa-9f63-2777ad44a154","parts":[{"kind":"text","text":"Use your skill to deploy an app named 'httpbin' using the image 'docker.io/mccutchen/go-httpbin:v2.15.0' on port 8080"}],"role":"user","taskId":"3020e09e-3e9b-4840-a805-feb9817d20a2"},{"contextId":"6d25b097-ab63-4f9b-8c37-7481fe9a1098","kind":"message","messageId":"msg-7e6a6435-997b-4afa-9f63-2777ad44a154","parts":[{"kind":"text","text":"Use your skill to deploy an app named 'httpbin' using the image 'docker.io/mccutchen/go-httpbin:v2.15.0' on port 8080"}],"role":"user","taskId":"3020e09e-3e9b-4840-a805-feb9817d20a2"},{"kind":"message","messageId":"114436b5-1b9e-4191-aabc-cc4f1db6f6a0","parts":[{"kind":"data","data":{"args":{"manifest":"apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: httpbin\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: httpbin\n template:\n metadata:\n labels:\n app: httpbin\n spec:\n containers:\n - name: httpbin\n image: docker.io/mccutchen/go-httpbin:v2.15.0\n ports:\n - containerPort: 8080\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: httpbin\nspec:\n selector:\n app: httpbin\n ports:\n - protocol: TCP\n port: 8080\n targetPort: 8080\n type: ClusterIP\n"},"id":"call_PdIQF51hPu1iBcOt3v1DkOzC","name":"k8s_apply_manifest"},"metadata":{"kagent_type":"function_call"}}],"role":"agent"},{"kind":"message","messageId":"1279457b-137b-4730-a1be-5dbe2985973b","parts":[{"kind":"data","data":{"id":"call_PdIQF51hPu1iBcOt3v1DkOzC","name":"k8s_apply_manifest","response":{"result":{"content":[{"text":"deployment.apps/httpbin created\nservice/httpbin created\n","type":"text"}],"isError":false}}},"metadata":{"kagent_type":"function_response"}}],"role":"agent"},{"kind":"message","messageId":"aefb1f07-3258-46bb-b078-515a9a6f08e5","parts":[{"kind":"text","text":"The app named 'httpbin' has been deployed using the image 'docker.io/mccutchen/go-httpbin:v2.15.0' on port 8080. A deployment and a corresponding service have been created. Let me know if you need any other assistance with this deployment."}],"role":"agent"}],"id":"3020e09e-3e9b-4840-a805-feb9817d20a2","kind":"task","metadata":{"kagent_app_name":"kagent__NS__k8s_assistant_with_skills","kagent_author":"k8s_assistant_with_skills","kagent_invocation_id":"e-b8f3e41b-a741-4338-b19b-f3a46ca33826","kagent_session_id":"6d25b097-ab63-4f9b-8c37-7481fe9a1098","kagent_usage_metadata":{"candidatesTokenCount":60,"promptTokenCount":1505,"totalTokenCount":1565},"kagent_user_id":"admin@kagent.dev"},"status":{"state":"completed","timestamp":"2025-11-21T22:14:33.755060+00:00"}}- Reviews the instructions in the skill’s
Check that the
httpbinapp was deployed successfully.kubectl get pods --namespace kagent | grep httpbinExample output:
httpbin-b8b86ff46-rn7mf 1/1 Running 0 2m16s
Cleanup
When you’re done, you can clean up the resources that you created.
Delete the agents that you created.
kubectl delete agent k8s-assistant-with-skills -n kagentClean up any applications that were deployed during testing, such as the
httpbinapp.kubectl delete deployment httpbin -n kagent kubectl delete service httpbin -n kagentRemove the skill directory and files that you created.
cd .. rm -rf k8s-deploy-skillOptionally, remove the Docker image and registry that you used for local testing.
docker rmi localhost:5000/k8s-deploy-skill:latest docker stop local-registry docker rm local-registry