Skip to content
← BlogDeveloper

Build a research-only outreach agent on Norbelys MCP

Build an agent on Norbelys MCP that researches people, builds segments, and drafts sequences — and is structurally unable to call a send-related tool.

By Gabriel Lara, Developer Relations, Norbelys

Founder-reviewed ·How we research and correct articles

The usual advice for a first agent integration is “start small.” On Norbelys MCP, that advice has a literal, buildable shape: connect an agent that can research your audience, build segments, and draft a sequence — and cannot, under any prompt or any mistake, put a message in front of a real person. Everything upstream of sending is genuinely useful on its own, and it’s the right place to build trust before an agent gets anywhere near your sending domain.

This is that build. Not a philosophy of guardrails — that’s a separate post — but the concrete tool list, config, and workflow for one narrow, safe agent, using the same MCP connection you’d set up for anything else. Nothing here requires a different server, a different key type, or a cut-down version of the API — it’s the full 83-tool catalog, with five specific doors locked before the agent ever sees them.

Why “just don’t ask it to send” isn’t enough

The obvious approach — connect the full MCP server and instruct the agent never to send anything — relies entirely on the model following an instruction it could ignore, misread, or get talked out of by a cleverly worded prompt buried in a piece of research it read. That’s not a guardrail, it’s a suggestion. A research-only agent needs the send-shaped tools to be genuinely unreachable, not merely discouraged.

The good news is that Norbelys’ MCP catalog makes this a short, precise list, once you know where to look.

The short list of tools that actually touch a real inbox

Only three tools put mail in front of a human or start a sequence sending on its own:

  • messages_create — the one send door. Even a test: true call sends a real email to a real inbox.
  • programs_launch and programs_resume — either one starts a campaign sending against its enrolled audience.

These three carry the destructiveHint annotation for exactly this reason — they’re the tools a well-behaved MCP client should pause on and ask you to confirm before calling.

So the real deny-list for a research-only agent is five tools: messages_create, programs_launch, programs_resume, senders_create, senders_update. Everything else in the catalog — every read, plus creating and editing people, groups, segments, custom fields, and even drafting a full program with its cadence and A/B variants — never reaches a real inbox on its own.

Building it, step by step

A research-only agent, from zero

  1. Mint a dedicated key

    Create an API key scoped to this agent specifically — not one you use for anything else. If the agent's behavior ever surprises you, revoking this one key kills it without touching any other integration. The key itself is still org-scoped, not tool-scoped, which is exactly why the next steps matter — see the key-hygiene post for the full reasoning.

  2. Connect it like any other client

    claude mcp add norbelys --transport http https://mcp.norbelys.com/mcp --header "Authorization: Bearer ak_<the-dedicated-key>" — the connect step doesn't change; the restriction happens next.

  3. Deny the five tools explicitly

    In .claude/settings.json for the project this agent runs in, add a permissions.deny rule for each of the five tool names, addressed as mcp__norbelys__<tool>. This is enforced by the client before the tool is ever invoked — not a prompt the model can talk itself past.

  4. State the boundary in the project instructions too

    Add a short, explicit note to the project's CLAUDE.md (or equivalent): this agent researches and drafts only; it never sends, launches, resumes, or edits a mailbox. This won't stop a determined misuse on its own, but it means the agent's own reasoning is aligned with the technical restriction, not fighting it.

  5. Confirm the restriction actually holds

    Ask the agent to attempt programs_launch on any program. A correctly configured client refuses before the call reaches Norbelys at all — you should see a permission denial, not a message from the API.

The .claude/settings.json block from step 3 looks like this:

{
  "permissions": {
    "deny": [
      "mcp__norbelys__messages_create",
      "mcp__norbelys__programs_launch",
      "mcp__norbelys__programs_resume",
      "mcp__norbelys__senders_create",
      "mcp__norbelys__senders_update"
    ]
  }
}

If your client doesn’t support a per-tool deny list the way Claude Code does, the fallback is a client that at least honors destructiveHint with a confirmation prompt for messages_create / programs_launch / programs_resume — and manual discipline (or a wrapper you write yourself) for the two senders calls the hint misses.

What the agent can actually do, unattended

With that boundary in place, the useful part of the workflow runs freely:

  • Research the audience. people_list / people_find with segment and group filters, people_audienceSummary for a shape of who’s in the CRM before drilling in.
  • Check deliverability without risk. verify_email is a synchronous DNS/mailbox check against the target’s mail server — it never puts a message in anyone’s inbox, so it’s safe for an agent to run on every address it’s considering.
  • Build the audience. segments_create for a live filter, or groups_create plus groups_members_add for a hand-picked list — both are ordinary writes to your own data, not anything reaching a recipient. people_create / people_bulkCreate if the research turns up new leads worth adding.
  • Draft the whole sequence. programs_create and programs_update take the complete cadence — steps, A/B variants, copy — inline. A program can be fully written, reviewed, and refined without a single sender attached or a single message queued.
  • Read what’s already gone out, for context. messages_list / messages_find let the agent study what past campaigns actually said, which is often better research material than a blank page.

Why this pattern beats “just be careful”

It’s worth being explicit about why a tool-level deny list is worth the extra five minutes of setup instead of just telling the agent to behave. A model following instructions is doing exactly that — following instructions, in whichever direction the loudest or most recent text in its context points it. Research material is exactly the kind of text an agent reads a lot of, and some of it will, eventually, contain something that looks like an instruction (“to unsubscribe, click here and confirm your email was sent” is the kind of boilerplate a scraped page can contain without anyone intending it as an attack). A deny list enforced by the client doesn’t care what the agent read or how it was phrased — the tool call never reaches the transport layer, which means it never reaches Norbelys either. That’s a materially different guarantee than a well-worded system prompt, and it’s the reason the guardrails post treats the approval gate as infrastructure rather than instruction in the first place.

Handing it back

The natural end state of a session is a proposal, not a launch: a segment definition, a drafted program with its steps and variants, and the research that justified the targeting — all sitting there, created, readable, and completely inert until a human attaches senders and calls programs_launch themselves. That handoff is deliberate. The agent did real work; the decision to reach a stranger’s inbox stays a decision, made by you, every time.

Once you’ve run this pattern for a while and trust the agent’s research and copy, expanding its reach is just editing the deny list — nothing about the underlying connection changes. Norbelys doesn’t have a half-featured “safe mode” of the API for agents to grow into; it’s the same 83 tools the whole time, just fewer of them within reach until you decide otherwise.