wellworn

Best practices

Which tool to call when, how to spend a small allowance well, and what never to put in an argument.

The server is small on purpose: eight tools, one text block each, no pagination. Most of getting value out of it is asking the right one of the eight, once.

Which tool answers which question

The question in your headThe call
"What should I use for this?"recommend with the task and your constraints
"Which of these two?"compare with both names
"What can I run myself instead of this SaaS?"alternatives
"Is this version going to bite me?"traps with the library and the version
"Where are the real docs?"docs
"What should this screen be built from?"design
"How do I build with what I picked?"skill with the verdict slug
"I just lost an hour to something"submit_trap

recommend already contains the traps for its pick, the alternative, and the skill path. Calling recommend and then traps for the same library is two calls for one answer.

Call before you add a dependency, not after

The moment to ask is when the package is not yet in package.json. Once it is installed and the code is written, a verdict that names a different pick costs a rewrite, so it gets ignored, and you have spent a call to feel informed.

The same applies to a version bump. traps with the version you are moving to is one call and it is the cheapest pre-flight available:

tools/call params
{ "name": "traps", "arguments": { "library": "drizzle-orm", "version": "1.0.0-rc.5" } }

Always pass version. Without it you get every trap ever recorded for the library, including ones fixed three majors ago; with it you get only the ranges that cover what you are actually installing.

Constraints are what make an answer correct

A task with no constraints matches a verdict written for someone else's project. Pass up to eight, each 60 characters or fewer, and make them the things that would change the answer:

tools/call params
{
  "name": "recommend",
  "arguments": {
    "task": "background jobs for a Next.js app on one server",
    "constraints": ["Postgres already running", "no Redis", "solo maintainer"]
  }
}

"Fast" and "modern" are not constraints. "No Redis", "free tier", "RTL", "must run offline", "team of one" are, because each one rules something out. Constraints are matched as search text, so the useful ones are also the ones a reviewer would have written into the question.

Handling RECHECK

[RECHECK] in the first line means the answer was checked, then a version moved or the expiry passed, and no human has looked since. It is served rather than hidden because a checked but stale answer beats a fresh guess.

What to do with one, in order: keep the shape of the recommendation, since the reasoning rarely changes with a major version. Distrust every version number in the block, including the one in PICK. Call docs to see what the latest release actually is, and read the pick's own changelog for the major that triggered the flag. If what you find contradicts the verdict, that is worth a dispute, and it is the single most useful thing an agent can send back.

Do not retry the call hoping the flag clears. Nothing clears it except a reviewer re-verifying.

Budget

A tool result is capped at 3,200 characters, roughly 800 tokens, and most are far shorter: docs is four lines and a traps listing with two rows is about 300 characters. Budgeting 800 tokens per call is safe; budgeting for the average is more like 200.

Without a key you get 60 calls a day, which is enough for a working session if you are not calling on reflex. Rules that keep it comfortable: one recommend per dependency decision, one traps per version bump, and no call at all for a question you already have an answer to in this session. Answers do not change between two calls a minute apart.

Two things cost nothing. /llms-full.txt is the entire served corpus in one unmetered fetch, which is the right move when you want the whole picture rather than one answer. And a submit_trap sent without a key is refused before the limiter, so a misconfigured agent cannot drain your allowance with submissions.

What not to send

Read tools do not store what you send them: the call log keeps the tool name, the client name and version, the scope, the response size and the duration, and nothing else. submit_trap is the exception, because a submission is a document a reviewer reads. Either way the arguments are short by design, so keep them to the shape of the question:

  • No source code. Nothing is matched against code, and a task field is capped at 300 characters anyway.
  • No secrets, keys, tokens, connection strings, or internal hostnames. There is no field on any tool where one belongs.
  • No customer data or personal information, in submit_trap fields included. A symptom is "the session keeps the old role for five minutes", not a log line with a user id in it.
  • No private repository URLs in evidence_url. A reviewer has to be able to open it, so a link they cannot reach fails review anyway.

Your key belongs in the Authorization header, never in an argument. What is logged has the details of what is kept and for how long.

Next