The Cost Model & cost_events Table

Every token spend creates a cost_event row: amount_usd, agent_id, run_id, model, input_tokens, output_tokens, timestamp. How the server computes amount_usd from model pricing tables.

The Cost Model: How Paperclip Tracks Spending

What you'll learn

The complete cost_events table, how costs are calculated per model, and the two-layer budget system (per-agent and per-company).

Every LLM Call Costs Money

Paperclip's cost model has one rule: every adapter invocation that uses tokens creates a cost_events row. This makes the audit trail complete and the budget enforcement reliable.

The cost_events Table

CREATE TABLE public.cost_events (
  id               uuid        PRIMARY KEY DEFAULT gen_random_uuid(),
  company_id       uuid        NOT NULL REFERENCES companies(id),
  agent_id         uuid        NOT NULL REFERENCES agents(id),
  heartbeat_run_id uuid        REFERENCES heartbeat_runs(id),
  issue_id         uuid        REFERENCES issues(id),
  model            text        NOT NULL,
  input_tokens     int         NOT NULL DEFAULT 0,
  output_tokens    int         NOT NULL DEFAULT 0,
  cost_usd         numeric(10,6) NOT NULL DEFAULT 0,
  created_at       timestamptz NOT NULL DEFAULT now()
);

How Cost Is Calculated

Each adapter reports inputTokens, outputTokens, and model. Paperclip multiplies by the per-model rate in pricing.ts:

// packages/server/src/lib/costs/pricing.ts
export type TokenPricing = { input: number; output: number }; // per 1K tokens

export const PRICING: Record<string, TokenPricing> = {
  'claude-opus-4-5':        { input: 0.015,   output: 0.075  },
  'claude-sonnet-4-5':      { input: 0.003,   output: 0.015  },
  'claude-haiku-3-5':       { input: 0.00025, output: 0.00125 },
  'gpt-4o':                 { input: 0.005,   output: 0.015  },
  'gpt-4o-mini':            { input: 0.00015, output: 0.0006 },
  'llama3-70b-8192':        { input: 0.00027, output: 0.00027 },
};

export function calculateCost(model: string, inputTokens: number, outputTokens: number): number {
  const pricing = PRICING[model];
  if (!pricing) return 0;
  return (inputTokens / 1000 * pricing.input) + (outputTokens / 1000 * pricing.output);
}

The Two-Layer Budget System

Company budget ($50/month)
  ├── Agent: CEO         budget $20/month
  ├── Agent: Researcher  budget $15/month
  └── Agent: Writer      budget $10/month

Agent-level enforcement: before claiming a new issue, the heartbeat checks if the agent's MTD spend < monthly_budget_usd. If not, the agent is skipped (set to paused).

Company-level enforcement: when cumulative MTD company spend exceeds companies.monthly_budget_usd, the entire company is paused — no agents run until the month rolls over or the budget is raised.

Querying MTD Spend

-- Current month spend per agent
SELECT
  a.name,
  a.monthly_budget_usd              AS budget,
  COALESCE(SUM(ce.cost_usd), 0)     AS spent,
  a.monthly_budget_usd
    - COALESCE(SUM(ce.cost_usd), 0) AS remaining,
  ROUND(100 * COALESCE(SUM(ce.cost_usd), 0)
    / NULLIF(a.monthly_budget_usd, 0)) AS pct_used
FROM agents a
LEFT JOIN cost_events ce
  ON ce.agent_id = a.id
  AND date_trunc('month', ce.created_at) = date_trunc('month', now())
WHERE a.company_id = 'your-company-id'
GROUP BY a.id, a.name, a.monthly_budget_usd
ORDER BY pct_used DESC NULLS LAST;

Checkpoint ✓

Sign in for progress tracking & Q&A →