Price, customize, and provision compute for your AI agent.
Free calculators and a skill file your agent follows. It prices only with your own quotes. No sign-up, no keys.
Example12,000 requests a day, 1,500 tokens in and 300 out. Self-host Qwen3.6 27B on H100 SXM at $2.00 a GPU-hour, or call an API at $0.70 in and $2.80 out per million tokens. Latency target 8 s.
The API is cheaper by $25.32 a day
- Self-host
- $48.00 a day
- 1 GPU, 1.1% busy on average
- Hosted API
- $22.68 a day
- $1.89 per 1,000 requests
- Break-even
- 25,397
- requests a day where both cost the same
- Answer at peak
- 4.5 s
- meets your latency target
- Self-host$48.00
- Hosted API$22.68
Example10,000 calls of 6,000 tokens in (4,000 cacheable) and 800 out, 12 s each. Limits of 4,000 requests and 2M input tokens a minute; $2.40 in and $9.60 out per million tokens; a $300.00 budget.
Keep 53 calls in flight; done in about 39.1 min
- Calls in flight
- 53
- input tokens per minute is the limit that binds
- Time to finish
- 39.1 min
- 10,310 calls with retries
- Cost with cache
- $158.36
- $227.64 without
- Hard cap
- $190.03
- inside your $300.00 budget
- No cache$227.64
- With cache$158.36
- Batch mode$113.82
Example8 GPUs on a 6-hour job, one interruption every 4 hours on average, 3-minute checkpoints. $1.20 spot or $3.00 on-demand per GPU-hour.
Spot is cheaper by $73.35
- Spot, expected
- 7.4 h
- $70.65
- Spot, 2× interruptions
- 8.4 h
- $80.51
- On-demand
- 6 h
- $144.00
- Checkpoint every
- 37.9 min
- 7.9% overhead
- Spot$70.65
- Spot, 2× interruptions$80.51
- On-demand$144.00
Estimates on the example numbers shown. The prices are illustrative inputs, not quotes; compute.md has no prices of its own.
- Know before you rent: what fits on which GPUs, and whether self-hosting beats an API at your volume.
- Spend on purpose: pace thousands of model calls under your rate limits, with a cost and a hard cap up front.
- Stop on time: budget, approval and stop rules your agent follows, then a teardown check.
- Cap model spend for real: an optional local meter refuses model calls routed through it when their worst case could pass your cap. How it works
Calculators
Price it with your numbers.
Five calculators for the compute questions that cost the most when an agent guesses. Type your own quotes and limits: compute.md has no prices of its own, and nothing you type is stored. Each one shows its formula and assumptions, and each is also /api/v1/<name> and an MCP tool, so your agent gets the same answer.
Result · example inputs
- Self-host
- $48.00 a day
- 1 GPU, 1.1% busy on average
- Hosted API
- $22.68 a day
- $1.89 per 1,000 requests
- Break-even
- 25,397
- requests a day where both cost the same
- Answer at peak
- 4.5 s
- meets your latency target
- Self-host$48.00
- Hosted API$22.68
GET /api/v1/serve_cost?requests_per_day=12000&input_tokens=1500&output_tokens=300&peak_factor=3&latency_target_s=8&cached_input_share=0&model=Qwen/Qwen3.6-27B&gpu=h100-sxm&precision=fp8&kv=bf16&max_gpus=8&max_streams_per_replica=256&replica_gpus=1&gpu_usd_per_hour=2&api_usd_per_m_input=0.7&api_usd_per_m_output=2.8&always_on=true&target_utilization=0.7How it’s worked out: formula, assumptions, what isn’t checked
Formula
input_tokens_per_day = requests_per_day x input_tokens; output_tokens_per_day = requests_per_day x output_tokens; avg_requests_per_s = requests_per_day / 86400; peak_requests_per_s = avg x peak_factor, or as given, or peak_concurrency / answer_time; for each replica of n GPUs (fewest that fit up to max_gpus): per_stream = fit throughput at c streams / c; answer = ttft(input_tokens) + output_tokens / per_stream; in_flight = peak_requests_per_s x answer (Little's law), c iterated until it settles; replicas = ceil(in_flight / (target_utilization x c)); answer_time = ttft + output_tokens / per_stream_tok_s; utilization_avg = avg_output_tok_s / (replicas x replica_capacity_tok_s); self_host_usd_per_day = total_gpus x 24 x gpu_usd_per_hour; api_usd_per_request = (input_tokens x ((1 - cached_share) + cached_share x (1 - discount)) x usd_per_m_input + output_tokens x usd_per_m_output) / 1e6; usd_per_month = usd_per_day x 730 / 24; break_even_requests_per_day = gpus_per_replica x 24 x gpu_usd_per_hour / api_usd_per_request, for the cheapest replica shape that meets the latency target with every slot busy and carries that volume at the target utilization
Assumptions
- peak_source:
- peak_factor
- target_utilization:
- 0.7
- always_on:
- true
- hours_per_month:
- 730
- capacity:
- fit estimate. Replicas of the fewest GPUs that fit up to max_gpus are tried. Streams per replica settle at the peak load; per-answer speed = replica throughput / streams, with every slot busy (on the slow side). Replica capacity = throughput at the most streams its GPUs hold within the latency target.
- model:
- Qwen/Qwen3.6-27B
- precision:
- fp8
- weights:
- FP8
- kv:
- bf16
- context:
- 2048
- prompt_tokens:
- 1500
- max_gpus:
- 8
- max_streams_per_replica:
- 256
- streams_per_replica:
- 3
- sized_for:
- fewest_gpus
- peak_factor:
- 3
Not checked
- · Engineering and operations time to run your own serving.
- · Redundancy: a spare replica (N+1) for failures and deploys.
- · Network egress and storage for weights and logs.
- · Idle scale-down: cold starts, minimum billing and load time.
- · Quality differences between the self-hosted model and the API model.
- · API rate limits and your provider's terms.
- · Measured speeds: fit speeds are bandwidth-bound upper bounds; confirm with a short load test.
Not an approval or a recommendation. It compares cost and speed on the numbers and quotes you gave; check model quality, uptime needs and your providers' terms yourself.
Full response (JSON)
Use at your own risk. compute.md is provided as is, without warranty. Information here may be inaccurate, incomplete or not current, and is not verified; sizing figures are estimates. Not financial, legal or procurement advice. Confirm everything with your providers before you rent or buy. Terms
Result · example inputs
- Offer B
- $12.07
- $3.02 per GPU-hour
- Offer A
- $40.03
- $10.01 per GPU-hour
- Order flips
- from 5 h
- Offer A is cheaper for longer runs
- Not ranked
- 1
- see each offer's reasons
- Offer B$12.07
- Offer A$40.03
This call has list or object inputs: POST them as JSON to /api/v1/compare_quotes.
How it’s worked out: formula, assumptions, what isn’t checked
Formula
units = max over gpus, vcpus and memory_gb the plan needs of ceil(plan / offer unit); 1 when the plan needs none. unit price = price_usd_per_hour, or price_usd_per_gpu_hour x offer gpus. Expected wall hours W = plan.hours; on an interruptible offer with mtbi_hours, Daly's W = (T / tau) x M x e^(R/M) x (e^((tau + C)/M) - 1), M = mtbi_hours / units, C = checkpoint hours, R = restart hours, tau = sqrt(2 x C x M) (Young); with no checkpoint_minutes, tau = T and C = 0. billed seconds per unit = max(minimum_billed_seconds, ceil(W x 3600 / increment) x increment). compute = units x unit price x billed seconds / 3600. storage = storage_gb x storage_usd_per_gb_month x W / 730. egress = egress_gb x egress_usd_per_gb. setup = setup_usd, once per run. total = compute + storage + egress + setup. effective per GPU-hour = total / (plan.gpus x plan.hours). monthly = total x runs_per_month. Break-even: the nearest run lengths under and over plan.hours (searched from 0 to 10x plan.hours) where the runner-up's total drops below the cheapest's, found exactly between billing steps.
Assumptions
- billing_increment:
- 3600 s (by the hour) when an offer sends none; stated per offer.
- missing_prices:
- A cost item with no price is left out ($0) and listed under left_out_no_price and not_checked. An offer with no compute price is not ranked.
- missing_sizes:
- An offer that does not state a size the plan needs is not ranked (status unverified).
- units_together:
- All units of an offer run the plan together; any unit's interruption stalls the run.
- interruptions:
- Interruptions arrive at random at a steady rate. Restart time is billed. Time lost to interruptions is billed like any other time.
- not_finishing:
- An interruptible offer whose expected wall time passes 10x plan.hours is ineligible.
- storage:
- Pro-rated over the expected wall time, 730 hours to a month.
- setup:
- setup_usd is charged once per run.
- interruptible:
- An offer that does not send interruptible is treated as not interruptible.
Not checked
- · Offer A: no minimum_billed_seconds, priced with no minimum.
- · Offer C: no minimum_billed_seconds, priced with no minimum.
- · Whether each offer has capacity when you need it.
- · Taxes, commitments, discounts, credits and support fees.
- · Data transfer into the provider and between zones.
- · Billing restarts after interruptions: an interrupted run is billed as one continuous run.
A comparison of the offers you sent, on your numbers. Not a quote, an approval or a recommendation of any provider.
Full response (JSON)
Use at your own risk. compute.md is provided as is, without warranty. Information here may be inaccurate, incomplete or not current, and is not verified; sizing figures are estimates. Not financial, legal or procurement advice. Confirm everything with your providers before you rent or buy. Terms
Result · example inputs
- Calls in flight
- 53
- input tokens per minute is the limit that binds
- Time to finish
- 39.1 min
- 10,310 calls with retries
- Cost with cache
- $158.36
- $227.64 without
- Hard cap
- $190.03
- inside your $300.00 budget
- No cache$227.64
- With cache$158.36
- Batch mode$113.82
GET /api/v1/plan_fanout?tasks=10000&calls_per_task=1&input_tokens=6000&output_tokens=800&latency_s=12&rpm_limit=4000&input_tpm_limit=2000000&output_tpm_limit=400000&failure_rate=0.03&headroom=0.8&cached_prefix_tokens=4000&cache_read_multiplier=0.2&cache_write_multiplier=1.2&cache_hit_rate=0.9&cached_counts_toward_input_tpm=true&usd_per_m_input=2.4&usd_per_m_output=9.6&batch_discount=0.5&batch_turnaround_hours=24&budget_usd=300How it’s worked out: formula, assumptions, what isn’t checked
Formula
calls_total = ceil(tasks x calls_per_task / (1 - failure_rate)); counted_input = input_tokens, or input_tokens - cached_prefix_tokens x cache_hit_rate when cached tokens don't count; ceiling (calls/min) = limit x headroom / per-call use: rpm 1; input tpm counted_input; output tpm output_tokens; total tpm counted_input + output_tokens; concurrency latency_s / 60; target_calls_per_min = smallest ceiling; concurrency = floor(target_calls_per_min / 60 x latency_s), at least 1, at most concurrency_limit (Little's law); reached_calls_per_min = min(target_calls_per_min, concurrency x 60 / latency_s); time_to_finish_min = (calls_total - 1) / reached_calls_per_min + latency_s / 60 (the last call starts, then runs one latency); cost_no_cache = (calls_total x input_tokens x usd_per_m_input + calls_total x output_tokens x usd_per_m_output) / 1e6; cost_with_cache = ((uncached + prefix x hit x read_mult + prefix x (1 - hit) x write_mult) x calls_total x usd_per_m_input + output x usd_per_m_output) / 1e6, write_mult = 1 when only read_mult is sent; cache_break_even_hit_rate = (write_mult - 1) / (write_mult - read_mult); batch_cost = cost_no_cache x (1 - batch_discount); suggested_hard_cap = min(expected x 1.2, budget_usd); tasks_affordable = floor(budget_usd / (expected / tasks))
Assumptions
- headroom:
- 0.8
- failure_rate:
- 0.03
- retries:
- every failed call is retried until it succeeds and is billed as a full call
- cache_hit_rate:
- 0.9
- cached_counts_toward_input_tpm:
- true
- cache_write:
- a call that misses the cache writes the prefix at the write multiplier
- cache_write_multiplier:
- 1.2
- hard_cap:
- expected cost plus 20%, never above budget_usd
- steady_state:
- calls run at a steady rate; ramp-up and bursts are not modeled
- prices:
- only the prices you sent; none are built in
- batch:
- the batch discount is applied to the no-cache cost; whether it stacks with caching depends on your terms
Not checked
- · Whether your limits are per model, per key or per account, and how they count bursts.
- · Whether output limits count max_tokens up front instead of tokens returned.
- · Whether failed calls are billed: they are counted here as full calls.
- · Whether cached tokens count toward your input limit: assumed yes. Set cached_counts_toward_input_tpm to false if not.
A planning estimate on your numbers. Not an approval, a quote or a recommendation.
Full response (JSON)
Use at your own risk. compute.md is provided as is, without warranty. Information here may be inaccurate, incomplete or not current, and is not verified; sizing figures are estimates. Not financial, legal or procurement advice. Confirm everything with your providers before you rent or buy. Terms
Result · example inputs
- Input billed
- 3.3M tokens
- context peaks at 141K
- Per session
- $6.62
- static caching
- Cheapest caching
- $2.87
- rolling caching
- Per month
- $9,924.12
- 1,500 sessions
- No cache$8.11
- Static cache$6.62
- Rolling cache$2.87
GET /api/v1/estimate_run?turns=40&system_tokens=3000&tool_schema_tokens=20000&first_message_tokens=1000&added_tokens_per_turn=2500&output_tokens_per_turn=500&context_limit=200000&cache_mode=static&cache_read_multiplier=0.2&cache_write_multiplier=1.2&cache_hit_rate=0.9&usd_per_m_input=2.4&usd_per_m_output=9.6&sessions_per_day=50How it’s worked out: formula, assumptions, what isn’t checked
Formula
context(1) = system + tools + first_message; context(t) = context(t-1) + added_tokens_per_turn + output_tokens_per_turn; input billed per session = sum of context(t) over every call; without compaction = turns x context(1) + (added + output) x turns x (turns - 1) / 2; compaction: when context(t) would pass compact_at, one extra call reads it and writes a summary of (compact_to - system - tools) tokens; context(t) = compact_to; static cache: first call writes system + tools; later calls read them at hit rate, rewrite on a miss; rolling cache: first call writes the whole context; later calls read the previous call's context at hit rate and write the rest; input cost = (uncached + cache_read x read_mult + cache_write x write_mult) x usd_per_m_input / 1e6; output cost = output tokens x usd_per_m_output / 1e6; tool schema share = tool_schema_tokens x calls / input billed; cache_break_even_hit_rate = (write_mult - 1) / (write_mult - read_mult); per_month = per_day x 30
Assumptions
- cache_hit_rate:
- 0.9
- output_joins_context:
- each turn's output is appended to the next turn's context
- first_call_writes_cache:
- the first call of a session always writes the cache
- compaction_call:
- a summary call reads the whole context and is billed like a turn; in rolling mode it writes no cache
- tool_schema_what_if:
- halving tool schemas also lowers compact_at and compact_to by the tokens cut, so the summary length stays the same
- compaction_what_if:
- the half-peak what-if keeps 20% of the conversation beyond system and tools
- overflow_rule:
- a call overflows when its input plus its output passes context_limit
- days_per_month:
- 30
- prices:
- only the prices you sent; none are built in
Not checked
- · Exact token counts: they depend on the model's tokenizer.
- · Minimum cacheable prefix sizes, cache lifetimes and expiry between turns.
- · Long-context price tiers: one input price is used for every turn.
A planning estimate on your numbers. Not an approval, a quote or a recommendation.
Full response (JSON)
Use at your own risk. compute.md is provided as is, without warranty. Information here may be inaccurate, incomplete or not current, and is not verified; sizing figures are estimates. Not financial, legal or procurement advice. Confirm everything with your providers before you rent or buy. Terms
Result · example inputs
- Spot, expected
- 7.4 h
- $70.65
- Spot, 2× interruptions
- 8.4 h
- $80.51
- On-demand
- 6 h
- $144.00
- Checkpoint every
- 37.9 min
- 7.9% overhead
- Spot$70.65
- Spot, 2× interruptions$80.51
- On-demand$144.00
GET /api/v1/spot_plan?gpus=8&gpus_per_machine=8&job_hours=6&mtbi_hours=4&checkpoint_minutes=3&restart_minutes=10&synchronous=true&spot_usd_per_gpu_hour=1.2&on_demand_usd_per_gpu_hour=3&budget_usd=250&hard_stop_hours=12&model_params_b=13How it’s worked out: formula, assumptions, what isn’t checked
Formula
machines = ceil(gpus / gpus_per_machine) = ceil(8 / 8) = 1. Fleet MTBI M = mtbi_hours / machines = 4 / 1 = 4 h (any interruption stalls the job). Optimal interval (Young) tau = sqrt(2 x C x M), C = checkpoint hours. Daly: tau = sqrt(2 x C x M) - C. Checkpoint overhead = C / tau. Expected wall W = (T / tau) x M x e^(R/M) x (e^((tau + C)/M) - 1), R = restart hours (Daly's model for random interruptions). Past 10x the job hours the job is marked as not finishing. Expected interruptions = W / M. Expected lost hours = W - T x (1 + C/tau). Spot GPU-hours = gpus x W. Spot USD = GPU-hours x spot price. Pessimistic case: M / 2, same interval. On-demand wall = T (no checkpoints). Break-even MTBI: per-machine MTBI where spot W x spot price = on-demand wall x on-demand price (solved numerically). Worst case = gpus x hard_stop_hours x spot price. Largest stop in budget = budget / (gpus x spot price). Suggested stop = min(largest stop in budget, 1.5 x pessimistic W). Checkpoint size: weights = 2 bytes x params; full training state = 16 bytes x params (AdamW).
Assumptions
- interruptions:
- Interruptions arrive at random at a steady average rate (exponential).
- lost_work_per_interruption:
- The work since the last checkpoint plus the restart time. Interruptions can also land during checkpoint writes and restarts.
- restart_billed:
- Restart time is billed at the spot price.
- interval_used:
- optimal (Young)
- machines_rounding:
- Whole machines.
- synchronous:
- Any one machine's interruption stalls the whole job.
- checkpoint_bytes_per_param:
- {"weights":2,"full_state":16,"note":"Full state uses the upper end of 14-16 bytes per parameter for AdamW."}
- on_demand:
- On demand is assumed never interrupted.
- on_demand_checkpoints:
- None counted: on-demand wall time is the job hours, whatever checkpoint interval you send.
Not checked
- · capacity availability
- · data loading after restart
- · preemption notice handling
- · storage and egress
This is not an approval or a recommendation. It shows what is cheaper or faster on the numbers you sent.
Full response (JSON)
Use at your own risk. compute.md is provided as is, without warranty. Information here may be inaccurate, incomplete or not current, and is not verified; sizing figures are estimates. Not financial, legal or procurement advice. Confirm everything with your providers before you rent or buy. Terms
Result · example inputs
Leftovers are still billing. Remove them in the order given, then run this check again.
- Left running
- 2
- $50.40 a day
- Burn a month
- $1,533.00
- if left running
- Spent so far
- $21.00
- on the leftovers
- Unknown
- 2
- ask the person before touching
This call has list or object inputs: POST them as JSON to /api/v1/teardown_check.
How it’s worked out: formula, assumptions, what isn’t checked
Formula
status = kept if id or label is in keep; else leftover if it has run_tag or its id is in planned_ids; else unknown (all matches case-insensitive); verdict = leftovers if any leftover; else unknown_resources if any unknown; else clean; hourly = hourly_usd, or monthly_usd / 730; monthly = monthly_usd, or hourly_usd x 730; burn per hour = sum of leftover hourly; per day = x 24; per month = sum of leftover monthly; age_hours = (now - started_at) / 1 hour, or age_hours as sent; accrued = sum of age_hours x hourly over leftovers with both; likely companion = an unknown volume, snapshot, ip or load_balancer whose id or label contains a leftover compute item's id or label as a whole word, or one of whose tag values equals it
Assumptions
- hours_per_month:
- 730
- accrued:
- each leftover billed at one steady hourly price for its whole age; stopped time, free tiers and minimum charges are not modeled
- keep_wins:
- an item in keep is kept even when it carries the run tag
- unknown:
- unknown items may belong to someone else and are never put in the removal order
- prices:
- only the prices you sent; none are built in
- clock:
- now as sent; this tool never reads a clock
Not checked
- · Whether the list is complete: every account, project, region and zone the run used must be listed.
- · Charges that outlive a resource (transfer, requests, minimum storage durations, logs) and stopped resources that still bill for disks or addresses.
- · Whether the prices you sent are current, and whether they include tax, discounts or credits.
- · Resources the run created without its tag and outside planned_ids: they show as unknown.
A check on the list you sent. It deletes nothing and approves nothing: confirm with the provider's own list after removal.
Full response (JSON)
Use at your own risk. compute.md is provided as is, without warranty. Information here may be inaccurate, incomplete or not current, and is not verified; sizing figures are estimates. Not financial, legal or procurement advice. Confirm everything with your providers before you rent or buy. Terms
Result · example inputs
- Largest that fits
- Nemotron 3 Super 120B
- native (FP8), 2 GPUs
- Per stream
- 56 tok/s
- at your concurrency
- Answer time
- 9 s
- 10.1 GB spare per GPU
- Fastest that fits
- gpt-oss 20B
- 137 tok/s per stream
Models that fit (10), largest first
| Model | Precision | Per stream | Answer |
|---|---|---|---|
| Nemotron 3 Super 120Bnative (FP8) · 2 GPUs | native (FP8) · 2 GPUs | 56 tok/s | 9 s |
| Mistral Small 4 119Bnative (FP8) · 2 GPUs | native (FP8) · 2 GPUs | 83 tok/s | 6 s |
| gpt-oss 120Bnative (MXFP4 + BF16) · 1 GPU | native (MXFP4 + BF16) · 1 GPU | up to 91 tok/s | 5.5 s |
| Llama 3.3 70Bfp8 · 2 GPUs | fp8 · 2 GPUs | 31 tok/s | 16.2 s |
| Qwen3.6 35B-A3Bnative (BF16) · 1 GPU | native (BF16) · 1 GPU | 83 tok/s | 6.1 s |
| Gemma 4 31Bnative (BF16) · 2 GPUs | native (BF16) · 2 GPUs | 44 tok/s | 11.7 s |
| Qwen3.6 27Bnative (BF16) · 1 GPU | native (BF16) · 1 GPU | 33 tok/s | 15.4 s |
| gpt-oss 20Bnative (MXFP4 + BF16) · 1 GPU | native (MXFP4 + BF16) · 1 GPU | up to 137 tok/s | 3.7 s |
| Qwen3.5 9Bnative (BF16) · 1 GPU | native (BF16) · 1 GPU | 84 tok/s | 6 s |
| Llama 3.1 8Bnative (BF16) · 1 GPU | native (BF16) · 1 GPU | 63 tok/s | 8 s |
GET /api/v1/what_fits?gpu=h100-sxm&count=2&context=16384&concurrency=8&task=serve&kv=bf16&prompt_tokens=2000&output_tokens=500How it’s worked out: formula, assumptions, what isn’t checked
Formula
weights = parameters x bytes per parameter (native: checkpoint size; fp8 and int8: 1; int4: 0.5625); kv = KV bytes per token x context x concurrency (sliding-window layers capped at the window); per_gpu = (weights + state) / gpus + kv x copies / gpus, where MLA caches are copied on every tensor-parallel GPU; fits when per_gpu <= memory x 0.9 - 1 GB (serving), memory x 0.95 - 1.5 GB (training), or 75% of a Mac's memory; precision = the first of native, 8-bit, int4 that fits; fastest_precision = the one that fits with the lowest answer_s (else the highest per_stream_tok_s); decode step = max(bytes read / (bandwidth x 0.7), 2 x active x streams / (TFLOPS x 0.5)) + 1 ms + layers x 20 us (40 us MoE) + 30 us per layer when split; decode_tok_s = 1 / step(1); throughput_tok_s = concurrency / step(concurrency); per_stream_tok_s = throughput_tok_s / concurrency; ttft_s = max((2 x active x prompt + attention FLOPs) / (TFLOPS x 0.4), weights / bandwidth) + step overhead; answer_s = ttft_s + output_tokens / per_stream_tok_s; copies = floor(count / gpus_used); throughput_all_copies_tok_s = throughput_tok_s x copies
Assumptions
- gb:
- GiB (2^30 bytes), as GPU drivers report memory
- serve_usable_fraction:
- 0.9
- serve_reserve_gb_per_gpu:
- 1
- train_usable_fraction:
- 0.95
- train_reserve_gb_per_gpu:
- 1.5
- local_usable_fraction:
- 0.75
- bandwidth_efficiency:
- 0.7
- decode_compute_efficiency:
- 0.5
- prefill_efficiency:
- 0.4
- train_mfu:
- 0.35
- int4_bytes_per_param:
- 0.5625
- full_finetune_bytes_per_param:
- 16
- lora_adapter_share:
- 0.004
- qlora_slowdown:
- 1.3
- unknown_tflops_per_gbs:
- 0.15
- local_tflops_per_gbs:
- 0.035
- multi_gpu_scaling:
- fabric parts 0.9 within a machine, 0.7 across machines; bridged pairs 0.9 (2), 0.65 (4), 0.5 (8); PCIe-only parts 0.8 (2), 0.65 (4), 0.5 (8); bridged and PCIe parts one machine max
- kv_context:
- every sequence at the full context length (worst case)
- gradient_checkpointing:
- true
- decode_step_overhead_ms:
- 1
- decode_layer_overhead_us:
- 20
- decode_layer_overhead_us_moe:
- 40
- tensor_parallel_overhead_us_per_layer:
- 30
- upper_bound_step_ms:
- 5
- speed_basis:
- decode step = max(bytes read / bandwidth, FLOPs / compute) + fixed overhead + per-layer overhead; conservative constants, not measured on your stack
- pipeline_parallel:
- past one machine the model runs in pipeline stages, one after another: one stream gets one machine's bandwidth, and throughput gains from more stages only when concurrency fills them
- kv_tensor_parallel:
- MLA and other single-latent caches are copied on every tensor-parallel GPU; GQA caches are copied when a machine's GPUs outnumber the KV heads; data-parallel attention is not assumed
- prompt_tokens:
- time to first token uses prompt_tokens, or the full context when not given
- attention_flops:
- prefill attention: 2 x prompt^2 x width per full-attention layer (causal), about 4 x prompt x window x width per sliding layer, at the BF16 rate; linear-attention and Mamba layers add none
- training_sharding:
- FSDP or ZeRO-3 style: weights, gradients and optimizer states split evenly across GPUs; with plain data parallel each GPU holds the whole model
- kv_estimate:
- no usable config.json: 64 KB x sqrt(params in billions) per token, low confidence; pass the attention shape for an exact figure
Not checked
- · prices: compute.md has none; use your own quotes
- · models outside the quick picks (use fit_model with any Hugging Face id)
- · quality loss from quantization
- · whether your serving software supports each precision on this part
- · real speed on your stack: measure with a short test
An estimate on your numbers, not an approval or a recommendation. Confirm with a short test run before relying on it.
Full response (JSON)
Use at your own risk. compute.md is provided as is, without warranty. Information here may be inaccurate, incomplete or not current, and is not verified; sizing figures are estimates. Not financial, legal or procurement advice. Confirm everything with your providers before you rent or buy. Terms
Spend meter · runs on your machine
A hard cap on model spend
A prompt can ask your agent to stop. compute-meter can refuse the call. It’s a free, open-source script you run yourself: a small proxy on 127.0.0.1 between your agent and the model API, holding it to a budget you set.
- 1
Reserve
Before a call goes out, the meter prices its worst case with your own prices: the prompt, estimated from its size, plus the most output the call may return. A call with no output limit gets one added, so that worst case is a real ceiling. It sets that much aside.
- 2
Refuse or forward
If spent plus everything set aside plus this call would pass your cap, the call is refused with an error your agent can read. A call it can’t measure or price is refused too, never sent unmetered. Otherwise it goes on to the model API over HTTPS, streamed back as it arrives.
- 3
Settle
When the provider reports the call’s usage, the reservation becomes the real cost at your prices. If that report never arrives, the full reservation is charged, never zero. A call that cost more than it reserved is flagged in status.
Download the script into your project, write the templates, add your prices, start it with a cap. The cap is saved, so restarts keep it.
# In your project. One plain script, no dependencies: read it first. Needs Node 18+mkdir -p .compute && curl -fsSL https://www.compute.md/meter/compute-meter.mjs -o .compute/compute-meter.mjs && node .compute/compute-meter.mjs init# Put your own prices in .compute/prices.json (the template has no numbers), then set a cap.# start saves it in .compute/meter.json; on a meter that's already running it updates the cap.node .compute/compute-meter.mjs start --budget-usd 20# also: --period run (since the last reset) | day | month, --max-call-usd, --max-calls, --max-tokens-mnode .compute/compute-meter.mjs statusWith an API key. Background agents use the same settings file.
# Adds the base URL to .claude/settings.json and a SessionStart hook# that starts the meter with your saved caps (merged with what's there;# shows only the keys it adds or changes)node .compute/compute-meter.mjs install# What it writes{ "env": { "ANTHROPIC_BASE_URL": "http://127.0.0.1:8787/anthropic" }, "hooks": { "SessionStart": [{ "hooks": [{ "type": "command", "command": "node \"$CLAUDE_PROJECT_DIR/.compute/compute-meter.mjs\" ensure", "timeout": 15 }] }] }}# Check the wiringnode .compute/compute-meter.mjs doctorPoint the base URL at the meter. It has one route per API style, /anthropic and /openai/v1.
# The official SDKs read theseexport ANTHROPIC_BASE_URL=http://127.0.0.1:8787/anthropicexport OPENAI_BASE_URL=http://127.0.0.1:8787/openai/v1# Other tools: put the same URL in their custom endpoint settingWhat your agent gets back instead of an answer when a call’s worst case could pass the cap.
HTTP 400 x-should-retry: false{"type": "error", "error": {"type": "invalid_request_error", "message": "compute-meter: this call could cost up to <worst case> (its worst case), which would pass your <cap> cap; <spent> spent so far. … The cap is set by <flag or file>. Only the person can raise it …"}}# Abridged. Your agent stops and tells you, or sends a smaller call.# It must not edit the cap, reset the meter or unset the base URL.What it holds to
- The cap is enforced on reservations: they never add up past it, even with many calls in flight. Retries are counted as separate calls.
- It fails closed: a request it can’t read, size or price (a malformed or compressed body, no model, an odd path) is refused, not forwarded.
- Context the provider holds that the request doesn’t show (earlier responses, stored prompts, files or images by id or link) is reserved at a size you set, 200,000 tokens by default, or refused if you set that to 0.
- Your cap sticks: start saves it, so the Claude Code hook and any restart use the same cap, and running start again on a live meter updates it. With no cap set, calls are refused unless you choose count-only.
- Prices come only from your own file. A model you haven’t priced is refused, not guessed at, and two equally close price patterns are refused as ambiguous.
- The refusal is a plain error that SDKs don’t retry. It says what the call could cost at worst, the cap, what was spent and where the cap is set, and that only you raise it.
- It listens on 127.0.0.1 only, passes your keys through without writing them down, sends no telemetry and talks only to the model APIs you configure. One meter per ledger: a second one won’t start.
What it can’t do
- It sees only the calls sent through its address. Anyone on the machine, your agent included, can unset that address or stop the meter: it’s a guardrail you control, not a lock. Teams can force routing through it with Claude Code’s managed settings.
- Reservations are estimates. A call can still cost more than it reserved, for example when the provider adds more context than the size you set, so spend can end above the cap. That call is flagged and the next one is refused.
- Each call reserves its full output limit, so the last part of a small cap can go unused. A Claude Code call can reserve about 200,000 tokens: set caps well above one call’s worst case.
- It works with tools that call the model API directly and let you set a base URL: Claude Code with an API key, the official SDKs, and coding tools with a custom endpoint setting. Tools that send even your own key through their vendor’s servers can’t be metered.
- Not covered in v1: realtime and WebSocket APIs (refused), and charges it can’t see, such as code-execution container time. Message batches are charged in full when submitted.
- On a Claude Code subscription login it counts tokens and calls, not dollars, so use a token or call cap there. Remote Control and voice dictation are off while a custom base URL is set.
- “--period run” counts since the last reset, not since the meter started. A meter the hook starts keeps running after the session until you stop it.
- Its figures are estimates from your prices, not your invoice.
Provided as is, without warranty. You install it, you set the cap, and you can stop or remove it at any time. Keep your provider’s own spend limits and alerts too. Script: https://www.compute.md/meter/compute-meter.mjs. See the terms.
Before you rent
Will it fit, and on what?
The skill’s sizing rules, run on real model files. Weights come from the checkpoint’s size on disk; the KV cache from the model’s own attention layout, including sliding-window, linear-attention and latent caches that make naive math 10x wrong. Estimates only: confirm with a short test run.
The address bar keeps your inputs, so a result is a link you can share or bookmark. Your agent gets the same answer from /api/v1/fit or the fit_model MCP tool, for any Hugging Face model. Already have the hardware? Try what fits my GPUs.
Memory needed (estimate)
≈ 68.9 GB
- weights 51.7 GB
- KV cache 16.0 GB
- state 1.1 GB
- 1× H100 SXM80 GB each2.1 GB spare each≈ 30 tok/s per stream at 8 · 237 total · first token 5.0 s
- 1× A100 80GB80 GB each2.1 GB spare each≈ 19 tok/s per stream at 8 · 148 total · first token 16.0 s
- 1× H100 PCIe80 GB each2.1 GB spare each≈ 18 tok/s per stream at 8 · 145 total · first token 6.6 s
- 1× H100 NVL94 GB each14.7 GB spare each≈ 34 tok/s per stream at 8 · 272 total · first token 6.0 s
- 1× GH20096 GB each16.5 GB spare each≈ 35 tok/s per stream at 8 · 279 total · first token 5.0 s
Spare = 90% of each device’s memory (the rest is kept for the serving software), minus 1 GB for the runtime, minus what this needs. On a Mac, 75% of unified memory counts.
Fits on 1× H100 SXM, about 2.1 GB spare on each
Get prices for this from your own providers, then a budget and a stop time before anything launches.
GET /api/v1/fit?model=Qwen/Qwen3.6-27B&task=serve&context=32768&concurrency=8Estimates on your inputs, not measurements, and they may not be current. Speeds come from memory bandwidth plus fixed per-step costs; very short steps are marked as upper bounds. Confirm with a short test run before relying on them.
Agents already spend on compute. Most of them guess.
Coding agents now fine-tune models, stand up inference servers and fan out thousands of model calls on someone’s card. COMPUTE.md is a method in one file that an agent reads before it spends, with your stack and rules written in, plus the calculators above to do the math. Here is what changes.
Without a method, an agent…
With COMPUTE.md, it…
Without: Rents a GPU, then finds out at load time that the KV cache doesn’t fit, or that half the card sits idle.
With COMPUTE.md: Sizes it first: memory, GPU count and speed per stream for the model, context and concurrency you need.
fit_model · what_fits
Without: Picks self-hosting or an API by feel.
With COMPUTE.md: Prices both on your quotes, shows which costs less a day, and the volume where they cross.
serve_cost
Without: Fires 10,000 calls at once, hits the rate limit, and retries blindly.
With COMPUTE.md: Paces under your tightest limit: calls in flight, time to finish, cost with and without caching, and stop rules.
plan_fanout
Without: Doesn’t notice the whole context is re-sent, and billed, on every turn.
With COMPUTE.md: Counts what a session costs as the context grows, and what caching or compaction saves.
estimate_run
Without: Runs spot with no checkpoints, or pays on-demand by default.
With COMPUTE.md: Sets a checkpoint interval and compares expected and worst-case cost under a hard stop.
spot_plan
Without: Leaves machines running over the weekend.
With COMPUTE.md: Sets a hard stop inside your budget, checks the plan before launch, then lists what can still bill after teardown.
check_plan · teardown
Every price in these steps is one you or your agent read from your own providers. The tools return estimates and never approve anything; a person still says yes before money moves.
Customize
Your rules, written into the file.
Start with the money: the budget, the amount above which your agent must ask, and an hourly cap are already set below. Change them, pick a preset, or go through the rest of the 126 settings in 15 groups. Your stack says what to provision; your rules say what your agent may do. Both are written into COMPUTE.md.
Every setting is a number or a fixed choice, with no provider names and no prices, so the file works with any provider and a shared link can’t slip words into it. The same settings work as URL parameters, MCP prompt arguments, the build_limits tool and /api/v1/limits.
A cautious starting point for most work: ask before anything risky, encrypt everything, keep outputs.
Spend
What the agent may spend, and when it must ask.
Your rules:what your agent may do
Set by the person you work for, and only that person can change them. Rules an agent drafted count only after that person says yes. Where a rule here and the rest of this file differ, the rule wins, stricter or looser. Anything not listed follows the rest of this file. If a rule blocks the task, stop and ask; don't work around it.
The setup the person you work for wants. Provision it at their provider: meet every line or take the closest offering above it, ask before going below any of them, and say what you matched and what differs. A stack an agent drafted counts only after the person says yes. If the stack and Your rules disagree, follow the rules and ask.
mkdir -p ~/.claude/skills/compute && curl -fsSL "https://www.compute.md/compute.md?budget_usd=50&approval_usd=10&max_hourly_usd=25&model_budget_usd=5&alert_pct=80&commitments=never&marketplace=ask&stop_hours=4&idle_minutes=30&spot=checkpointed&checkpoint_minutes=30&long_running=ask&teardown=keep_outputs&backups=daily&fast_storage=ask&retention_days=30&databases=managed&cdn=allowed&exposure=ask&static_ip=ask&remote_access=tunnel&private_links=ask&dns=ask&images=official&patching=auto&serving=scale_to_zero&model_data=no_training&media=ask&monitoring=basic&alerts=on&encryption=provider&transit=tls12&secrets=manager&scanning=report&providers=existing&approver=user&credentials=existing&admin=ask&iam=ask&production=ask&approvals=shared®ions=any&personal_data=minimal&provisioning=cli" -o ~/.claude/skills/compute/SKILL.mdhttps://www.compute.md/compute.md?budget_usd=50&approval_usd=10&max_hourly_usd=25&model_budget_usd=5&alert_pct=80&commitments=never&marketplace=ask&stop_hours=4&idle_minutes=30&spot=checkpointed&checkpoint_minutes=30&long_running=ask&teardown=keep_outputs&backups=daily&fast_storage=ask&retention_days=30&databases=managed&cdn=allowed&exposure=ask&static_ip=ask&remote_access=tunnel&private_links=ask&dns=ask&images=official&patching=auto&serving=scale_to_zero&model_data=no_training&media=ask&monitoring=basic&alerts=on&encryption=provider&transit=tls12&secrets=manager&scanning=report&providers=existing&approver=user&credentials=existing&admin=ask&iam=ask&production=ask&approvals=shared®ions=any&personal_data=minimal&provisioning=cliCopy as JSON
The same settings as one JSON object. It feeds the check_plan tool or POST /api/v1/check.
44 of 126 settings set. Anything not set follows the skill’s own rules.
Use it in your stack
Paste it, install it, or call it.
The skill alone gives an agent a method to size, price and clean up. The MCP server and API add the calculators, sizing estimates, accelerator specs, your stack and rules, and plan checks. No key, no account.
Agents: one-pass setup at /setup.md
Paste the prompt into a system prompt, project instructions or custom instructions. Or keep the file in the repo and point AGENTS.md at it.
curl -fsSL https://www.compute.md/compute.md -o COMPUTE.mdecho "Before renting compute or spending on model calls, follow COMPUTE.md." >> AGENTS.mdInstall the skill so Claude loads it whenever compute comes up, and add the MCP server for the calculators, sizing and specs.
# The skillmkdir -p ~/.claude/skills/computecurl -fsSL https://www.compute.md/compute.md -o ~/.claude/skills/compute/SKILL.md# Tools: fit_model, gpu_specs, model_spec, build_limits, check_plan, serve_cost, compare_quotes, plan_fanout, estimate_run, spot_plan, teardown_check, what_fitsclaude mcp add --transport http compute https://www.compute.md/mcpA local Claude Code hook. A command that provisions compute needs a plan checked against your settings first. Blocked plans are refused and plans that need a yes ask you. A plan it doesn’t object to goes on to your normal permissions; the gate never approves anything. It runs on your machine, sends nothing, and stops only what it recognizes. If the gate itself can’t run, Claude Code blocks shell commands until you fix or remove it.
# In your project: download the gate (one plain script; read it first). Needs Node 18+mkdir -p .claude/hookscurl -fsSL https://www.compute.md/hook/compute-gate.mjs -o .claude/hooks/compute-gate.mjs# Save your settings (paste your link from "Copy link" above) and turn the hook onnode .claude/hooks/compute-gate.mjs init "https://www.compute.md/compute.md?budget_usd=50&approval_usd=10&stop_hours=4"# Try itnode .claude/hooks/compute-gate.mjs test "terraform apply"A local proxy that refuses model calls routed through it when their worst case, at your own prices, could pass the cap you set, and refuses calls it can’t meter. A guardrail you control, not a lock: it sees only calls sent to its address. Details, guarantees and limits are in “A hard cap on model spend” above.
# In your project: download the meter (one plain script; read it first). Needs Node 18+mkdir -p .compute && curl -fsSL https://www.compute.md/meter/compute-meter.mjs -o .compute/compute-meter.mjs && node .compute/compute-meter.mjs init# Add your prices to .compute/prices.json, then set a cap (saved, so restarts keep it; updates a running meter)node .compute/compute-meter.mjs start --budget-usd 20# Claude Code: route model calls through itnode .compute/compute-meter.mjs installAdd the remote MCP server to the project, then paste the prompt into your rules.
// Cursor: .cursor/mcp.json{ "mcpServers": { "compute": { "url": "https://www.compute.md/mcp" } } }// VS Code: .vscode/mcp.json{ "servers": { "compute": { "type": "http", "url": "https://www.compute.md/mcp" } } }Any client that speaks remote MCP over HTTP can add it as a custom connector. Read-only, so there is nothing to authorize.
url: https://www.compute.md/mcptransport: streamable-http # stateless, JSON responsestools: fit_model, gpu_specs, model_spec, build_limits, check_plan, serve_cost, compare_quotes, plan_fanout, estimate_run, spot_plan, teardown_check, what_fitsprompts: compute # the COMPUTE.md rules, with your limits setup # one-pass setup in your repoPlain GETs, CORS open. An OpenAPI document at /openapi.json loads into any OpenAPI tool loader.
# Will it fit? Memory, GPUs and estimated speed. Any Hugging Face model.curl -s "https://www.compute.md/api/v1/fit?model=Qwen/Qwen3.6-27B&context=32768&concurrency=8" | jq .summary# Fine-tuning: QLoRA over 50M tokens, with an estimated durationcurl -s "https://www.compute.md/api/v1/fit?model=meta-llama/Llama-3.3-70B-Instruct&task=qlora&train_tokens=50m" | jq .summary# Accelerators with at least 140 GB of memorycurl -s "https://www.compute.md/api/v1/gpus?min_memory_gb=140" | jq '.gpus[] | {name, memory_gb, bandwidth_gb_s}'# The skill with your limits written incurl -fsSL "https://www.compute.md/compute.md?budget_usd=100&approval_usd=25&stop_hours=6&spot=never" -o COMPUTE.mdclaude mcp add --transport http compute https://www.compute.md/mcpExample code
Size, plan, check, prove.
Working code against the API. The calculators are GET or POST at /api/v1/serve_cost /api/v1/compare_quotes /api/v1/plan_fanout /api/v1/estimate_run /api/v1/spot_plan /api/v1/teardown_check /api/v1/what_fits. The full reference is at /api/v1 and /openapi.json.
Size a deployment and print the options a person prices with their own providers and approves before anything launches.
// plan.mts: size a deployment with compute.md, then print the options your// user prices with their own providers and approves before anything launches.// npx tsx plan.mts Qwen/Qwen3.6-27Bconst model = process.argv[2] ?? "Qwen/Qwen3.6-27B";const url = new URL("https://www.compute.md/api/v1/fit");url.search = new URLSearchParams({ model, context: "32768", concurrency: "16", limit: "20" }).toString();const res = await fetch(url);const fit = await res.json();if (!res.ok) throw new Error(`${res.status}: ${fit.error} ${fit.hint ?? ""}`);console.log(fit.summary.join("\n"));for (const w of fit.warnings) console.warn(`! ${w}`);// Hardware that fits, smallest first. Prices are blank on purpose: fill them// in from the providers you use, with where and when you read each one.const rows = fit.options .filter((o: any) => o.fits && o.tier !== "local") .slice(0, 3) .map((o: any) => ({ hardware: `${o.count}x ${o.name}`, free_gb_each: o.headroomGB, tokens_per_s: o.throughputTokS, usd_per_hour: "", source_and_time: "", }));console.table(rows);console.log(fit.disclaimer);What /api/v1/fit returns, trimmed to the first options: a summary an agent can quote, the memory breakdown, and each option with estimated speed.
{ "model": { "id": "Qwen/Qwen3.6-27B", "name": "Qwen3.6 27B", "params_b": 27.78, "active_params_b": 27.78, "active_source": "dense", "moe": null, "native": "BF16", "native_gb": 51.7, "max_context": 262144, "attention": { "kind": "hybrid-linear", "fullBytesPerToken": 65536, "stateBytesPerSeq": 150994944, "confidence": "medium", "fullLayers": 16, "kvHeads": 4, "basis": "config" }, "source": "curated" }, "input": { "task": "serve", "precision": "native", "kv": "bf16", "context": 32768, "concurrency": 8, "trainTokens": null, "maxGpus": 8, "gpus": null, "limit": 3, "promptTokens": null, "outputTokens": null }, "memory": { "weightsGB": 51.7, "weightsLabel": "BF16 checkpoint", "kvCacheGB": 16, "stateGB": 1.13, "activationsGB": 0, "optimizerGB": 0, "totalGB": 68.9, "kvPerTokenKB": 64, "contextUsed": 32768, "kvPerTokenKBBeyondWindow": 64, "kvWindowTokens": null, "kvConfidence": "medium", "kvBasis": "config" }, "options": [ { "gpu": "h100-sxm", "name": "H100 SXM", "vendor": "NVIDIA", "tier": "datacenter", "memoryGB": 80, "count": 1, "fits": true, "usedPerGpuGB": 68.9, "headroomGB": 2.1, "decodeTokS": 37.1, "throughputTokS": 237, "ttftS": 5.05, "trainHours": null, "notes": [], "perStreamTokS": 29.6, "answerS": null, "stepMs": 26.95, "speedIsUpperBound": false, "ttftBasis": "tensor", "tensorParallel": 1, "pipelineStages": 1, "kvCopies": 1 }, { "gpu": "a100-80gb", "name": "A100 80GB", "vendor": "NVIDIA", "tier": "datacenter", "memoryGB": 80, "count": 1, "fits": true, "usedPerGpuGB": 68.9, "headroomGB": 2.1, "decodeTokS": 23.4, "throughputTokS": 148, "ttftS": 16, "trainHours": null, "notes": [], "perStreamTokS": 18.5, "answerS": null, "stepMs": 42.82, "speedIsUpperBound": false, "ttftBasis": "tensor", "tensorParallel": 1, "pipelineStages": 1, "kvCopies": 1 }, { "gpu": "h100-pcie", "name": "H100 PCIe", "vendor": "NVIDIA", "tier": "datacenter", "memoryGB": 80, "count": 1, "fits": true, "usedPerGpuGB": 68.9, "headroomGB": 2.1, "decodeTokS": 22.9, "throughputTokS": 145, "ttftS": 6.6, "trainHours": null, "notes": [], "perStreamTokS": 18.1, "answerS": null, "stepMs": 43.61, "speedIsUpperBound": false, "ttftBasis": "tensor", "tensorParallel": 1, "pipelineStages": 1, "kvCopies": 1 } ], "picks": { "smallest": "h100-sxm", "fastest": "b200", "local": "m4-max" }, "summary": [ "Needs about 68.9 GB: 51.7 GB weights (BF16 checkpoint), 16.0 GB KV cache for 8 x 32,768 tokens, 1.1 GB recurrent state.", "Smallest setup that fits: 1x H100 SXM (80 GB each, about 2.1 GB free each).", "On 1x H100 SXM: about 30 tokens/s per stream at 8 streams, first token in about 5.0 s.", "Fastest option: 1x B200, about 517 tokens/s across 8 streams (an upper bound).", "Runs locally on a Mac M4 Max (128 GB).", "Estimates only. Get prices from your own providers before choosing, and confirm with a short test run." ], "warnings": [], "disclaimer": "Use at your own risk. compute.md is provided as is, without warranty. Information here may be inaccurate, incomplete or not current, and is not verified; sizing figures are estimates. Not financial, legal or procurement advice. Confirm everything with your providers before you rent or buy.", "terms": "https://www.compute.md/terms"}Check a plan against your stack and rules before anything launches: totals, rule breaks and what needs a yes.
// check.mts: check a launch plan against your stack and rules with compute.md// before anything starts. Pass the hourly price you just read from your provider.// npx tsx check.mts <price per hour you read>const price = Number(process.argv[2]);const hourly_usd = price > 0 ? price : undefined;if (!hourly_usd) console.warn("No hourly price given: sending the plan anyway, and the checker will flag it.");// Your rules and your stack, by setting key. GET https://www.compute.md/api/v1/levers lists them all.const limits = { budget_usd: 50, approval_usd: 25, max_hourly_usd: 10, stop_hours: 8, spot: "checkpointed", max_gpus: 2, exposure: "private", egress_gb: 10, encryption: "provider", gpu_memory_gb: 80, memory_gb: 128, disk_type: "nvme", // your stack: the minimums to provision};// The plan, described without provider names: a spot GPU machine for a// fine-tune and a bucket for its checkpoints.const plan = { hours: 6, resources: [ { // 120 GB of RAM is below the 128 GB in your stack, so the checker asks for a yes. kind: "machine", name: "fine-tune", gpus: 1, gpu_memory_gb: 80, vcpus: 16, memory_gb: 120, disk_type: "nvme", hourly_usd, interruptible: true, checkpoint_minutes: 30, stop_after_hours: 8, idle_stop_minutes: 20, public_ip: "none", inbound: "none", encrypted: true, }, { kind: "storage", name: "checkpoints", storage_gb: 200, encrypted: true }, ],};const res = await fetch("https://www.compute.md/api/v1/check", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ limits, plan }),});const out = await res.json();if (!res.ok) throw new Error(`${res.status}: ${out.error} ${out.hint ?? ""}`);console.log(`${out.verdict}: ${out.summary}`);if (hourly_usd) console.log(`about $${out.totals.hourly_usd}/hour, $${out.totals.est_total_usd} in total, from your price`);for (const f of [...out.violations, ...out.approvals, ...out.warnings]) console.log(`- [${f.severity}] ${f.rule}: ${f.message}`);console.log("A clean check is not an approval. Show the plan to your user first.");if (out.disclaimer) console.log(out.disclaimer);The proof step: list everything that can still bill, for every kind of resource, after the job ends.
#!/usr/bin/env bash# Illustrative only: prove nothing billable is left after a task.# "cloud" is a placeholder. Swap it for your provider's CLI, with its own# list commands and filters, and run it in every account and region you used.TASK=finetune-1014 # the task tag you set at launchcloud() { echo " (placeholder) cloud $*"; } # remove once "cloud" is a real CLI# Everything tagged with this task, for each kind of resource that can keep billing.for kind in machines volumes snapshots images ips load-balancers gateways \ databases buckets file-shares endpoints cdn dns-records \ keys secrets roles; do echo "== $kind tagged task=$TASK" cloud "$kind" list --tag "task=$TASK"done# Leftovers people miss. They often carry no tag.echo "== untagged leftovers"cloud volumes list --detachedcloud ips list --unattachedcloud snapshots list --older-than 7decho "Anything listed above may still bill. Delete what this task created,"echo "list again, then report: what ran, where, hours, cost, where the outputs are."FAQ
Open any question for the answer.
Does compute.md rent or book compute?
Why are there no prices built in?
Are the calculators’ answers a quote or advice?
How accurate is the sizing?
Which models work?
params_b and the attention shape.Why would an agent follow this instead of guessing?
Can I change everything?
What can I set?
Does it name providers or prices?
Can my agent check a plan?
check_plan MCP tool or POST /api/v1/check. It gets back totals, rule breaks, where it falls short of your stack, and what needs a yes. A clean result isn’t approval; the person still says yes before money moves.Can it stop an agent from launching something?
.compute/plan.json checked against your settings. Blocked plans are refused and plans that need a yes ask you. A plan it doesn’t object to goes on to your normal permissions; the gate never approves anything. Its rules never stop teardown commands it recognizes.Is the gate a guarantee?
Can it hold my agent to a model budget?
compute-meter.mjs, is a local proxy you start with --budget-usd; it saves that cap, so its startup hook and restarts keep it. It reserves each call’s worst case at your own prices and refuses the call if that could pass the cap, refuses calls it can’t measure instead of sending them, then charges what the provider reports. The cap is enforced on those reservations, so a call that ends up costing more than it reserved can take spend past the cap; the next call is then refused. It only sees calls sent to its address, and anyone on the machine can unset that address, so it’s a guardrail you control, not a lock. It doesn’t cover tools that route calls through their vendor’s servers, realtime APIs, or charges it can’t see. Its figures are estimates from your prices, not your bill.Can an agent set up its own stack and rules?
build_limits tool and /api/v1/limits. The skill, the tool and the API all tell it that a drafted stack or rules count only after the person says yes, so it shows you the draft first. Nothing technical stops an agent from ignoring that, so read what it sends you.