Single-Shot Pattern: Simple Transformations Done Right
Master the single-shot skill pattern for building focused, reliable AI skills that transform inputs to outputs in one clean operation.
Single-Shot Pattern: Simple Transformations Done Right
The single-shot pattern is the most fundamental skill design pattern. It represents a clean, predictable flow: input goes in, transformation happens, output comes out. No loops, no complex state management, no multi-step workflows. Just one focused operation done well.
Despite its simplicity, the single-shot pattern powers many of the most useful skills in production. Formatters, converters, validators, extractors, and summarizers all follow this pattern. When applied correctly, single-shot skills are fast, reliable, and easy to maintain.
In this guide, we will explore the single-shot pattern in depth, covering when to use it, how to implement it effectively, and common pitfalls to avoid.
Understanding the Single-Shot Pattern
The single-shot pattern follows a straightforward flow:
Input → Process → Output
That's it. No feedback loops. No intermediate states. No branching workflows. The skill receives input, performs a transformation, and returns the result.
Core Characteristics
Single-shot skills share several defining characteristics:
Deterministic: Given the same input, they produce the same output. This makes them predictable and testable.
Stateless: They don't remember previous invocations or maintain state between calls. Each call is independent.
Focused: They do one thing. Not three things that might be related, but exactly one well-defined transformation.
Fast: Without loops or multiple steps, they complete quickly. Most single-shot skills finish in under a second.
Composable: Their simple interface makes them easy to chain with other skills.
When to Use Single-Shot
The single-shot pattern works best for:
- Format conversion: JSON to YAML, Markdown to HTML, CSV to JSON
- Data extraction: Pull specific information from text
- Text transformation: Summarize, expand, translate, rephrase
- Validation: Check if input meets criteria
- Code formatting: Apply style rules to code
- Template filling: Insert data into templates
- Classification: Categorize input into predefined groups
When Not to Use Single-Shot
Avoid single-shot when you need:
- Iterative refinement based on feedback
- Multi-stage processing with dependencies
- User interaction during processing
- Dynamic decision making about next steps
- Complex state that evolves during processing
For these cases, consider the Chain, Router, or Feedback Loop patterns instead.
Anatomy of a Single-Shot Skill
Let us examine the components of a well-designed single-shot skill.
The Basic Structure
---
name: json-to-yaml
description: Converts JSON to YAML format
version: 1.0.0
---
# JSON to YAML Converter
Convert JSON input to equivalent YAML format.
## Input
Valid JSON string or object.
## Processing
1. Parse JSON if provided as string
2. Convert to YAML syntax
3. Preserve data types and structure
4. Handle special characters appropriately
## Output
Valid YAML string representing the same data.
## Example
Input:
```json
{"name": "Claude", "version": 3, "features": ["fast", "accurate"]}
Output:
name: Claude
version: 3
features:
- fast
- accurate
### Input Specification
Clear input specifications prevent errors and set expectations.
```markdown
## Input Requirements
### Required
- `content`: The JSON data to convert (string or object)
### Optional
- `style`: YAML style preference
- "block" (default): Readable, indented format
- "flow": Compact, inline format
- `indent`: Number of spaces for indentation (default: 2)
### Validation
- Content must be valid JSON
- Maximum input size: 100KB
- Nested depth limit: 20 levels
### Examples
Minimal input:
```json
{"content": "{\"key\": \"value\"}"}
Full options:
{
"content": {"key": "value"},
"style": "block",
"indent": 4
}
### Processing Logic
The processing section describes what the skill does, not how the AI should think about it.
```markdown
## Processing Logic
### Step 1: Parse Input
If input is a string, parse as JSON.
Validate the parsed structure.
Handle parsing errors with clear messages.
### Step 2: Convert Structure
Walk the JSON structure:
- Objects become YAML mappings
- Arrays become YAML sequences
- Strings preserve quotes only when needed
- Numbers remain unquoted
- Booleans convert to true/false
- Null converts to null or ~
### Step 3: Format Output
Apply requested style:
- Block style: One item per line, proper indentation
- Flow style: Inline braces and brackets
### Step 4: Validate Output
Ensure output is valid YAML.
Verify round-trip conversion would match input.
Output Specification
Define exactly what the skill produces.
## Output Format
### Success Response
```yaml
success: true
result: |
# The converted YAML content
name: example
value: 123
metadata:
inputSize: 156
outputSize: 42
conversionTime: 12ms
Error Response
success: false
error:
type: "ParseError" | "ConversionError" | "ValidationError"
message: "Human readable explanation"
location: "Where in input the error occurred"
suggestion: "How to fix the issue"
Guarantees
- Output is always valid YAML when success is true
- Metadata always includes size and timing information
- Error messages always include actionable suggestions
## Common Single-Shot Skill Types
Let us explore specific types of single-shot skills with examples.
### Formatters
Formatters restructure content without changing its meaning.
```markdown
---
name: code-formatter
description: Formats code according to style rules
---
# Code Formatter
Format source code according to specified style rules.
## Input
- `code`: Source code string
- `language`: Programming language
- `style`: Style configuration or preset name
## Processing
Apply formatting rules in order:
1. Normalize line endings
2. Apply indentation rules
3. Format whitespace around operators
4. Handle line length limits
5. Order imports/includes
6. Add/remove trailing commas as configured
## Output
Formatted code that is semantically identical to input.
## Example
Input:
```javascript
const x=1;const y=2;function add(a,b){return a+b;}
Output:
const x = 1;
const y = 2;
function add(a, b) {
return a + b;
}
Guarantees
- Output is syntactically valid if input was valid
- No semantic changes (same behavior when executed)
- Deterministic (same input always produces same output)
### Extractors
Extractors pull specific information from larger content.
```markdown
---
name: email-extractor
description: Extracts email addresses from text
---
# Email Extractor
Extract all email addresses from provided text.
## Input
- `text`: Text content to search
- `validate`: Whether to check email format validity (default: true)
- `unique`: Return only unique emails (default: true)
## Processing
1. Scan text for email patterns
2. Validate format if requested
3. Deduplicate if requested
4. Sort alphabetically
## Output
```json
{
"emails": ["alice@example.com", "bob@example.com"],
"count": 2,
"duplicatesRemoved": 1,
"invalidSkipped": 0
}
Edge Cases
- Multiple emails on same line: Extract all
- Emails in code blocks: Include by default
- Obfuscated emails (user [at] domain): Do not extract
- International domains: Support full Unicode
### Validators
Validators check if input meets specified criteria.
```markdown
---
name: json-schema-validator
description: Validates JSON against a schema
---
# JSON Schema Validator
Validate JSON data against a JSON Schema.
## Input
- `data`: JSON data to validate
- `schema`: JSON Schema to validate against
- `strict`: Reject unknown properties (default: false)
## Processing
1. Parse data and schema
2. Apply schema validation rules
3. Collect all validation errors
4. Determine overall validity
## Output
```json
{
"valid": false,
"errors": [
{
"path": "$.user.email",
"message": "Invalid email format",
"rule": "format",
"expected": "email",
"received": "not-an-email"
}
],
"errorCount": 1,
"checkedProperties": 15
}
Guarantees
- All schema violations reported (not just first)
- Paths use JSON Pointer notation
- Clear, actionable error messages
### Converters
Converters transform between formats or representations.
```markdown
---
name: markdown-to-html
description: Converts Markdown to HTML
---
# Markdown to HTML Converter
Convert Markdown content to HTML.
## Input
- `markdown`: Markdown text
- `options`:
- `sanitize`: Remove dangerous HTML (default: true)
- `gfm`: GitHub Flavored Markdown (default: true)
- `headerIds`: Add IDs to headers (default: true)
## Processing
1. Parse Markdown to AST
2. Apply GFM extensions if enabled
3. Transform to HTML
4. Add header IDs if enabled
5. Sanitize if enabled
## Output
```json
{
"html": "<h1 id=\"title\">Title</h1>\n<p>Content</p>",
"toc": [
{"level": 1, "text": "Title", "id": "title"}
],
"metadata": {
"headings": 1,
"links": 0,
"images": 0,
"codeBlocks": 0
}
}
### Summarizers
Summarizers condense content while preserving key information.
```markdown
---
name: text-summarizer
description: Summarizes text to specified length
---
# Text Summarizer
Generate a concise summary of provided text.
## Input
- `text`: Text to summarize
- `maxLength`: Maximum summary length in words (default: 100)
- `style`: "extractive" | "abstractive" (default: "abstractive")
- `focus`: Optional topic to emphasize
## Processing
For extractive:
1. Split into sentences
2. Score sentence importance
3. Select top sentences up to limit
4. Order naturally
For abstractive:
1. Understand main points
2. Generate new text capturing essence
3. Constrain to length limit
4. Maintain factual accuracy
## Output
```json
{
"summary": "Condensed version of the text...",
"wordCount": 85,
"compressionRatio": 0.15,
"keyPoints": [
"Main point one",
"Main point two"
]
}
Constraints
- Never introduce information not in source
- Preserve factual accuracy
- Maintain neutral tone
- Include most important points first
## Best Practices for Single-Shot Skills
Follow these practices to build reliable single-shot skills.
### Keep It Focused
A single-shot skill should do one thing. If you find yourself saying "and also," you're likely combining multiple skills.
```markdown
# Bad: Multiple Responsibilities
Parse JSON, validate against schema, format the output,
and generate a summary of the contents.
# Good: Single Responsibility
Parse JSON string into a structured object.
Validate it meets expected format.
Return parsed object or parsing error.
Define Clear Boundaries
Specify exactly what the skill will and won't do.
## Scope
This skill will:
- Parse valid JSON strings
- Handle nested objects and arrays
- Preserve all data types
This skill will not:
- Fetch JSON from URLs
- Transform or modify the data
- Pretty-print the output
- Handle JSONL or streaming JSON
Handle Errors Gracefully
Every input should produce meaningful output, even invalid ones.
## Error Handling
For invalid input:
1. Don't throw exceptions or crash
2. Return structured error response
3. Include specific location of problem
4. Suggest how to fix it
Example error response:
```json
{
"success": false,
"error": {
"type": "SyntaxError",
"message": "Unexpected token '}' at position 45",
"line": 3,
"column": 12,
"context": "...\"name\": \"test\", }...",
"suggestion": "Remove trailing comma before '}'"
}
}
### Document Edge Cases
Explicitly handle boundary conditions.
```markdown
## Edge Cases
| Input | Behavior |
|-------|----------|
| Empty string | Return empty result, not error |
| null/undefined | Error: Input required |
| Very long input | Process normally up to 100KB limit |
| Unicode characters | Preserve correctly |
| Nested 100 levels | Error: Nesting limit exceeded |
| Circular references | Error: Not supported in JSON |
Optimize for Speed
Single-shot skills should be fast. Avoid unnecessary processing.
## Performance Considerations
- Parse once, reference multiple times
- Avoid redundant validation passes
- Stream large outputs when possible
- Fail fast on invalid input
- Cache compiled patterns/schemas
Target performance:
- Small inputs (<1KB): <100ms
- Medium inputs (<100KB): <500ms
- Large inputs (>100KB): <2s
Testing Single-Shot Skills
Testing single-shot skills is straightforward due to their deterministic nature.
Test Categories
## Test Suite
### Happy Path Tests
- Typical valid input produces expected output
- All supported options work correctly
- Different input sizes handled properly
### Edge Case Tests
- Empty input
- Minimum valid input
- Maximum size input
- Unicode and special characters
- Boundary values for numeric inputs
### Error Case Tests
- Invalid format
- Missing required fields
- Exceeds size limits
- Malformed structure
### Regression Tests
- Previously fixed bugs stay fixed
- Known problematic inputs work
Test Structure
## Test: json-to-yaml
### Test Case: Simple Object
Input:
```json
{"name": "test", "value": 42}
Expected Output:
name: test
value: 42
Test Case: Nested Structure
Input:
{"outer": {"inner": {"deep": true}}}
Expected Output:
outer:
inner:
deep: true
Test Case: Array Values
Input:
{"items": [1, 2, 3]}
Expected Output:
items:
- 1
- 2
- 3
Test Case: Invalid JSON
Input:
{invalid json}
Expected:
- success: false
- error.type: "ParseError"
- error.message: Contains "Unexpected token"
## Real-World Examples
Let us look at complete single-shot skills used in production.
### Git Commit Message Generator
```markdown
---
name: commit-message-generator
description: Generates commit message from diff
version: 1.0.0
---
# Commit Message Generator
Generate a conventional commit message from a git diff.
## Input
- `diff`: Git diff output
- `style`: Commit style (default: "conventional")
- "conventional": type(scope): description
- "simple": Just description
- "detailed": Description with body
- `maxLength`: Maximum subject line length (default: 72)
## Processing
1. Analyze diff to understand changes:
- Files modified
- Type of changes (add, modify, delete)
- Scope of changes (file, module, feature)
2. Categorize the change:
- feat: New feature
- fix: Bug fix
- docs: Documentation
- style: Formatting
- refactor: Code restructure
- test: Test changes
- chore: Maintenance
3. Identify scope from file paths
4. Generate concise description:
- Use imperative mood
- Focus on what and why
- Stay within length limit
## Output
```json
{
"message": "feat(auth): add password reset functionality",
"type": "feat",
"scope": "auth",
"description": "add password reset functionality",
"body": null,
"confidence": 0.9
}
Constraints
- Subject line under maxLength
- Use imperative mood ("add" not "added")
- No period at end of subject
- Type must be from standard list
- Scope should match directory/module
Example
Input diff:
--- a/src/auth/password.ts
+++ b/src/auth/password.ts
@@ -10,6 +10,20 @@ export class PasswordService {
+ async resetPassword(email: string): Promise<void> {
+ const user = await this.findUser(email);
+ const token = this.generateResetToken();
+ await this.sendResetEmail(user, token);
+ }
Output:
{
"message": "feat(auth): add password reset functionality",
"type": "feat",
"scope": "auth",
"description": "add password reset functionality",
"confidence": 0.95
}
### API Response Formatter
```markdown
---
name: api-response-formatter
description: Formats data as standardized API response
version: 1.0.0
---
# API Response Formatter
Format arbitrary data as a standardized API response.
## Input
- `data`: The data to return
- `status`: HTTP status code (default: 200)
- `message`: Optional message
- `pagination`: Optional pagination info
## Processing
1. Wrap data in standard envelope
2. Add metadata
3. Handle null/empty data
4. Format dates as ISO strings
5. Ensure consistent structure
## Output
Success response:
```json
{
"success": true,
"data": { ... },
"message": "Operation completed",
"metadata": {
"timestamp": "2025-01-15T10:30:00Z",
"requestId": "generated-uuid",
"version": "1.0"
},
"pagination": {
"page": 1,
"pageSize": 20,
"total": 100,
"totalPages": 5
}
}
Error response:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input",
"details": [...]
},
"metadata": { ... }
}
Guarantees
- Always includes success boolean
- Always includes metadata with timestamp
- Consistent structure regardless of input
- Null data becomes empty object
## Conclusion
The single-shot pattern is the foundation of AI skill development. Its simplicity is its strength—predictable, testable, and easy to understand. When you need a reliable transformation without complexity, single-shot is the answer.
Key takeaways:
1. **One input, one output, one purpose**: Keep skills focused
2. **Clear contracts**: Define input and output precisely
3. **Handle everything**: Valid input, invalid input, edge cases
4. **Deterministic behavior**: Same input always produces same output
5. **Fast execution**: No loops or waiting states
Start with single-shot when building new skills. Only reach for more complex patterns when single-shot genuinely cannot meet your needs. Many seemingly complex requirements can be addressed by composing multiple single-shot skills rather than building a monolithic multi-step skill.
Master the single-shot pattern, and you will have the foundation for building any AI skill.