Three Tools for 1,100 Endpoints: How We Opened MarketBetter to AI Agents
Sometime this year, the "user" on the other end of your product stopped being reliably human. We've written about AI agents replacing search traffic and about vendors coining "business-to-agent" as a category. This post is the practical sequel: what we actually shipped so that an AI agent can operate MarketBetter โ not read about it, operate it.
The short version: our entire API surface โ over 1,100 operations at the time of writing โ is now reachable by agents through exactly three generic tools, on two rails. One rail is a remote MCP connector. The other is a bring-your-own-key skill for an agent tool catalog. Neither rail ships a single hand-written per-feature tool.
The trap: one tool per featureโ
The obvious way to connect an assistant to your product is to hand-write a tool for each thing it can do: create_campaign, list_audiences, get_analytics, and so on. Every sales-tech vendor that launched an MCP server this year started here, and you can watch the pattern strain in public. Salesloft and Clari's MCP server launched read-only with a curated tool list that couldn't even retrieve cadences. Outreach's MCP suite grew write actions a month after launch, as a separate release.
The curated-tool approach has two structural problems:
- Context bloat. Seventy tool definitions land in the agent's context window on every conversation, whether or not the task needs them. Agents get slower and dumber as the tool list grows.
- A release train you didn't want. Every new backend endpoint needs a matching connector release before any agent can touch it. Your integration is permanently a sprint behind your product.
We ship product weekly. A connector that lags the API by a release cycle would be stale on arrival.
The thin waist: discover, inspect, callโ
So instead of seventy tools, agents get three moves:
| Move | What it does | Access |
|---|---|---|
| Discover | Search the live API catalog by keyword โ campaigns, audiences, signals, analytics, dialer, anything | Read-only |
| Inspect | Pull one operation's exact parameters, request-body schema, and response shape | Read-only |
| Call | Execute the operation โ GET by default; writes only when the agent explicitly asks for them | Authenticated, role-scoped |
The source of truth behind all three is our live OpenAPI document, published at a public URL with no API key required. It describes every published path, method, parameter, and schema, and it is generated from the running API โ so the day an endpoint ships, every connected agent can discover it, inspect it, and call it. No connector update. No marketplace re-review. No sprint lag.

