Free shared agent compute is the right default only after you list constraints you will not relax. I still watch teams grab a free endpoint first, then discover the loop can mail customers they cannot later audit. Price never explained that failure, because isolation, replay, and data ownership were never on the shopping list. So I invert the choice: name the non-negotiables, then pick the cheapest lane that still honors them.
Does that sound slower than opening a playground and pasting a prompt into the first vendor tab? It is slower, and I would rather spend twenty minutes on constraints than a week explaining an unreproducible tool call. Free remains useful, but it has to survive that inversion instead of skipping to the front of the line.
Price hides the tradeoffs you actually buy
A free model lane and a free server look identical to a paid API until the first bad tool call lands. Then you learn whether traces leave the box, whether another tenant can starve your queue, and whether Tuesday's payload still exists. Self-hosted runtimes flip those answers, but they also dump drivers, network policy, and patching onto your calendar without asking. Paid APIs sit in the awkward middle: clearer tenancy than a weekend shared box, less operational drag than a cluster you page.
I do not treat "free" as a personality trait of a product I happen to like this week. I treat it as a bundle of relaxed guarantees that somebody else already chose for me. If I cannot name those relaxed guarantees out loud, I am not choosing a lane; I am hoping the demo stays read-only. Have you ever shipped a read-only agent that grew a send-email tool before the README caught up with it?
Four constraints I score before any endpoint
I keep four questions beside the agent repo, and I refuse to discuss model names until they have answers. If any answer is a hard constraint, free shared compute has to earn a seat instead of inheriting one. Quality comparisons come later, because a brilliant completion that I cannot replay is only an anecdote with extra tokens.
- Trace custody. Can I export every prompt, tool call, and tool result into storage I control?
- Side-effect radius. Can this loop mutate tickets, mail, money, or production files without a human gate?
- Replay fidelity. Can I rerun last Tuesday's transcript against a new prompt and get a comparable trace?
- Queue isolation. Can a noisy neighbor delay a job that a human is already waiting on?
Notice that none of those questions is which model looks smartest in a social feed this week. Smartness is an experiment you can rerun after the lane is honest enough to hold evidence. Constraints decide whether that experiment is even allowed to run on shared hardware you do not operate.
Invert the constraints, then pick a lane
Here is the sitting-length workflow I actually walk when a new agent shows up in a review. It fits in one pass, and it produces a file you can argue about instead of a slide. If the file and the tool list disagree, I trust the tool list and I update the file immediately.
- Write the agent's tools as an allow-list, and mark each tool
readorwrite. - Record each constraint above as
hard,soft, oroffin YAML next to the code. - Reject any lane that violates a
hardconstraint, including a lane that happens to be free. - Among the lanes that survive, pick the smallest operations surface you can staff this week.
- Re-score the file after the first mutating tool ships, because the matrix goes stale that afternoon.
Would I skip step three because a demo is due on Friday and the slide already says shipped? I have wanted to, and that is usually when the wrong email leaves the building under a demo account. The inversion is a brake pedal, not a vibe, and the allow-list below is what I brake against.
{
"tools": [
{"name": "search_docs", "mode": "read"},
{"name": "list_tickets", "mode": "read"},
{"name": "send_email", "mode": "write"}
]
}
If send_email exists and nobody is in the loop, free shared compute is already on probation. Read tools can stay cheap; write tools have to buy isolation or a human gate, sometimes both. That distinction matters more than the sticker on the inference endpoint you pasted into dotenv.
Decision matrix: free shared, paid API, self-hosted
I use the matrix as a conversation starter with whoever owns the tools, not as a score that pretends to be science. Read down the first column until you hit a constraint you will not relax for this agent. Then read right, and stop treating every free box as interchangeable with a runtime you actually isolate.
| Hard constraint you cannot relax | Free shared model or server | Paid isolated API | Self-hosted runtime |
|---|---|---|---|
| Trace custody | Only if you copy logs into storage you own | Fit when export and retention are explicit | Fit if you already run the archive |
| Unattended mutating tools | Poor fit | Conditional on identity, audit, and rollback | Conditional on IAM you actually maintain |
| Replay for eval gates | Weak unless transcripts live in your repo | Fit if request ids stay stable | Fit if you pin the runtime image |
| Human waiting on the result | Risky on contended shared capacity | Better with reserved throughput | Best with dedicated workers |
| No hard constraints, read-only tools | Strong fit for exploration | Often overkill while the loop is still changing | Overkill until the workflow stops thrashing |
This table is a fit guide, not a benchmark, and it will not rank vendors by tokens or latency. I am not publishing tokens per dollar, percentile charts, or a bake-off I did not run on your traffic. If a vendor card disagrees with a hard constraint in the YAML, the constraint wins and the card waits.
A mapper you can run locally
The script below is a proposal I keep as a checklist, not a production control plane with SLAs. It reads YAML, prints a lane, and exits non-zero when free shared compute fails the inversion outright. Install PyYAML, then run it from the agent repository root before anyone argues about endpoints again. Label it as unexecuted in your own environment until you have run it against your real tool list.
# agent_constraints.yaml
constraints:
trace_custody: off # hard | soft | off
mutating_tools: off
replay_fidelity: soft
queue_isolation: off
human_gated_writes: true
#!/usr/bin/env python3
"""Constraint-inversion mapper for agent compute lanes.
Proposal / checklist script. It does not probe live vendors or capacity.
"""
from __future__ import annotations
import argparse
from dataclasses import dataclass
from typing import Literal
try:
import yaml
except ImportError as exc:
raise SystemExit("pip install pyyaml") from exc
Lane = Literal["free_shared", "paid_api", "self_hosted"]
@dataclass
class Constraints:
trace_custody: str
mutating_tools: str
replay_fidelity: str
queue_isolation: str
human_gated_writes: bool
HARD = "hard"
def load(path: str) -> Constraints:
with open(path, encoding="utf-8") as handle:
raw = yaml.safe_load(handle) or {}
block = raw.get("constraints", raw)
return Constraints(
trace_custody=str(block.get("trace_custody", "off")),
mutating_tools=str(block.get("mutating_tools", "off")),
replay_fidelity=str(block.get("replay_fidelity", "off")),
queue_isolation=str(block.get("queue_isolation", "off")),
human_gated_writes=bool(block.get("human_gated_writes", False)),
)
def invert(c: Constraints) -> tuple[Lane, str]:
hard_mutation = c.mutating_tools == HARD and not c.human_gated_writes
if hard_mutation and c.trace_custody == HARD and c.queue_isolation == HARD:
return (
"self_hosted",
"Unattended writes plus custody plus isolation need a runtime you operate.",
)
if hard_mutation:
return (
"paid_api",
"Unattended writes need a lane with identity, audit, and a real boundary.",
)
if c.trace_custody == HARD or c.replay_fidelity == HARD:
return (
"paid_api",
"You must own or export traces; a contended free box is a weak archive.",
)
if c.queue_isolation == HARD:
return (
"paid_api",
"A human is waiting; do not share a queue you cannot protect.",
)
return (
"free_shared",
"Read-only or gated work with no hard isolation demand can stay on free shared compute.",
)
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--config", default="agent_constraints.yaml")
args = parser.parse_args()
lane, reason = invert(load(args.config))
print(f"lane={lane}")
print(f"reason={reason}")
raise SystemExit(0 if lane == "free_shared" else 2)
if __name__ == "__main__":
main()
pip install pyyaml
python constraint_invert.py --config agent_constraints.yaml
echo "exit=$?"
Flip mutating_tools to hard and set human_gated_writes to false, then run the same command again. You should leave free_shared immediately, which is the entire lesson encoded as a boring exit code. I want that refusal in CI before anyone pastes a new base URL into an environment file.
# Proposal only: gate endpoint changes on the inversion, not on enthusiasm.
python constraint_invert.py --config agent_constraints.yaml
# exit 0 -> free_shared is still an honest fit
# exit 2 -> choose paid_api or self_hosted before swapping endpoints
Where a free model lane still wins
When every tool is read-only, traces can live in my repository, and nobody is blocked on the queue, cheap compute is the honest answer. Many so-called agents are still deterministic workflows with a language model sitting at the leaves of a boring graph. Those leaves do not need a private cluster on day one, and pretending they do just delays learning.
MonkeyCode is one option in that exploration bucket, and I am not going to dress it up as a compliance boundary. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The project is open source, and it offers free model access plus a free server option I treat as a shared matrix lane. I still keep the constraint file in git, because the lane should be swappable the hour a write tool appears.
I do not need that lane to win a quality contest I never ran against a private cluster. I need it to survive the four questions without pretending isolation that the lane does not actually provide. If you are mapping a read-only agent this week, drop a free shared lane into the matrix and check your hard constraints.
Limitations, and who should not use this
This inversion will not satisfy a regulator, a SOC questionnaire, or a lawyer who needs a paper trail. It also will not detect silent prompt injection, poisoned tools, or a model that confidently lies about tool results. The script never probes live capacity, never estimates cost, and never pins a model name that would rot in a week. Those claims go stale faster than a README, so I refuse to print them as if they were facts.
Skip the free shared recommendation if your prompts contain customer PII, or if writes travel without a human gate. Skip self-hosted if nobody on the team can patch the box this quarter without opening a mystery incident. Skip paid APIs if you cannot explain data retention to the rest of the company in one paragraph. Skip this whole checklist if you do not have tools at all; a side-effect-free chatbot can stay in a playground.
Constraints first, then the cheapest honest lane, is the entire decision I want in the repository. Everything else is shopping, and shopping is how unattended mail tools land on shared queues by accident. Invert the file, then pick the endpoint, and do not reverse those two steps because a homepage said free.
Top comments (0)