GunSpec
Practice

Build an agent on GunSpec

Which tools to chain for a job, how to keep an answer honest when the catalog is silent, and what a conversation costs.

The server exposes 35 single-purpose tools and 5 workflow tools. A workflow is one call that does the work of several, which matters because each call is metered and each round trip is latency the user is watching.

tool-chain
javascript
// A product question, answered in three tool calls rather than// a dozen. Each call is metered, so the shape of the chain is the// cost of the feature. // 1. Words to a record. Never guess a slug, and never take the//    first search hit as the answer.gunspec_resolve_firearm({ query: "that 10mm Glock with the long slide" })// -> { status: "resolved", firearmId: "glock-g40-gen4", score: 0.93 } // 2. One workflow call instead of interfaces + attachments +//    offers + a lookup per part.gunspec_what_fits({ id: "glock-g40-gen4", category: "optic" }) // 3. The artwork, as URLs you hand to your renderer. The tool//    returns links and credits; it never returns file bytes.gunspec_firearm_media({ id: "glock-g40-gen4", kind: "silhouette" })

Each row is a complete job. Start at the left tool and stop when the question is answered.

What the user askedTools, in orderNotes
"Tell me about this gun"gunspec_resolve_firearm → gunspec_get_firearmResolve first, always. Act on the status rather than the top of a search ranking.
"Which is better, X or Y?"gunspec_compare_by_nameOne workflow call. It resolves both names and returns them aligned.
"What optic fits my rifle?"gunspec_what_fitsOne call for mounts, parts and offers. Beats four, and carries the confidence with each fit.
"What is this thing in the photo?"gunspec_identify_firearmDescription to candidates, ranked, with the reasons they matched.
"Show me pictures or a 3D model"gunspec_firearm_mediaReturns URLs and credits. It never returns file bytes, so hand the URL to your renderer.
"How does this cartridge perform?"gunspec_cartridge_profileCartridge, loads and ballistics in one answer instead of three lookups.
"Where can I buy it?"gunspec_firearm_offers or gunspec_attachment_offersSellers for a record, already filtered for freshness. Link through the counted redirect.
"How do I call this endpoint?"gunspec_search_docs → gunspec_read_docsRead the documentation rather than recalling parameters. Quote what comes back.

An agent on a specification database is trusted for exactly as long as it never invents a number. Four rules, each one about what not to say. Data quality is the evidence behind them.

grounding.ts
javascript
// The rules that decide whether your agent is trusted.// Every one of them is about what NOT to say. if (result.status === "ambiguous") {  // Ask. Generations differ in exactly the numbers people came for.  return askUser(result.alternatives)} if (firearm.barrelLengthMm == null) {  // A null is "not sourced". It is not zero, and it is not an  // invitation to recall a number from training data.  return "GunSpec does not hold a barrel length for this record."} if (firearm.dataConfidence < 0.6) {  // Say so, and cite what the record was compiled from.  return withCaveat(answer, firearm.sources)} // Cite the id you used. It is stable, so the reader can check it.return `${answer} (GunSpec: ${firearm.id})`

Two tools exist so an agent writing an integration does not work from memory: one searches these guides, the other returns a page or a single section as Markdown. Pair them with the packs on the AI page for agents that have no MCP connection.

  • gunspec_search_docs takes the question in the user’s own words and returns the sections that answer it, best first.
  • gunspec_read_docs returns one guide, or one anchor of it, which is usually what an answer needs. A whole page can run to tens of kilobytes.
  • gunspec_api_operation and gunspec_code_sample answer the narrower question: what this endpoint takes, and the sample the reference prints for it.
  • A question the documentation does not cover returns nothing. That means the answer is not written down, not that a near-enough one should be offered.

MCP calls have their own daily ceiling inside the plan: 20 on Explorer, 500 on Builder, and it is a sub-cap rather than extra allowance. An agent spends faster than a program because it retries, re-asks and explores, which is exactly why the ceiling exists. MCP limits has the table; staying inside the plan has the levers.

  • Prefer a workflow tool to a chain of four. It is one call against the cap and one round trip of latency.
  • Cache resolutions in your own session state. Resolving the same name three times in one conversation is three calls for one fact.
  • Set a per-conversation tool budget and degrade deliberately when it is spent, rather than failing on the last question.
  • A tool the plan does not cover returns an error naming the plan it needs. Surface that as an upgrade, never as a retry.

GunSpec answers what a firearm is, what fits it and who stocks it. It does not know your users, your inventory or your prices, so the interesting products are compositions.

  • Pair the catalog with your own inventory tool: GunSpec resolves and describes, your system answers stock and price. Keyed on the catalog id you stored.
  • Pair it with a retrieval tool over your own manuals or policies when the answer is part specification and part house rule.
  • For a product rather than a conversation, call the API directly from your server with the SDK. MCP is for agents; a page render does not need a model in the loop.
  • Selling as well as describing is the marketplace guide, including the counted links and the seller feed.