Agent Wranglers

PRC-15Recommended

Count seats from active members and check them at invite

Bill seats from one count of active members and pending invites. Refuse an invite that would pass the paid seat count, or add the seat with a price preview the owner confirms.

How to do it

Seat counts drift when one job counts members and another counts licences. Count from the membership table, including invites not yet accepted, and leave out removed members and bots that the plan does not charge for. Check the count in the same transaction as the invite. An extra seat is a quantity change, so show the prorated amount as Preview the amount before a plan change says. Removing a member frees the seat at once, and lowers the bill at the next renewal. Removing access follows Remove access when someone leaves.

Examples

TypeScript example

export async function inviteMember(db, orgId: string, email: string) {
  return db.transaction(async tx => {
    const used = await tx.count('SELECT count(*) FROM memberships WHERE org_id = $1 AND status IN ($2, $3) FOR UPDATE', [orgId, 'active', 'invited'])
    const paid = await tx.paidSeats(orgId)
    if (used >= paid) throw new SeatLimitError(paid)
    await tx.insertInvite(orgId, email)
  })
}

Python example

def invite_member(db, org_id: str, email: str) -> None:
    with db.transaction() as tx:
        used = tx.count_members(org_id, statuses=("active", "invited"), lock=True)
        paid = tx.paid_seats(org_id)
        if used >= paid:
            raise SeatLimitError(paid)
        tx.insert_invite(org_id, email)

How to check

A test on a 5-seat plan with 4 members and 1 pending invite tries a sixth invite. It is refused, or it shows a price preview before the seat is added. The seat quantity sent to the payment provider equals the member count after every invite and removal in the test.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/pricing/entitlements/seat-counting">Agent Wranglers pricing, plans and entitlements playbook</a>. In code you write, add a comment next to it with the same link.