The "As a… I want… so that…" line of a user story.
A user story is a short, plain-language description of a piece of functionality told from the point of view of the person who wants it. It fits on an index card, names a user, a desire, and a reason, and it is deliberately incomplete: the card is a placeholder for a conversation the team still owes itself.
User stories came out of Extreme Programming. Kent Beck described them in *Extreme Programming Explained* (1999) as the unit of planning in XP's planning game: customers write down the featuresFeatureProduct SpecificationA product capability or featureView reference → they want in their own words, and developers estimate and schedule them. The point was to keep requirements light enough that a business person and a programmer could discuss one face to face.
The template most teams recognise came later. In 2001 the XP team at Connextra in London settled on "As a <role>, I want <goal>, so that <benefit>", and the form spread from there. Ron Jeffries gave the practice its discipline with the Three Cs: the Card holds a token of the requirement, the Conversation fleshes it out, and the Confirmation captures how everyone will know it is done. The card is the smallest part; the conversation is the work.
Mike Cohn generalised the practice in User Stories Applied (2004), still the standard reference, moving the idea past physical cards into a way of working. Bill Wake then gave teams a quality test with the INVEST mnemonic: a good story is Independent, Negotiable, Valuable, Estimable, Small, and Testable. INVEST is where the live debate sits. "Valuable" pushes back on stories that describe internal plumbing with no user-visible payoff, and "Independent" is the one teams break most often, since real backlogs are full of stories that secretly depend on each other.
A payments team wants to reduce failed renewals. Someone proposes the story: "As a subscriber whose card has expired, I want to be warned before my renewal date, so that my subscriptionSubscriptionSales & RevenueA recurring subscriptionView reference → does not lapse." It scores well on INVEST. It is small, it is testable, and the benefit clause states why it matters in revenue terms.
The conversation that follows decides the detail the card omits. How far ahead is the warning, by email or in-app, what happens to a subscriber who ignores it. Those answers become acceptance criteria: a reminder fires seven days out, a second fires on the renewal date, and a dunning flow retries the charge three times across five days. The story stays a sentence. The criteria carry the precision, and the test suiteTest SuiteQuality AssuranceA suite of related testsView reference → checks them. Six weeks on, the team can point at one shipped story and a measured drop in involuntary churn, because the story named a user and a reason, which a screen mockup never would.
In the Unified Product Graph the user story lives in the Product & Delivery region, which models the work-breakdown spine feature → epic → story → task. A story sits inside an epicEpicProduct SpecificationA large body of work that can be broken into storiesView reference → through Epicspecified byUser Storyhierarchy, decomposes downward through epic_specified_by_user_storyuser_story_broken_into_task, and is pinned to its definition of done through User Storyverified byAcceptance Criterionhierarchy. This structure keeps the Three Cs honest: the card is the node, the tasks and criteria are the conversation and the confirmation made queryable, and a story that connects to neither is visibly underspecified. Note that the canonical spec treats user_story_verified_by_acceptance_criterionUser StoryProduct SpecificationA user's goal and the value they expect, in the "As a… I want… So that…" format. Now also a first-class plannable unit (priority, effort, assignee, due_date) that schedules into a planning_cycle, and it round-trips an external board's column via workflow_state. as a label on delivery work and folds thin, task-shaped stories into user_storyTaskProduct SpecificationA unit of work within a story or epicView reference → at the leaf; the region preserves the story role for teams who plan at story granularity.task
Worked example: Trellis
One of Trellis's core user stories is: as a director, I want to see how a structural change will affect every existing record before it runs, so that I can approve it with confidence. That story sits under the Safe Change epicEpicProduct SpecificationA large body of work that can be broken into storiesView reference → and drives the acceptance criteria for the preview the director reviews before any agent change is applied.
Urgent Blocking progress or time-critical; must be addressed immediately.
Type-specific fields on BaseNode
as_astring"As a [persona], …". Free-text persona name or slug ref.
i_want_tostringCapability or action the persona wants.
so_thatstringBenefit or outcome the persona expects.
textstringFree-form story text. Used as a single-line rendered view.
assigneestringAssigned person. Promote to a `node_owned_by_person` edge if ownership must be queryable.
effortstringEffort estimate (e.g. "2h", "1d", "3 points"). Use a consistent unit within your team.
priorityenumRelative importance against other stories. Lifted onto user_story (0.20.0) so the story is a first-class plannable unit alongside task, matching Jira/Linear where the story/issue is the estimated-and-assigned atom.
due_datestringISO date due. Typically bounded by the release or planning_cycle the story is scheduled into.
workflow_statestringThe source tool's raw custom workflow state, verbatim and opaque (e.g. "In Review", "QA", "Needs Triage"). Non-canonical and never reasoned over: it exists to round-trip an import losslessly. Map it onto a canonical bucket with `workflow_state_category`; canonical `status` stays the sole reasoning axis.
workflow_state_categorystringCanonical bucket the raw `workflow_state` maps onto for reasoning (a source "In Review" and "QA" might both map to a verification phase). Optional companion to `workflow_state`: it lets a graph reason over an imported custom workflow without promoting the raw label to `status`.
idstringrequiredUnique identifier (UUID)
typeNodeTyperequiredDiscriminator for the entity type
titlestringrequiredDisplay name
descriptionstringOptional detailed description
statusstringLifecycle status
tagsstring[]Freeform tags for filtering
5 edge types connected to this entity.
epic_specified_by_user_storyuser_story_verified_by_acceptance_criteriontask_implements_user_storyplanning_cycle_schedules_user_storytest_case_covers_user_story1 framework use this entity type.