← All posts
·6 min read
View .md

Write your first behavior spec in 15 minutes

A step-by-step guide to writing a .pbc.md file for your product's most critical module. Start with plain Markdown, then add structured blocks that tools and agents can read.

product-behavior-contractpbc-specdeveloper-experienceai-coding

TL;DR: Pick your riskiest module (billing, auth, or entitlements). Write down what must happen, what must not happen, and the edge cases. Put it in a .pbc.md file in your repo. That's it — you now have a behavior spec. This guide walks through the whole process.

Every other post on this blog explains why behavior specs matter. This one shows you how to write one.

You'll need: a code editor, 15 minutes, and one module in your product where an agent mistake would actually hurt.

Step 1: Pick the module

Don't try to contract your entire product. Start with the module where getting it wrong costs the most.

Good first candidates:

Pick one. For this tutorial, we'll use billing.

Step 2: Create the file

Create a file called billing.pbc.md in your repo. The .pbc.md extension is a convention — it's still plain Markdown. Put it wherever makes sense: the root, a docs/ folder, or alongside the code it describes.

Start with frontmatter:

---
id: billing
title: Billing & Subscriptions
context: billing
status: draft
updated: 2026-04-04
---

The status: draft is honest — you're writing this for the first time. It'll become trusted once your team has reviewed and confirmed the behaviors.

Step 3: Define the scope

Write a short section describing what this contract covers and what it doesn't. This prevents scope creep and tells readers (human and agent) where the boundaries are.

# Billing & Subscriptions

## Scope

- Subscription lifecycle (trial, active, past due, cancelled, expired)
- Payment failure and grace period behavior
- Plan limits and what happens when they're exceeded

## Non-goals

- Payment gateway API details (that's implementation)
- Invoice formatting (that's presentation)
- Tax calculation logic (that's a separate module)

Step 4: List your terms

If your module uses domain-specific language, define it. This eliminates ambiguity — the grace period means exactly this, not whatever someone infers from the code.

## Glossary

| Term | Definition |
| --- | --- |
| Grace period | The 14-day recovery window after a failed renewal payment. |
| Billing cycle | The recurring period (monthly or annual) between charges. |
| Plan limits | The monthly usage caps for a given subscription tier. |

Step 5: Write the behaviors

This is the core of the contract. For each behavior, write:

Start with the happy path, then add failure cases and edge cases.

## Behaviors

### Automatic renewal

#### Given

- The subscription is active
- The current billing cycle ends today
- A valid payment method exists

#### When

The system processes the subscription for renewal.

#### Then

1. A charge is submitted to the payment processor
2. On success: subscription stays active, billing cycle advances
3. Plan limits reset for the new period

---

### Payment failure and grace period

#### Given

- The subscription is active
- A renewal charge fails

#### When

The payment processor reports a failed charge.

#### Then

1. Subscription moves to past_due status
2. User retains full access for 14 days (the grace period)
3. System retries the payment on days 1, 3, and 7
4. If payment succeeds during grace period: subscription returns to active
5. If grace period ends without payment: subscription moves to expired

#### Invariants

- Grace period is exactly 14 days — not configurable per plan
- No data deletion occurs during grace period
- User is notified on each retry attempt

#### Edge cases

- If user manually updates their payment method during grace period: immediate retry
- If user downgrades plan during grace period: grace period continues on the new plan

That's a behavior spec. It's readable by your team, your agents, and anyone who touches this code six months from now.

Step 6: Add structured blocks (optional but powerful)

Plain Markdown is already useful. But if you want tools and agents to parse the spec deterministically — not just read it as prose — you can add pbc:* fenced blocks.

These are YAML blocks inside Markdown code fences with a pbc: prefix. They look like code blocks to a Markdown renderer, but a PBC-aware tool can extract them as typed data.

For example, add a structured version of the glossary:

```pbc:glossary
- term: Grace period
  definition: The 14-day recovery window after a failed renewal payment.
- term: Billing cycle
  definition: The recurring period (monthly or annual) between charges.
- term: Plan limits
  definition: The monthly usage caps for a given subscription tier.
```

And a structured version of a behavior:

```pbc:behavior
id: BIL-BHV-002
name: Payment failure and grace period
actor: billing_scheduler
description: When a renewal charge fails, the system enters a 14-day grace period with retries before expiring the subscription.
```

```pbc:preconditions
- The subscription is in active.
- A renewal charge fails.
```

```pbc:trigger
The payment processor reports a failed charge.
```

```pbc:outcomes
- Subscription moves to past_due.
- User retains full access for 14 days.
- System retries payment on days 1, 3, and 7.
- If payment succeeds: subscription returns to active.
- If grace period ends without payment: subscription moves to expired.
```

You don't have to add structured blocks for everything. Start with plain Markdown. Add pbc:* blocks to the behaviors that are most critical — the ones where you want a tool to be able to verify they're still honored.

Step 7: Point your agents at it

Add a line to your CLAUDE.md, AGENTS.md, or whatever instruction file your agents read:

Before modifying any billing, auth, or entitlement logic, read the relevant
`.pbc.md` file in this repo. Do not change behaviors marked as invariants
without explicit approval.

This is the bridge between your existing agent workflow and the behavior spec. The instruction file says "look here first." The behavior spec says "here's what the product promises."

Step 8: Review with your team

Share the .pbc.md file with your team. Ask two questions:

  1. Is this accurate? Does the spec match what the product actually does?
  2. Is anything missing? Are there behaviors or edge cases that should be captured?

When you and your team agree the spec is accurate, change status: draft to status: trusted.

That's it. You have a living behavior spec — your product truth — in your repo.

What you just built

In 15 minutes, you created an artifact that:

You didn't write documentation. You wrote product truth — a structured statement of what the product promises to do, explicit enough that both humans and agents can hold the code accountable to it.

Next steps

Related posts

Stewie reads your codebase and helps you author a living product behavior spec. We're onboarding a small group of product and engineering teams before public launch. Request early access →