This is the same thin-waist bet we admired when Attio rebuilt its CRM around a SQL engine agents can query directly, and the same three-door logic we mapped in Apollo's headless GTM stack: give agents a small, stable interface to a large, moving surface, and let the surface move.
There's a trade, and we'll be honest about it: generic tools make the agent do more reasoning per task than a purpose-built create_campaign tool would. Discovery is a search step a curated tool list wouldn't need. We think the trade is right โ a three-tool interface that's never stale beats a seventy-tool interface that's always partial โ but it is a trade, not a free lunch. And no, we haven't benchmarked token cost versus a curated connector. When Apollo claimed its CLI used "25% fewer tokens than MCP" we flagged the missing methodology; the same standard applies to us.
We now write API docs for a reader that hallucinatesโ
Here's the part nobody warned us about: once your API's primary new reader is an agent, your documentation changes genre.
Our OpenAPI document's description now opens with a section literally titled "STOP โ Read These Before Creating Any Play Node." It exists because agents make a category of mistake humans rarely make: they invent plausible fields. A human developer who doesn't know the mailbox format goes and looks it up. An agent confidently writes "mailboxes": [1344] when the API wants "mailboxes": [{"id": 1344}], or invents a field_mappings parameter on a CRM action because CRM actions in general often have one.
So the docs now defend against specific hallucinations, by name:
- the exact JSON shape for mailbox arrays, with the wrong shape shown and labeled NEVER
- a warning that the LinkedIn enrichment flag is
enrich_people, plural โ because the singular form "does not exist" (an agent will try it anyway) - instructions to always request
minimal=trueon large list endpoints, because a full response that's 93% larger than necessary doesn't just waste bandwidth โ it floods the agent's context window
Every one of those warnings is a scar: a real failure mode we watched an agent hit, promoted into the document the next agent reads before it can repeat the mistake. If you maintain an API and you're expecting agent traffic, this is the cheapest reliability work available: your error logs are already a list of what the docs should say.
Rail one: the MCP connectorโ
For assistants like Claude and ChatGPT, the three moves are exposed as a remote MCP server at mcp.marketbetter.ai/mcp. Authentication is OAuth 2.1 with PKCE โ you sign in with your MarketBetter account and approve the connection. No API key ever appears in a connector URL or a config file.
The safety model matters more than the tool count:
- Reads can't silently become writes. The call tool defaults to GET; a write requires the agent to explicitly set a write method, and the tool carries a write/destructive annotation so the client treats every call with appropriate caution.
- Only published operations execute. The method and path must exist in the discovery catalog; undisclosed routes are rejected.
- Your role is the ceiling. Every request runs as the connected user, and the API enforces the same role-level access control the dashboard does. An agent connected by an SDR can do what that SDR can do โ nothing more.
That last point is the quiet one worth stealing: we didn't build a separate permission system for agents. The agent inherits the human's. Given what happened when vendors tried to gate agent access behind separate quote-only packages, we think identity inheritance is the pattern that survives.
Rail two: tool catalogs, bring your own keyโ
MCP connectors assume a person sitting in a chat app. But a growing share of agent traffic comes from headless agents โ scripts, crons, and autonomous workflows that shop for capabilities in tool catalogs the way developers once shopped for npm packages. Catalogs like treg (which pitches itself as "OpenRouter for agent tools") give an agent one token and a few thousand callable endpoints, with per-call pricing and measured reliability instead of vendor marketing.
We've packaged MarketBetter for that world too, and the shape of the package is the interesting part:
- A recipe โ a SKILL.md file that tells any agent the three moves: fetch the public OpenAPI document to discover operations, read the relevant schema block, call the operation. The recipe is a page long. It doesn't enumerate endpoints, because it doesn't have to โ discovery is live.
- A contract โ a small JSON file declaring the base URL, the health check (the public OpenAPI URL itself), and exactly one secret binding: the user's own MarketBetter API key, injected server-side by the catalog as a bearer token.
Bring-your-own-key is the part we'd underline. The user's key lives in the catalog's vault and is injected at the gateway; it never appears in the agent's context, its logs, or its chat transcript โ which matters, because agent context is the leakiest surface in modern software. And because each user brings their own key, there's no reseller relationship, no pooled billing, no mystery middleman account. Your agent, your workspace, your key.
One honest status note: as of publication, the skill package and its publish pipeline are built, but you won't yet find MarketBetter in treg's public hub search โ the public listing is a separate step that hasn't flipped. We're writing the pattern up anyway, because the contract shape (live-OpenAPI recipe + single secret binding + health check) is reusable by anyone today, including against our API directly.
What an agent can actually do with thisโ
Everything the dashboard can. That's the point of the thin waist โ the agent isn't limited to a curated subset. Concretely, the loop we care about:
- Find the audience. Search operations for audience and signal endpoints, query intent signals for accounts showing buying behavior.
- Build the motion. Create or update an audience, attach plays โ email sequences, LinkedIn steps, voicemail drops โ using the exact schemas from inspection.
- Act on the moments. Wire the follow-ups humans forget: nurture loops that learn from silence, chat sessions that recognize form-fillers, landing pages generated per target account.
- Read the results. Pull campaign analytics and feed them back into the next iteration.
A nightly cron with a scoped key can now run that loop headlessly โ with writes gated, roles enforced, and every operation it's allowed to touch defined by the same document a human developer reads.
If you're exposing your own product to agentsโ
The checklist we'd hand a peer, compressed from this build:
- Publish a machine-readable surface with no login wall. Our OpenAPI document is public and keyless by design โ discovery can't require the credential the agent is trying to figure out how to use.
- Prefer few generic tools over many specific ones. Discover/inspect/call scales with your API; a curated list scales with your release calendar.
- Write docs against hallucinations, not just ignorance. Name the wrong field shapes explicitly. Your 400-error logs are the outline.
- Default to read; annotate writes. The agent should have to mean it.
- Inherit human permissions. Don't invent a parallel agent-permission system you'll regret.
- Meet headless agents where they shop. BYOK catalog listings cost you a recipe and a contract file โ a weekend, not a quarter.
The distribution shift underneath all this hasn't slowed: agents research vendors, agents compare pricing, and increasingly agents operate the tools they recommended. We'd rather be the platform an agent can drive end-to-end than the one it can only summarize.
If you want to see what an agent-operable outbound platform looks like with a human at the wheel, book a demo โ and if you try the three-move pattern against our API from your own agent stack, we genuinely want to hear what breaks.
