|
| 1 | +--- |
| 2 | +title: "Tutorial: Creating New Agents" |
| 3 | +--- |
| 4 | + |
| 5 | +Every team has unique infrastructure, monitoring systems, and incident response |
| 6 | +processes. The example agents in our library serve as references and starting |
| 7 | +points, but the real power of Unpage comes from understanding the agent-building |
| 8 | +process itself. |
| 9 | + |
| 10 | +This tutorial walks you through the steps needed to design and implement your |
| 11 | +own agents from scratch. |
| 12 | + |
| 13 | + |
| 14 | +## Overview: The Agent Creation Process |
| 15 | + |
| 16 | +Creating a new agent involves six key steps: |
| 17 | + |
| 18 | +1. **Identify your input source** - What webhook/alert will trigger the agent? |
| 19 | +2. **Write the agent description** - How will the router know when to use this agent? |
| 20 | +3. **Design the runbook instructions** - What should the agent do step-by-step? |
| 21 | +4. **Define required tools** - What built-in and custom tools does the agent need? |
| 22 | +5. **Create custom shell tools** - Extend Unpage with your specific commands/scripts |
| 23 | +6. **Test and deploy** - Validate locally and set up production webhook handling |
| 24 | + |
| 25 | +Let's walk through each step with a practical example. |
| 26 | + |
| 27 | +## Example Scenario: Redis Memory Usage Alerts |
| 28 | + |
| 29 | +For this tutorial, we'll create an agent that handles Redis memory usage alerts |
| 30 | +from DataDog. When Redis memory usage exceeds 85%, our agent will: |
| 31 | + |
| 32 | +- Check current Redis memory statistics |
| 33 | +- Identify the largest keys consuming memory |
| 34 | +- Analyze recent memory growth patterns |
| 35 | +- Check for memory-intensive operations in Redis logs |
| 36 | +- Post actionable recommendations to the incident |
| 37 | + |
| 38 | + |
| 39 | +## Step 1: Identify Your Input Source |
| 40 | + |
| 41 | +The first step is understanding what triggers your agent. This could be: |
| 42 | + |
| 43 | +- **PagerDuty incidents** from various monitoring systems |
| 44 | +- **Direct webhooks** from DataDog, New Relic, CloudWatch, etc. |
| 45 | +- **GitHub Actions failures** or other CI/CD events |
| 46 | +- **Custom application alerts** from your own services |
| 47 | + |
| 48 | +For our Redis example, we'll assume we get alerts that look like: |
| 49 | + |
| 50 | +```json |
| 51 | +{ |
| 52 | + "incident": { |
| 53 | + "title": "Redis Memory Usage Critical", |
| 54 | + "description": "redis-prod-cluster memory usage: 87.2% (6.1GB/7.0GB)", |
| 55 | + "service": "redis-prod-cluster", |
| 56 | + "status": "triggered" |
| 57 | + } |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | + |
| 62 | +## Step 2: Write the Agent Description |
| 63 | + |
| 64 | +The agent description is used by Unpage's [Router](/concepts/router) to |
| 65 | +automatically select which agent should handle each incoming alert. Write |
| 66 | +descriptions that are: |
| 67 | + |
| 68 | +- **Specific** about the alert types this agent handles |
| 69 | +- **Distinguishing** to differentiate from other agents |
| 70 | +- **Comprehensive** to cover edge cases and variations |
| 71 | + |
| 72 | +Create the agent configuration: |
| 73 | + |
| 74 | +```bash |
| 75 | +$ unpage agent create redis_memory_alerts |
| 76 | +``` |
| 77 | + |
| 78 | +Start with the description in the YAML file that opens: |
| 79 | + |
| 80 | +```yaml |
| 81 | +description: > |
| 82 | + Handle Redis memory usage alerts and high memory consumption issues. |
| 83 | + Use this agent when: |
| 84 | + - The alert mentions Redis, redis-server, or Redis cluster names |
| 85 | + - Memory usage, memory consumption, or OOM (out of memory) is mentioned |
| 86 | + - Redis-specific metrics like used_memory, maxmemory, or evicted_keys are referenced |
| 87 | + - The alert comes from DataDog, CloudWatch, or other monitoring systems monitoring Redis instances |
| 88 | +``` |
| 89 | +
|
| 90 | +## Step 3: Design the Runbook Instructions |
| 91 | +
|
| 92 | +The `prompt` section contains step-by-step instructions for what the agent should do. |
| 93 | +Think of this as a detailed runbook that a human SRE would follow, but written for an LLM. |
| 94 | + |
| 95 | +Structure your instructions clearly: |
| 96 | + |
| 97 | +- Use numbered or bulleted steps |
| 98 | +- Be specific about what information to gather |
| 99 | +- Include error handling and edge cases |
| 100 | +- Specify what actions to take based on findings |
| 101 | +- Include formatting requirements for status updates |
| 102 | + |
| 103 | +```yaml |
| 104 | +prompt: > |
| 105 | + You are a Redis memory analysis specialist. When investigating Redis memory alerts: |
| 106 | +
|
| 107 | + 1. Extract the Redis instance/cluster name from the PagerDuty alert |
| 108 | + 2. Use `shell_redis_memory_info` to get current memory statistics and configuration |
| 109 | + 3. Use `shell_redis_top_keys` to identify the largest keys consuming memory |
| 110 | + 4. Use `shell_redis_memory_usage_history` to analyze memory growth patterns over the last 4 hours |
| 111 | + 5. Use `search_datadog_logs` to find Redis logs from the last 30 minutes, looking for: |
| 112 | + - Memory-related warnings or errors |
| 113 | + - Large key operations (HSET, SADD with many members) |
| 114 | + - Client connection spikes that might indicate memory leaks |
| 115 | + 6. Use `get_resource_with_neighbors` to identify applications connected to this Redis instance |
| 116 | + 7. For each connected application, search logs for Redis-related errors or unusual patterns |
| 117 | + |
| 118 | + Analysis and Response: |
| 119 | + - If memory usage is above 90%: Mark as CRITICAL and recommend immediate action |
| 120 | + - If memory usage is 85-90%: Mark as HIGH and suggest proactive measures |
| 121 | + - If large keys (>100MB) exist: Identify the key patterns and suggest optimization |
| 122 | + - If memory growth is rapid (>10% in 1 hour): Flag as potential memory leak |
| 123 | + |
| 124 | + Create a comprehensive status update including: |
| 125 | + - Current memory usage percentage and absolute values |
| 126 | + - Top 10 memory-consuming key patterns with sizes |
| 127 | + - Memory growth rate over the last 4 hours |
| 128 | + - Any concerning log patterns or errors |
| 129 | + - Connected applications that might be causing issues |
| 130 | + - Specific recommended actions (key cleanup, configuration changes, scaling) |
| 131 | + |
| 132 | + Post findings using `pagerduty_post_status_update` with priority based on severity analysis. |
| 133 | +``` |
| 134 | + |
| 135 | +## Step 4: Define Required Tools |
| 136 | + |
| 137 | +List all the tools your agent needs in the `tools` section. These include: |
| 138 | + |
| 139 | +- **Built-in tools** from Unpage plugins (DataDog, PagerDuty, AWS, etc.) |
| 140 | +- **Custom shell commands** you'll create for specific operations |
| 141 | +- **Wildcards** for groups of related tools |
| 142 | + |
| 143 | +```yaml |
| 144 | +tools: |
| 145 | + - "shell_redis_memory_info" |
| 146 | + - "shell_redis_top_keys" |
| 147 | + - "shell_redis_memory_usage_history" |
| 148 | + - "search_datadog_logs" |
| 149 | + - "get_resource_with_neighbors" |
| 150 | + - "pagerduty_post_status_update" |
| 151 | +``` |
| 152 | +
|
| 153 | +To see all available built-in tools: |
| 154 | +
|
| 155 | +```bash |
| 156 | +$ unpage mcp tools list |
| 157 | +``` |
| 158 | + |
| 159 | +Your Agent will **only** have access to the tools you explicitly give it |
| 160 | +permission to call. |
| 161 | + |
| 162 | + |
| 163 | +## Step 5: Create Custom Shell Tools |
| 164 | + |
| 165 | +You can always extend Unpage with custom [shell commands](/plugins/shell) to |
| 166 | +interact with your specific infrastructure. These commands can: |
| 167 | + |
| 168 | +- Execute Redis CLI commands against your instances |
| 169 | +- Run custom scripts or database queries |
| 170 | +- Call internal APIs or tools |
| 171 | +- Parse and format data for the agent |
| 172 | + |
| 173 | +Edit your Unpage configuration (`~/.unpage/profiles/default/config.yaml`) to add the custom commands: |
| 174 | + |
| 175 | +```yaml |
| 176 | +plugins: |
| 177 | + # ... existing plugins |
| 178 | + shell: |
| 179 | + enabled: true |
| 180 | + settings: |
| 181 | + commands: |
| 182 | + - handle: redis_memory_info |
| 183 | + description: Get comprehensive Redis memory statistics and configuration |
| 184 | + command: | |
| 185 | + redis-cli -h {redis_host} -p {redis_port} --raw INFO memory && |
| 186 | + echo "---CONFIG---" && |
| 187 | + redis-cli -h {redis_host} -p {redis_port} CONFIG GET maxmemory* && |
| 188 | + redis-cli -h {redis_host} -p {redis_port} CONFIG GET save |
| 189 | + args: |
| 190 | + redis_host: The Redis server hostname or IP address |
| 191 | + redis_port: The Redis server port (default 6379) |
| 192 | + |
| 193 | + - handle: redis_top_keys |
| 194 | + description: Identify the largest keys in Redis by memory usage |
| 195 | + command: | |
| 196 | + redis-cli -h {redis_host} -p {redis_port} --latency-history -i 1 > /dev/null 2>&1 & |
| 197 | + LATENCY_PID=$! |
| 198 | + redis-cli -h {redis_host} -p {redis_port} --bigkeys --i 0.01 |
| 199 | + kill $LATENCY_PID 2>/dev/null || true |
| 200 | + args: |
| 201 | + redis_host: The Redis server hostname or IP address |
| 202 | + redis_port: The Redis server port (default 6379) |
| 203 | + |
| 204 | + - handle: redis_memory_usage_history |
| 205 | + description: Get Redis memory usage metrics from the last 4 hours via DataDog API |
| 206 | + command: | |
| 207 | + curl -X GET "https://api.datadoghq.com/api/v1/query" \ |
| 208 | + -H "Content-Type: application/json" \ |
| 209 | + -H "DD-API-KEY: ${DATADOG_API_KEY}" \ |
| 210 | + -H "DD-APPLICATION-KEY: ${DATADOG_APP_KEY}" \ |
| 211 | + -G \ |
| 212 | + --data-urlencode "query=avg:redis.info.memory.used_memory{host:{redis_host}}" \ |
| 213 | + --data-urlencode "from=$(date -d '4 hours ago' +%s)" \ |
| 214 | + --data-urlencode "to=$(date +%s)" |
| 215 | + args: |
| 216 | + redis_host: The Redis server hostname to query metrics for |
| 217 | +``` |
| 218 | +
|
| 219 | +### Shell Command Best Practices |
| 220 | +
|
| 221 | +When creating shell commands: |
| 222 | +
|
| 223 | +- **Include error handling** with `2>/dev/null || echo "Command failed"` |
| 224 | +- **Use environment variables** for API keys and credentials |
| 225 | +- **Chain commands** with `&&` for sequential execution |
| 226 | +- **Parse output** to provide clean, structured data |
| 227 | +- **Add timeouts** for potentially long-running operations |
| 228 | +- **Document required permissions** and dependencies |
| 229 | + |
| 230 | +## Step 6: Test and Deploy |
| 231 | + |
| 232 | +### Local Testing |
| 233 | + |
| 234 | +Test your agent with sample data before deploying: |
| 235 | + |
| 236 | +```bash |
| 237 | +# Test with a sample alert payload |
| 238 | +$ echo '{"incident": {"title": "Redis Memory Usage Critical", "description": "redis-prod-cluster memory usage: 87.2%"}}' | unpage agent run redis_memory_alerts |
| 239 | +
|
| 240 | +# Test with a PagerDuty incident ID |
| 241 | +$ unpage agent run redis_memory_alerts --pagerduty-incident PXXXXX |
| 242 | +``` |
| 243 | + |
| 244 | +### Test Routing |
| 245 | + |
| 246 | +Verify the router selects your agent correctly: |
| 247 | + |
| 248 | +```bash |
| 249 | +# Test routing decision |
| 250 | +$ unpage agent route '{"incident": {"title": "Redis Memory Critical"}}' |
| 251 | +
|
| 252 | +# Debug routing with detailed explanation |
| 253 | +$ unpage agent route --debug '{"incident": {"title": "Redis Memory Critical"}}' |
| 254 | +``` |
| 255 | + |
| 256 | +### Production Deployment |
| 257 | + |
| 258 | +Set up webhook handling for production alerts: |
| 259 | + |
| 260 | +```bash |
| 261 | +# Local webhook server for testing |
| 262 | +$ unpage agent serve |
| 263 | +
|
| 264 | +# Public webhook with ngrok tunnel |
| 265 | +$ unpage agent serve --tunnel --ngrok-token YOUR_NGROK_TOKEN |
| 266 | +
|
| 267 | +# Production deployment (typically with reverse proxy) |
| 268 | +$ unpage agent serve --host 0.0.0.0 --port 8000 |
| 269 | +``` |
| 270 | + |
| 271 | +Configure your monitoring system (PagerDuty, DataDog, etc.) to send webhooks to: |
| 272 | +- Local testing: `http://localhost:8000/webhook` |
| 273 | +- Ngrok tunnel: `https://your-tunnel.ngrok.io/webhook` |
| 274 | +- Production: `https://your-domain.com/webhook` |
| 275 | + |
| 276 | +## Advanced Agent Patterns |
| 277 | + |
| 278 | +### Multi-Step Analysis Agents |
| 279 | + |
| 280 | +For complex scenarios, break analysis into phases: |
| 281 | + |
| 282 | +```yaml |
| 283 | +prompt: > |
| 284 | + Phase 1 - Data Collection: |
| 285 | + - Gather all relevant metrics and logs |
| 286 | + - Verify the scope of the issue |
| 287 | +
|
| 288 | + Phase 2 - Root Cause Analysis: |
| 289 | + - Correlate data to identify potential causes |
| 290 | + - Rule out common false positives |
| 291 | +
|
| 292 | + Phase 3 - Impact Assessment: |
| 293 | + - Determine affected services and users |
| 294 | + - Estimate business impact |
| 295 | +
|
| 296 | + Phase 4 - Response and Communication: |
| 297 | + - Post detailed findings with evidence |
| 298 | + - Recommend specific remediation steps |
| 299 | + - Set appropriate incident priority |
| 300 | +``` |
| 301 | + |
| 302 | +### Conditional Logic Agents |
| 303 | + |
| 304 | +Use conditional prompts for different scenarios: |
| 305 | + |
| 306 | +```yaml |
| 307 | +prompt: > |
| 308 | + Analyze the alert and determine the scenario: |
| 309 | +
|
| 310 | + If memory usage > 95%: |
| 311 | + - Execute emergency memory cleanup procedures |
| 312 | + - Post CRITICAL update with immediate actions |
| 313 | +
|
| 314 | + If memory growth rate > 20% per hour: |
| 315 | + - Focus on identifying memory leaks |
| 316 | + - Examine recent deployments and configuration changes |
| 317 | +
|
| 318 | + If evicted_keys metric is increasing: |
| 319 | + - Analyze key eviction patterns |
| 320 | + - Recommend maxmemory policy adjustments |
| 321 | +
|
| 322 | + Otherwise: |
| 323 | + - Perform standard memory analysis |
| 324 | + - Post standard monitoring recommendations |
| 325 | +``` |
| 326 | + |
| 327 | +### Integration with External Systems |
| 328 | + |
| 329 | +Agents can interact with any system your shell commands can reach: |
| 330 | + |
| 331 | +```yaml |
| 332 | +tools: |
| 333 | + - "shell_slack_notify_team" |
| 334 | + - "shell_create_jira_ticket" |
| 335 | + - "shell_trigger_runbook_automation" |
| 336 | + - "shell_update_status_page" |
| 337 | +``` |
| 338 | + |
| 339 | +## Debugging and Iteration |
| 340 | + |
| 341 | +### Monitoring Agent Performance |
| 342 | + |
| 343 | +Use Unpage's built-in tracing to monitor agent execution: |
| 344 | + |
| 345 | +```bash |
| 346 | +# Start MLflow tracking server |
| 347 | +$ unpage mlflow serve |
| 348 | +
|
| 349 | +# Run agent with tracing enabled |
| 350 | +$ env MLFLOW_TRACKING_URI=http://127.0.0.1:5566 unpage agent run redis_memory_alerts @test_alert.json |
| 351 | +``` |
| 352 | + |
| 353 | +View execution traces at `http://127.0.0.1:5566/#/experiments/1?searchFilter=&orderByKey=attributes.start_time&orderByAsc=false&startTime=ALL&lifecycleFilter=Active&modelVersionFilter=All+Runs&datasetsFilter=W10%3D&compareRunsMode=TRACES` to see: |
| 354 | +- Tool usage patterns |
| 355 | +- Execution timing |
| 356 | +- Error rates and types |
| 357 | +- Agent decision flows |
| 358 | + |
| 359 | +## Best Practices Summary |
| 360 | + |
| 361 | +1. **Start simple** - Begin with basic analysis, then add complexity |
| 362 | +2. **Test thoroughly** - Use various input scenarios and edge cases |
| 363 | +3. **Handle errors gracefully** - Include fallbacks for failed commands |
| 364 | +4. **Be specific in descriptions** - Help the router make correct decisions |
| 365 | +5. **Document dependencies** - Note required tools, permissions, and environment setup |
| 366 | +6. **Iterate based on results** - Refine prompts based on real incident responses |
| 367 | +7. **Monitor and improve** - Use tracing data to optimize agent performance |
| 368 | + |
| 369 | +## Conclusion |
| 370 | + |
| 371 | +Creating effective Unpage agents transforms reactive incident response into |
| 372 | +proactive, automated analysis. By following this systematic approach you can |
| 373 | +build agents that not only save time during incidents but also provide deeper |
| 374 | +insights into your infrastructure than manual investigation alone. |
| 375 | + |
| 376 | +The key is starting with one well-defined use case, perfecting it through testing |
| 377 | +and iteration, then expanding to cover additional scenarios as you gain experience |
| 378 | +with the platform. |
| 379 | + |
| 380 | +Remember: the best agents are those that encode your team's operational |
| 381 | +knowledge and decision-making processes, making your entire team more effective |
| 382 | +at infrastructure management. |
0 commit comments