ROLE: Product Manager
Ingest feature requests, cluster them by theme, score against strategy, and draft a roadmap brief
halo
// ============================================================
// ROLE: Product Manager
// PURPOSE: Ingest feature requests, cluster them by theme,
// score against strategy, and draft a roadmap brief
// ============================================================
policy BudgetPolicy : MaxSpend(1.00)
policy StrategyAlign : Enforce(ProductStrategy.JSON)
// --- Tools ---
tool Linear : POST("api.linear.app/graphql", apiKey: Env.LINEAR_KEY)
tool Notion : POST("api.notion.com/v1/pages", apiKey: Env.NOTION_KEY)
tool SlackPM : POST("hooks.slack.com/services/pm-team")
// --- Store ---
tool RequestHistory : VectorStore(Env.PINECONE_KEY, namespace: "feature-requests")
tool ProductDocs : VectorStore(Env.PINECONE_KEY, namespace: "product-strategy")
// --- Agents ---
agent Clustering [openai/gpt-4o-mini, temp: 0.2]
system """
You are a feature request analyst. Cluster raw user
requests into coherent themes by user segment, problem
area, and urgency. Deduplicate and normalize language.
"""
requires BudgetPolicy
agent Strategist [anthropic/claude-sonnet-4, temp: 0.3]
system """
You are a product strategist. Score feature clusters
against strategic goals using a weighted matrix. Prioritize
by revenue impact, retention lift, competitive edge, and
engineering effort. Output ranked recommendations.
"""
equips ProductDocs
requires StrategyAlign, BudgetPolicy
agent Writer [openai/gpt-4o-mini, temp: 0.5]
system """
You are a product communications writer. Draft roadmap
briefings with strategic narrative arc. Lead with the
"why now," follow with prioritized themes, close with
resource asks and timeline.
"""
equips Notion
// --- The Pipeline ---
@timeout(10m)
pipeline RoadmapBrief(requests: FeatureRequests) -> Briefing:
requests
// Step 1: Cluster raw requests into themes
|> Clustering.cluster(
context.data.requests.items,
["user_segment", "problem_area", "urgency"],
8
) as clusters
// Step 2: Gate — need at least 3 items to be actionable
|? (context.data.clusters.total_items > 3)
// Step 3: Score each cluster against strategic goals
|> Strategist.score(
context.data.clusters.themes,
ProductDocs,
["revenue_impact", "retention", "competitive_edge", "effort"]
) as scoring
// Step 4: Gate — drop clusters below threshold
|? (context.data.scoring.top_scores > 50)
// Step 5: Draft the roadmap brief, then save it to Notion
|> Writer.compose(
"RoadmapBrief",
[context.data.clusters, context.data.scoring.ranked],
"strategic_narrative"
) as draft
|> Notion.create_page(
title: "Roadmap Brief",
content: context.data.draft
) as notion
// Step 6: Send draft to PM Slack for feedback
|! yield(
SlackPM,
context.data.draft.executive_summary,
[context.data.notion.doc_url],
24h
)
// Step 7: Wait for PM review
~> listen(SlackPM.Reaction) as pm_review
// Step 8: Gate on approval
|? (context.data.pm_review.status == "approved")
|> System.Publish(
context.data.notion.doc_id,
"product-team"
)