Turn vague product ideas into clear, actionable plans that your team can execute immediately. Generate clear feature descriptions, break large projects into manageable steps, and organize work into realistic schedules. Reach for this product planning assistant whenever you need to prioritize new features or clarify exactly what needs to be built next.
name: “agile-product-owner”
description: Agile product ownership for backlog management and sprint execution. Covers user story writing, acceptance criteria, sprint planning, and velocity tracking. Use for writing user stories, creating acceptance criteria, planning sprints, estimating story points, breaking down epics, or prioritizing backlog.
triggers:
write user story
create acceptance criteria
plan sprint
estimate story points
break down epic
prioritize backlog
sprint planning
INVEST criteria
Given When Then
user story template
sprint capacity
velocity tracking
Agile Product Owner
Backlog management and sprint execution toolkit for product owners, including user story generation, acceptance criteria patterns, sprint planning, and velocity tracking.
Create INVEST-compliant user stories from requirements:
Identify the persona (who benefits from this feature)
Define the action or capability needed
Articulate the benefit or value delivered
Write acceptance criteria using Given-When-Then
Estimate story points using Fibonacci scale
Validate against INVEST criteria
Add to backlog with priority
Validation: Story passes all INVEST criteria; acceptance criteria are testable
User Story Template
As a [persona],I want to [action/capability],So that [benefit/value].
Example:
As a marketing manager,I want to export campaign reports to PDF,So that I can share results with stakeholders who don't have system access.
Story Types
Type
Template
Example
Feature
As a [persona], I want to [action] so that [benefit]
As a user, I want to filter search results so that I find items faster
Improvement
As a [persona], I need [capability] to [goal]
As a user, I need faster page loads to complete tasks without frustration
Bug Fix
As a [persona], I expect [behavior] when [condition]
As a user, I expect my cart to persist when I refresh the page
Enabler
As a developer, I need to [technical task] to enable [capability]
As a developer, I need to implement caching to enable instant search
Persona Reference
Persona
Typical Needs
Context
End User
Efficiency, simplicity, reliability
Daily feature usage
Administrator
Control, visibility, security
System management
Power User
Automation, customization, shortcuts
Expert workflows
New User
Guidance, learning, safety
Onboarding
Acceptance Criteria Patterns
Write testable acceptance criteria using Given-When-Then format.
Given-When-Then Template
Given [precondition/context],When [action/trigger],Then [expected outcome].
Examples:
Given the user is logged in with valid credentials,When they click the "Export" button,Then a PDF download starts within 2 seconds.Given the user has entered an invalid email format,When they submit the registration form,Then an inline error message displays "Please enter a valid email address."Given the shopping cart contains items,When the user refreshes the browser,Then the cart contents remain unchanged.
Acceptance Criteria Checklist
Each story should include criteria for:
Category
Example
Happy Path
Given valid input, When submitted, Then success message displayed
Validation
Should reject input when required field is empty
Error Handling
Must show user-friendly message when API fails
Performance
Should complete operation within 2 seconds
Accessibility
Must be navigable via keyboard only
Minimum Criteria by Story Size
Story Points
Minimum AC Count
1-2
3-4 criteria
3-5
4-6 criteria
8
5-8 criteria
13+
Split the story
See references/user-story-templates.md for complete template library.
Epic Breakdown Workflow
Break epics into deliverable sprint-sized stories:
Define epic scope and success criteria
Identify all personas affected by the epic
List all capabilities needed for each persona
Group capabilities into logical stories
Validate each story is ≤8 points
Identify dependencies between stories
Sequence stories for incremental delivery
Validation: Each story delivers standalone value; total stories cover epic scope
Epic: User Dashboard (34 points total)├── US-001: View key metrics (5 pts) - End User├── US-002: Customize layout (5 pts) - Power User├── US-003: Export data to CSV (3 pts) - End User├── US-004: Share with team (5 pts) - End User├── US-005: Set up alerts (5 pts) - Power User├── US-006: Filter by date range (3 pts) - End User├── US-007: Admin overview (5 pts) - Admin└── US-008: Enable caching (3 pts) - Enabler
Sprint Planning Workflow
Plan sprint capacity and select stories:
Calculate team capacity (velocity × availability)
Review sprint goal with stakeholders
Select stories from prioritized backlog
Fill to 80-85% of capacity (committed)
Add stretch goals (10-15% additional)
Identify dependencies and risks
Break complex stories into tasks
Validation: Committed points ≤85% capacity; all stories have acceptance criteria
Capacity Calculation
Sprint Capacity = Average Velocity × Availability FactorExample:Average Velocity: 30 pointsTeam availability: 90% (one member partially out)Adjusted Capacity: 27 pointsCommitted: 23 points (85% of 27)Stretch: 4 points (15% of 27)
# Generate stories from sample epicpython scripts/user_story_generator.py# Plan sprint with capacitypython scripts/user_story_generator.py sprint 30
Generates:
INVEST-compliant user stories
Given-When-Then acceptance criteria
Story point estimates (Fibonacci scale)
Priority assignments
Sprint loading with committed and stretch items
Sample Output
USER STORY: USR-001========================================Title: View Key MetricsType: storyPriority: HIGHPoints: 5Story:As a End User, I want to view key metrics and KPIsso that I can save time and work more efficientlyAcceptance Criteria: 1. Given user has access, When they view key metrics, Then the result is displayed 2. Should validate input before processing 3. Must show clear error message when action fails 4. Should complete within 2 seconds 5. Must be accessible via keyboard navigationINVEST Checklist: ✓ Independent ✓ Negotiable ✓ Valuable ✓ Estimable ✓ Small ✓ Testable
[One sentence describing what this sprint achieves]
Scrum Master
[Name]
Product Owner
[Name]
Sprint Goal
[Expand on the sprint goal. What is the single most important outcome? What does "done" look like for this sprint? 2-3 sentences.]
Team Capacity
Team Member
Available Days
Notes
[Name]
[X] / [Total]
[PTO, training, on-call, etc.]
[Name]
[X] / [Total]
[Name]
[X] / [Total]
Total Capacity: [X] person-days
Historical Velocity: [X] story points (avg of last 3 sprints)
Planned Velocity: [X] story points (adjusted for capacity)
Selected Stories
#
Story
Points
Assignee
Priority
Status
1
[Story title with ticket link]
[SP]
[Name]
Must Have
To Do
2
[Story title with ticket link]
[SP]
[Name]
Must Have
To Do
3
[Story title with ticket link]
[SP]
[Name]
Should Have
To Do
4
[Story title with ticket link]
[SP]
[Name]
Nice to Have
To Do
Total Planned: [X] story points
Dependencies
Dependency
Blocking Story
Owner
Status
Due Date
[External API ready]
[Story #]
[Name/Team]
[Status]
[Date]
[Design review complete]
[Story #]
[Name]
[Status]
[Date]
Risks
Risk
Impact
Likelihood
Mitigation
[Risk description]
High/Med/Low
High/Med/Low
[Plan]
[Risk description]
High/Med/Low
High/Med/Low
[Plan]
Definition of Done
Code complete and peer reviewed
Unit tests written and passing
Acceptance criteria verified
Documentation updated (if applicable)
Deployed to staging environment
QA sign-off received
Product Owner acceptance
Sprint Ceremonies
Ceremony
Day/Time
Duration
Daily Standup
[Day] [Time]
15 min
Sprint Review
[Date] [Time]
60 min
Sprint Retrospective
[Date] [Time]
60 min
User Story
Story Info
Field
Value
Title
[Short descriptive title]
Epic
[Parent epic name/link]
Story Points
[Estimate]
Priority
Must Have / Should Have / Nice to Have
Assignee
[Name]
Sprint
[Sprint number]
User Story
As a [type of user/role],
I want [capability or feature],
So that [benefit or value I receive].
Acceptance Criteria
Scenario 1: [Happy Path]
Given [precondition or context]
When [action the user takes]
Then [expected outcome]
Scenario 2: [Alternative Path]
Given [precondition or context]
When [action the user takes]
Then [expected outcome]
Scenario 3: [Edge Case / Error]
Given [precondition or context]
When [action the user takes]
Then [expected error handling or outcome]
Notes
[Technical notes, design references, API details]
[Dependencies on other stories or external systems]
[Out of scope items for this story]
[Links to mockups, prototypes, or design files]
Definition of Done
Acceptance criteria met
Code reviewed and approved
Tests written and passing
Documentation updated
Product Owner accepted
Sprint Planning Guide
Sprint planning workflows, capacity calculation, and backlog management.
As a [persona],I want to [action/capability],So that [benefit/value].
Template by Story Type
Feature Story:
As a [persona],I want to [perform action]So that [I achieve benefit].Example:As a marketing manager,I want to export campaign reports to PDFSo that I can share results with stakeholders who don't have system access.
Improvement Story:
As a [persona],I need [capability/improvement]To [achieve goal more effectively].Example:As a sales rep,I need faster search resultsTo find customer records without interrupting calls.
Bug Fix Story:
As a [persona],I expect [correct behavior]When [specific condition].Example:As a user,I expect my session to remain activeWhen navigating between dashboard tabs.
Integration Story:
As a [persona],I want to [integrate/connect with system]So that [workflow improvement].Example:As an admin,I want to sync user data with our LDAP serverSo that employees are automatically provisioned.
Enabler Story (Technical):
As a developer,I need to [technical requirement]To enable [user-facing capability].Example:As a developer,I need to implement caching layerTo enable sub-second dashboard load times.
Persona Library
Persona
Typical Needs
Context
End User
Efficiency, simplicity, reliability
Daily core feature usage
Administrator
Control, visibility, security
System management
Power User
Automation, customization, shortcuts
Expert workflows
New User
Guidance, learning, safety
Onboarding experience
Manager
Reporting, oversight, delegation
Team coordination
External User
Access, security, documentation
Customer/partner usage
Acceptance Criteria Patterns
Given-When-Then (Gherkin)
Preferred format for testable acceptance criteria:
Given [precondition/context],When [action/trigger],Then [expected outcome].
Examples:
Given the user is logged in with valid credentials,When they click the "Export" button,Then a PDF download starts within 2 seconds.Given the user has entered invalid email format,When they submit the registration form,Then an inline error message displays "Please enter a valid email address."Given the daily sync job has not run in 24 hours,When the scheduler triggers at midnight,Then all pending records are synchronized and logged.
Should/Must/Can Patterns
Should (Expected Behavior):
Should [behavior] when [condition].Example:Should display loading spinner when API call exceeds 500ms.
Must (Hard Requirement):
Must [requirement] to [achieve outcome].Example:Must encrypt all data at rest to meet compliance requirements.
Can (Capability):
Can [capability] without [negative outcome].Example:Can undo last action without losing other changes.
Acceptance Criteria Checklist
Each story should have acceptance criteria covering:
Category
Example Criterion
Happy Path
Given valid input, When submitted, Then success message displayed
Validation
Should reject input when required field is empty
Error Handling
Must show user-friendly message when API fails
Performance
Should complete operation within 2 seconds
Accessibility
Must be navigable via keyboard only
Security
Should not expose sensitive data in URL parameters
Minimum Acceptance Criteria Count
Story Size (Points)
Minimum AC Count
1-2
3-4
3-5
4-6
8
5-8
13+
Split the story
INVEST Criteria
INVEST Validation Checklist
Criterion
Question
Pass If...
Independent
Can this story be developed without depending on another story?
No blocking dependencies on uncommitted work
Negotiable
Is the implementation approach flexible?
Multiple ways to deliver the value
Valuable
Does this deliver value to users or business?
Clear benefit statement in "so that"
Estimable
Can the team estimate this story?
Understood well enough to size
Small
Can this be completed in one sprint?
≤8 story points typically
Testable
Can we verify this story is done?
Clear, measurable acceptance criteria
INVEST Failure Patterns
Criterion
Red Flag
Fix
Independent
"After story X is done..."
Combine stories or resequence
Negotiable
Specific implementation in story
Focus on outcome, not solution
Valuable
No "so that" clause
Add benefit statement
Estimable
Team says "no idea"
Spike first, then story
Small
>8 points
Split into smaller stories
Testable
"System should be better"
Add measurable criteria
Story Splitting Techniques
When stories are too large (>8 points), split using:
#!/usr/bin/env python3"""User Story Generator with INVEST CriteriaCreates well-formed user stories with acceptance criteria"""import jsonfrom typing import Dict, List, Tupleclass UserStoryGenerator: """Generate INVEST-compliant user stories""" def __init__(self): self.personas = { 'end_user': { 'name': 'End User', 'needs': ['efficiency', 'simplicity', 'reliability', 'speed'], 'context': 'daily usage of core features' }, 'admin': { 'name': 'Administrator', 'needs': ['control', 'visibility', 'security', 'configuration'], 'context': 'system management and oversight' }, 'power_user': { 'name': 'Power User', 'needs': ['advanced features', 'automation', 'customization', 'shortcuts'], 'context': 'expert usage and workflow optimization' }, 'new_user': { 'name': 'New User', 'needs': ['guidance', 'learning', 'safety', 'clarity'], 'context': 'first-time experience and onboarding' } } self.story_templates = { 'feature': "As a {persona}, I want to {action} so that {benefit}", 'improvement': "As a {persona}, I need {capability} to {achieve_goal}", 'fix': "As a {persona}, I expect {behavior} when {condition}", 'integration': "As a {persona}, I want to {integrate} so that {workflow}" } self.acceptance_criteria_patterns = [ "Given {precondition}, When {action}, Then {outcome}", "Should {behavior} when {condition}", "Must {requirement} to {achieve}", "Can {capability} without {negative_outcome}" ] def generate_epic_stories(self, epic: Dict) -> List[Dict]: """Break down epic into user stories""" stories = [] # Analyze epic for key components epic_name = epic.get('name', 'Feature') epic_description = epic.get('description', '') personas = epic.get('personas', ['end_user']) scope = epic.get('scope', []) # Generate stories for each persona and scope item for persona in personas: for i, scope_item in enumerate(scope): story = self.generate_story( persona=persona, feature=scope_item, epic=epic_name, index=i+1 ) stories.append(story) # Add enabler stories (technical, infrastructure) if epic.get('technical_requirements'): for req in epic['technical_requirements']: enabler = self.generate_enabler_story(req, epic_name) stories.append(enabler) return stories def generate_story(self, persona: str, feature: str, epic: str, index: int) -> Dict: """Generate a single user story""" persona_data = self.personas.get(persona, self.personas['end_user']) # Create story story = { 'id': f"{epic[:3].upper()}-{index:03d}", 'type': 'story', 'title': self._generate_title(feature), 'narrative': self._generate_narrative(persona_data, feature), 'acceptance_criteria': self._generate_acceptance_criteria(feature), 'estimation': self._estimate_complexity(feature), 'priority': self._determine_priority(persona, feature), 'dependencies': [], 'invest_check': self._check_invest_criteria(feature) } return story def generate_enabler_story(self, requirement: str, epic: str) -> Dict: """Generate technical enabler story""" return { 'id': f"{epic[:3].upper()}-E{len(requirement):02d}", 'type': 'enabler', 'title': f"Technical: {requirement}", 'narrative': f"As a developer, I need to {requirement} to enable user features", 'acceptance_criteria': [ f"Technical requirement {requirement} is implemented", "All tests pass", "Documentation is updated", "No regression in existing functionality" ], 'estimation': 5, # Default medium complexity 'priority': 'high', 'dependencies': [], 'invest_check': { 'independent': True, 'negotiable': False, # Technical requirements often non-negotiable 'valuable': True, 'estimable': True, 'small': True, 'testable': True } } def _generate_title(self, feature: str) -> str: """Generate concise story title""" # Simplify feature description to title words = feature.split()[:5] return ' '.join(words).title() def _generate_narrative(self, persona: Dict, feature: str) -> str: """Generate story narrative in standard format""" template = self.story_templates['feature'] action = self._extract_action(feature) benefit = self._extract_benefit(feature, persona['needs']) return template.format( persona=persona['name'], action=action, benefit=benefit ) def _generate_acceptance_criteria(self, feature: str) -> List[str]: """Generate acceptance criteria""" criteria = [] # Happy path criteria.append(f"Given user has access, When they {self._extract_action(feature)}, Then {self._extract_outcome(feature)}") # Validation criteria.append(f"Should validate input before processing") # Error handling criteria.append(f"Must show clear error message when action fails") # Performance criteria.append(f"Should complete within 2 seconds") # Accessibility criteria.append(f"Must be accessible via keyboard navigation") return criteria def _extract_action(self, feature: str) -> str: """Extract action from feature description""" action_verbs = ['create', 'view', 'edit', 'delete', 'share', 'export', 'import', 'configure', 'search', 'filter'] feature_lower = feature.lower() for verb in action_verbs: if verb in feature_lower: return feature_lower return f"use {feature.lower()}" def _extract_benefit(self, feature: str, needs: List[str]) -> str: """Extract benefit based on feature and persona needs""" feature_lower = feature.lower() if 'save' in feature_lower or 'quick' in feature_lower: return "I can save time and work more efficiently" elif 'share' in feature_lower or 'collab' in feature_lower: return "I can collaborate with my team effectively" elif 'report' in feature_lower or 'analyt' in feature_lower: return "I can make data-driven decisions" elif 'automat' in feature_lower: return "I can reduce manual work and errors" else: return f"I can achieve my goals related to {needs[0]}" def _extract_outcome(self, feature: str) -> str: """Extract expected outcome""" return f"the {feature.lower()} is successfully completed" def _estimate_complexity(self, feature: str) -> int: """Estimate story points based on complexity indicators""" feature_lower = feature.lower() # Complexity indicators complexity = 3 # Base complexity if any(word in feature_lower for word in ['simple', 'basic', 'view', 'display']): complexity = 1 elif any(word in feature_lower for word in ['create', 'edit', 'update']): complexity = 3 elif any(word in feature_lower for word in ['complex', 'advanced', 'integrate', 'migrate']): complexity = 8 elif any(word in feature_lower for word in ['redesign', 'refactor', 'architect']): complexity = 13 return complexity def _determine_priority(self, persona: str, feature: str) -> str: """Determine story priority""" feature_lower = feature.lower() # Critical features if any(word in feature_lower for word in ['security', 'fix', 'critical', 'broken']): return 'critical' # High priority for primary personas if persona in ['end_user', 'admin']: if any(word in feature_lower for word in ['core', 'essential', 'primary']): return 'high' # Medium for improvements if any(word in feature_lower for word in ['improve', 'enhance', 'optimize']): return 'medium' # Low for nice-to-haves return 'low' def _check_invest_criteria(self, feature: str) -> Dict[str, bool]: """Check INVEST criteria compliance""" return { 'independent': not any(word in feature.lower() for word in ['after', 'depends', 'requires']), 'negotiable': True, # Most features can be negotiated 'valuable': True, # Assume value if it made it to backlog 'estimable': len(feature.split()) < 20, # Can estimate if not too vague 'small': self._estimate_complexity(feature) <= 8, # 8 points or less 'testable': not any(word in feature.lower() for word in ['maybe', 'possibly', 'somehow']) } def generate_sprint_stories(self, capacity: int, backlog: List[Dict]) -> Dict: """Generate stories for a sprint based on capacity""" sprint = { 'capacity': capacity, 'committed': [], 'stretch': [], 'total_points': 0, 'utilization': 0 } # Sort backlog by priority and size sorted_backlog = sorted( backlog, key=lambda x: ( {'critical': 0, 'high': 1, 'medium': 2, 'low': 3}[x['priority']], x['estimation'] ) ) # Fill sprint for story in sorted_backlog: if sprint['total_points'] + story['estimation'] <= capacity: sprint['committed'].append(story) sprint['total_points'] += story['estimation'] elif sprint['total_points'] + story['estimation'] <= capacity * 1.2: sprint['stretch'].append(story) sprint['utilization'] = round((sprint['total_points'] / capacity) * 100, 1) return sprint def format_story_output(self, story: Dict) -> str: """Format story for display""" output = [] output.append(f"USER STORY: {story['id']}") output.append("=" * 40) output.append(f"Title: {story['title']}") output.append(f"Type: {story['type']}") output.append(f"Priority: {story['priority'].upper()}") output.append(f"Points: {story['estimation']}") output.append("") output.append("Story:") output.append(story['narrative']) output.append("") output.append("Acceptance Criteria:") for i, criterion in enumerate(story['acceptance_criteria'], 1): output.append(f" {i}. {criterion}") output.append("") output.append("INVEST Checklist:") for criterion, passed in story['invest_check'].items(): status = "✓" if passed else "✗" output.append(f" {status} {criterion.capitalize()}") return "\n".join(output)def create_sample_epic(): """Create a sample epic for testing""" return { 'name': 'User Dashboard', 'description': 'Create a comprehensive dashboard for users to view their data', 'personas': ['end_user', 'power_user'], 'scope': [ 'View key metrics and KPIs', 'Customize dashboard layout', 'Export dashboard data', 'Share dashboard with team members', 'Set up automated reports' ], 'technical_requirements': [ 'Implement caching for performance', 'Set up real-time data pipeline' ] }def main(): import sys generator = UserStoryGenerator() if len(sys.argv) > 1 and sys.argv[1] == 'sprint': # Generate sprint planning capacity = int(sys.argv[2]) if len(sys.argv) > 2 else 30 # Create sample backlog epic = create_sample_epic() backlog = generator.generate_epic_stories(epic) # Plan sprint sprint = generator.generate_sprint_stories(capacity, backlog) print("=" * 60) print("SPRINT PLANNING") print("=" * 60) print(f"Sprint Capacity: {sprint['capacity']} points") print(f"Committed: {sprint['total_points']} points ({sprint['utilization']}%)") print(f"Stories: {len(sprint['committed'])} committed + {len(sprint['stretch'])} stretch") print("\n📋 COMMITTED STORIES:\n") for story in sprint['committed']: print(f" [{story['priority'][:1].upper()}] {story['id']}: {story['title']} ({story['estimation']}pts)") if sprint['stretch']: print("\n🎯 STRETCH GOALS:\n") for story in sprint['stretch']: print(f" [{story['priority'][:1].upper()}] {story['id']}: {story['title']} ({story['estimation']}pts)") else: # Generate stories for epic epic = create_sample_epic() stories = generator.generate_epic_stories(epic) print(f"Generated {len(stories)} stories from epic: {epic['name']}\n") # Display first 3 stories in detail for story in stories[:3]: print(generator.format_story_output(story)) print("\n") # Summary of all stories print("=" * 60) print("BACKLOG SUMMARY") print("=" * 60) total_points = sum(s['estimation'] for s in stories) print(f"Total Stories: {len(stories)}") print(f"Total Points: {total_points}") print(f"Average Size: {total_points/len(stories):.1f} points") print("\nPriority Breakdown:") for priority in ['critical', 'high', 'medium', 'low']: count = len([s for s in stories if s['priority'] == priority]) if count > 0: print(f" {priority.capitalize()}: {count} stories")if __name__ == "__main__": main()
Install this Skill
Skills give your AI agent a consistent, structured approach to this task — better output than a one-off prompt.