Finalize Your Dapr Skill
Complete and test your dapr-deployment skill for production use, adding safety guardrails and validating coverage across all building blocks
- Status
- stable
- Trust
- unverified
- Approved
- ag-archive/0.1.0 ·
You've built a dapr-deployment skill in Lesson 0 and refined it through nine lessons. Each lesson added patterns: sidecar architecture, building blocks vs components, Helm deployment, state management, pub/sub messaging, service invocation, bindings, the Jobs API, secrets, and configuration.
Now it's time to make that skill production-ready.
A skill isn't complete when it covers all the topics. It's complete when it helps you avoid the mistakes you'd make without it. This lesson focuses on three things: testing your skill against real prompts, adding safety guardrails that prevent production disasters, and documenting the errors you'll encounter so you can fix them quickly.
Review: What Your Skill Should Cover
Throughout this chapter, you've added patterns to your skill after each lesson. Here's what a complete dapr-deployment skill should include:
| Lesson | Pattern Added | Check Your Skill |
|---|---|---|
| L01 | Sidecar architecture explanation | Translator analogy, daprd ports (3500/50001), Kubernetes annotations |
| L02 | Building blocks vs components distinction | APIs vs implementations, component YAML structure, backend swapping |
| L03 | Helm deployment + state patterns | Helm commands for Dapr 1.14+, state component YAML, ETag concurrency |
| L04 | Service invocation patterns | invoke_method() usage, app-id discovery, mTLS automatic |
| L05 | Pub/Sub patterns | publish_event(), subscription decorators, CloudEvents format |
| L06 | Binding patterns | Input bindings (triggers), output bindings (external calls) |
| L07 | Jobs API patterns | Job creation, scheduling, one-time vs recurring |
| L08 | Secrets/config patterns | get_secret(), secrets component, configuration subscriptions |
| L09 | Complete integration example | Full FastAPI app with state + pub/sub + invoke |
Open your skill file and check each row. If something's missing, this is the lesson to add it.
Test Your Skill Against Production Prompts
A skill that only works for the examples you learned from isn't production-ready. Test it against prompts that simulate real deployment scenarios.
Test Prompt 1: Kubernetes Deployment
Using my dapr-deployment skill, deploy Dapr 1.14 on a fresh Kubernetes cluster.
Show me the Helm commands and how to verify all control plane pods are running.Expected skill output should include:
# Add Dapr Helm repo
helm repo add dapr https://dapr.github.io/helm-charts/
helm repo update
# Install Dapr control plane
helm upgrade --install dapr dapr/dapr \
--version=1.14.0 \
--namespace dapr-system \
--create-namespace \
--wait
# Verify installation
kubectl get pods -n dapr-systemPlus verification that you see: dapr-operator, dapr-sidecar-injector, dapr-sentry, dapr-placement-server, dapr-scheduler-server.
If your skill fails this test: Add the Helm deployment section from Lesson 03.
Test Prompt 2: State Management
Using my dapr-deployment skill, add state management to my FastAPI app.
I need to save and retrieve task objects using Redis as the backend.
Show me the component YAML and Python code.Expected skill output should include:
State component YAML:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.redis
version: v1
metadata:
- name: redisHost
value: redis-master.default.svc.cluster.local:6379Python code using DaprClient:
from dapr.clients import DaprClient
import json
with DaprClient() as client:
# Save state
client.save_state(
store_name='statestore',
key='task-123',
value=json.dumps({'title': 'Buy groceries', 'status': 'pending'})
)
# Get state
state = client.get_state(store_name='statestore', key='task-123')
task = json.loads(state.data) if state.data else NoneIf your skill fails this test: Add the state management patterns from Lesson 03.
Test Prompt 3: Pub/Sub Setup
Using my dapr-deployment skill, set up pub/sub messaging for my FastAPI service.
I need to publish task events and subscribe to them in another service.Expected skill output should include:
Pub/sub component YAML:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
spec:
type: pubsub.redis
version: v1
metadata:
- name: redisHost
value: redis-master.default.svc.cluster.local:6379Publishing code:
from dapr.clients import DaprClient
import json
with DaprClient() as client:
client.publish_event(
pubsub_name='pubsub',
topic_name='task-events',
data=json.dumps({'event_type': 'task.created', 'task_id': 'task-123'}),
data_content_type='application/json'
)Subscription code:
from fastapi import FastAPI
from dapr.ext.fastapi import DaprApp
app = FastAPI()
dapr_app = DaprApp(app)
@dapr_app.subscribe(pubsub='pubsub', topic='task-events')
async def handle_task_event(event_data: dict):
print(f"Received: {event_data}")
return {"status": "SUCCESS"}If your skill fails this test: Add the pub/sub patterns from Lesson 05.
Test Prompt 4: Scheduled Job
Using my dapr-deployment skill, schedule a recurring cleanup job that runs
every hour to remove completed tasks older than 7 days.Expected skill output should include:
Jobs API usage:
from dapr.clients import DaprClient
with DaprClient() as client:
# Schedule recurring job
client.start_workflow(
workflow_component='dapr',
workflow_name='cleanup-job',
input={'retention_days': 7}
)Or the Jobs API endpoint pattern:
POST http://localhost:3500/v1.0/jobs/cleanup-old-tasks
Content-Type: application/json
{
"schedule": "@every 1h",
"data": {"retention_days": 7}
}If your skill fails this test: Add the Jobs API patterns from Lesson 07.
Test Prompt 5: Secrets Configuration
Using my dapr-deployment skill, configure my FastAPI service to retrieve
API keys from Kubernetes secrets instead of environment variables.Expected skill output should include:
Secrets component YAML:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: kubernetes-secrets
spec:
type: secretstores.kubernetes
version: v1
metadata: []Python code:
from dapr.clients import DaprClient
with DaprClient() as client:
secret = client.get_secret(
store_name='kubernetes-secrets',
key='api-credentials'
)
api_key = secret.secret.get('api-key')If your skill fails this test: Add the secrets management patterns from Lesson 08.
Add Safety Guardrails
Your skill should prevent production mistakes, not just show working patterns. Add these guardrails to your dapr-deployment skill.
NEVER
Add a "Safety: NEVER" section to your skill:
## Safety: NEVER
- **Call Dapr before sidecar is ready** - Your app will get connection refused errors. Always wait for sidecar health check.
- **Hardcode component names** - Use configuration or environment variables. Component names may differ between environments.
- **Skip error handling for Dapr API calls** - Dapr calls can fail (sidecar not ready, component misconfigured, backend unavailable). Always wrap in try/except.
- **Store sensitive data in state without encryption** - State stores are not encrypted by default. Use secrets component for credentials, or enable encryption at the component level.
- **Expose Dapr HTTP/gRPC ports externally** - Dapr's sidecar ports (3500, 50001) are for internal pod communication only. External access bypasses mTLS.
- **Use `dapr.io/app-port` for gRPC apps without specifying protocol** - If your app uses gRPC, set `dapr.io/app-protocol: "grpc"` or Dapr will send HTTP to your gRPC server.ALWAYS
Add a "Safety: ALWAYS" section to your skill:
## Safety: ALWAYS
- **Wait for sidecar readiness** before making Dapr calls:
```python
import httpx
import asyncio
async def wait_for_sidecar(timeout: int = 30):
"""Wait for Dapr sidecar to be ready."""
async with httpx.AsyncClient() as client:
for _ in range(timeout):
try:
response = await client.get("http://localhost:3500/v1.0/healthz")
if response.status_code == 204:
return True
except httpx.ConnectError:
pass
await asyncio.sleep(1)
raise RuntimeError("Dapr sidecar not ready")-
Use secrets component for credentials - Never put passwords in component YAML. Use
secretKeyRef:metadata: - name: redisPassword secretKeyRef: name: redis-secret key: password -
Enable mTLS in production - Dapr enables mTLS by default when Sentry is running. Verify with:
kubectl get pods -n dapr-system | grep sentry -
Configure retry policies for resilience:
apiVersion: dapr.io/v1alpha1 kind: Resiliency metadata: name: myresiliency spec: policies: retries: myRetryPolicy: policy: constant duration: 1s maxRetries: 3 -
Set resource limits on sidecar to prevent resource contention:
annotations: dapr.io/sidecar-cpu-limit: "500m" dapr.io/sidecar-memory-limit: "256Mi"
---
## Common Errors Reference
Add this error table to your skill. When something breaks, this is the first place you'll look.
```markdown
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `ERR_STATE_STORE_NOT_FOUND` | State component not configured or not in same namespace | Apply component YAML: `kubectl apply -f components/statestore.yaml` |
| `ERR_PUBSUB_NOT_FOUND` | Pub/sub component not configured | Apply component YAML: `kubectl apply -f components/pubsub.yaml` |
| `connection refused :3500` | Sidecar not ready when app starts | Add startup probe or wait for `/v1.0/healthz` before Dapr calls |
| `ERR_DIRECT_INVOKE` | Target app-id not found | Check target has `dapr.io/app-id` annotation and is running |
| `DEADLINE_EXCEEDED` | Request timeout | Increase timeout or check if target service is overloaded |
| `sidecar not found` | Sidecar injection not enabled | Check `dapr.io/enabled: "true"` annotation and namespace has injection enabled |
| `ERR_SECRET_STORE_NOT_FOUND` | Secrets component not configured | Apply secrets component YAML |
| `ERR_PUBSUB_FORBIDDEN` | App not in component's scope | Add app-id to component's `scopes` list |Final Validation: Complete Integration Test
Run this prompt against your skill as a final validation:
Using my dapr-deployment skill, generate a complete Dapr setup for:
- A FastAPI service that saves tasks to state store
- Publishes events to pub/sub when tasks are created
- Calls a notification service via service invocation
- Schedules a daily cleanup job
- Gets API keys from Kubernetes secrets
Show all component YAMLs, Python code, and Kubernetes deployment manifest.A production-ready skill should generate:
- Component YAMLs: statestore, pubsub, kubernetes-secrets
- Python code: Complete FastAPI app with DaprClient
- Kubernetes manifest: Deployment with Dapr annotations
- Sidecar readiness: Health check before Dapr calls
- Error handling: Try/except around Dapr operations
If your skill generates incomplete or incorrect output, identify the gap and add the missing pattern.
Your Growing Skills Library
Your dapr-deployment skill joins a growing collection of production-ready tools:
.claude/skills/
+-- skill-creator/
+-- fetching-library-docs/
+-- fastapi-agent-api/ # Chapter 70
+-- docker-deployment/ # Chapter 79
+-- kubernetes-deployment/ # Chapter 80
+-- helm-chart/ # Chapter 81
+-- kafka-events/ # Chapter 82
+-- dapr-deployment/ # This chapter - COMPLETEEach skill compounds your capability. The dapr-deployment skill doesn't just know Dapr patterns---it encodes the safety guardrails and error diagnostics you'd otherwise learn through production incidents.
That's the value of skill-first learning. You don't just learn Dapr. You build an asset that makes every future Dapr project faster and safer.
Try With AI
You've completed your dapr-deployment skill. Use AI to validate, extend, and stress-test it.
Prompt 1: Coverage Audit
Review my dapr-deployment skill. Does it cover all 6 building blocks from
Chapter 83?
The building blocks are:
1. State Management
2. Pub/Sub Messaging
3. Service Invocation
4. Bindings (input and output)
5. Secrets Management
6. Jobs API
For each building block, tell me:
- Is it covered in my skill? (Yes/No)
- Is the coverage complete? (Component YAML + Python code + common patterns)
- What's missing?
[Paste your SKILL.md content here]What you're learning: External review reveals blind spots. You may have excellent state management coverage but missed input bindings entirely. This prompt forces a systematic audit of completeness.
Prompt 2: Safety Guardrails Review
I've added safety guardrails to my dapr-deployment skill. Review them and tell me:
1. Are my NEVER rules comprehensive? What production mistakes am I still vulnerable to?
2. Are my ALWAYS rules actionable? Can someone follow them without additional research?
3. What guardrails do experienced Dapr operators add that I'm missing?
Current guardrails:
NEVER:
- Call Dapr before sidecar is ready
- Hardcode component names
- Skip error handling
- Store secrets in state
- Expose Dapr ports externally
ALWAYS:
- Wait for sidecar readiness
- Use secretKeyRef for credentials
- Enable mTLS in production
- Configure retry policies
- Set sidecar resource limitsWhat you're learning: Safety guardrails emerge from production experience. AI can surface patterns from thousands of Dapr deployments, identifying risks you haven't encountered yet.
Prompt 3: Stress Test
Test my dapr-deployment skill by generating a complete Dapr-enabled microservice
from scratch. The service should:
- Accept HTTP requests to create orders
- Save order state with ETag-based optimistic concurrency
- Publish order.created events to pub/sub
- Call inventory-service to check stock via service invocation
- Retrieve Stripe API keys from secrets
- Schedule order cleanup job for midnight daily
Generate all YAMLs, Python code, and Kubernetes manifests.
After generating, evaluate: Did my skill produce production-ready output?
What was missing or incorrect?What you're learning: Real-world scenarios expose gaps. An order system has different patterns than a task system---different event types, different concurrency requirements, different integration points. This stress test validates that your skill generalizes beyond the Task API examples.
Safety Note: When deploying Dapr-enabled services to production clusters, always verify component configurations in a staging environment first. Misconfigured components can cause silent data loss (state not persisted) or message drops (pub/sub misconfigured). Your skill provides patterns; you validate they match your specific infrastructure.
Core Concept
Finalize your Dapr skill by testing it against real scenarios, filling gaps discovered during the chapter, and preparing it for production use in your Digital FTE portfolio.
Key Mental Models
- Skill Validation: Test your skill against the capstone to identify gaps
- Iterative Improvement: Update skill based on lessons learned
- Production Readiness: Add resiliency, observability, and security patterns
- Portfolio Asset: The skill is a sellable component of your Digital FTE
Critical Patterns
- Test skill against each building block learned in the chapter
- Identify and document gaps in the skill's knowledge
- Update skill with missing patterns and configurations
- Verify skill generates production-quality output
AI Collaboration Keys
- Ask your Dapr skill to solve the capstone problems
- Identify where the skill falls short and improve it
- Use Claude to verify skill output against official docs
Common Mistakes
- Skipping skill validation and assuming it's complete
- Not updating the skill with patterns learned in the chapter
- Forgetting to test the skill with production scenarios
Connections
- Builds on: Lesson 9 - Capstone Task API integration
- Leads to: Chapter 84 - CI/CD and GitOps with ArgoCD