TL;DR
- A Claude Code sales agent is four files: a
CLAUDE.mdwith rules, a subagent with a short tool list, a slash command, and one MCP connection for data. - It takes about 30 minutes. A run spends about 13 of your 1,000 free LeadOcean records: 10 search rows and 3 enrichments.
- The agent sizes the audience for free, pulls a small sample, and drafts first lines for you to review. It never sends anything.
Prerequisites
- A LeadOcean account from app.leadocean.io. The free plan has no card and 1,000 records, one-off.
- Claude Code installed, and a project folder to hold the agent files.
curlandjqfor the check in step 5. The REST calls read your key from$LEADOCEAN_API_KEY. The MCP route needs no key.
mkdir sales-agent && cd sales-agent
export LEADOCEAN_API_KEY="paste-your-key-here"Step 1: Connect the LeadOcean MCP server
The agent gets its data from one hosted MCP server. Add it as an HTTP server, then sign in with OAuth. The Claude Code MCP docs, September 2026, say to run /mcp in a session to authenticate a remote server.
claude mcp add --transport http leadocean https://api.leadocean.io/mcp
claude mcp list/mcpPick leadocean and approve the sign-in. The server exposes 13 tools. Seven of them never spend records: count leads, count companies, filter list, enum list, account, get export and list exports.
Step 2: Write the rules in CLAUDE.md
Put the rules the agent must never break in a project CLAUDE.md. Claude Code loads it every session, and subagents load it too, September 2026. Keep it short and specific.
SALES AGENT RULES
- You are a prospecting assistant for one seller. You draft. A human sends.
- Never send, schedule or post anything. You have no email tool, and you do not ask for one.
- Count before you pull. Call leadocean_count_leads first and report the total and the filters.
- Records are money. Stop at 25 records per run. Say how many you spent at the end.
- Resolve every enum with leadocean_list_enum_values. Never guess an industry or a job level.
- Use only fields that came back in the row. Never invent a company fact, a funding event or a quote.
- Say what the count measures. The default count is mailable people, not everyone matching.The last two rules matter most. The count tool counts only addresses worth sending to unless you widen it. An agent that reports that total as "everyone" is wrong.
Why write the rules down at all? A model that is asked to "find me leads" will pull until it has enough. The 25-record cap and the count-first rule turn that into a bounded run. On the free plan the 1,000 records are one-off, so a loose agent can spend them in one afternoon.
Step 3: Define the prospector subagent
A subagent is a Markdown file with YAML frontmatter in .claude/agents/. Only name and description are required. The tools field is an allow-list, so this is where you take away what the agent should not have.
---
name: prospector
description: Finds and ranks prospects from the LeadOcean MCP server. Use for any request to size an audience, pull sample rows or draft first lines.
tools: mcp__leadocean__leadocean_count_leads, mcp__leadocean__leadocean_list_enum_values, mcp__leadocean__leadocean_search_leads, mcp__leadocean__leadocean_get_lead, Write
model: sonnet
---
You turn an ICP into a short, reviewable list of prospects.
1. Resolve each filter value with leadocean_list_enum_values.
2. Run leadocean_count_leads. Report the total, the filters, and that it counts mailable people.
3. If the total is under 25 or over 100,000, stop and ask for a narrower ICP.
4. Run leadocean_search_leads with limit 10. Rank by title fit.
5. Run leadocean_get_lead on the top 3, by person_id.
6. For each of the 10, write one line: name, title, company, and a first sentence that uses only fields in the row.
7. End with the records spent.The tool names follow the mcp__<server>__<tool> pattern from the Claude Code docs. Here leadocean is the server name you gave in step 1. There is no leadocean_export_leads in the list, so this agent cannot start a bulk export.
Step 4: Add the /prospect command
Skills and .claude/commands/ files both create slash commands. A skill at .claude/skills/prospect/SKILL.md gives you /prospect. The $ARGUMENTS placeholder is replaced with whatever you type after the command.
---
name: prospect
description: Build a short prospect brief for an ICP. Use when the user types /prospect followed by an audience.
---
Use the prospector subagent for this ICP: $ARGUMENTS
Ask it for the count, the 10 ranked rows and the first lines. Save its answer to
briefs/brief-<today's date>.md. Show me the count, the table and the records spent.
Do not draft anything beyond one first line per person.Start Claude Code in the folder and run it. Describe the ICP as filters, not as a story. A vague ICP gives the agent room to guess an enum value, and the rules in step 2 tell it to look the value up instead.
Expect this order of tool calls: leadocean_list_enum_values for the industry and job function, then leadocean_count_leads, then leadocean_search_leads with a limit of 10, then three leadocean_get_lead calls. Only the last two kinds spend records. If you see a search before a count, the rules did not load. Check that CLAUDE.md sits in the folder where you started Claude Code.
/prospect VP-level sales leaders (jobLevel VP, jobFunction Sales & Business Development) at US software companies (industry Software Development) with 51-200 staffStep 5: Check the agent against the API
Do not trust a count you cannot reproduce. The same count over REST is a search with count=true as a query parameter and limit at 1. It returns meta.total and no rows, and it spends nothing.
curl -s "https://api.leadocean.io/v1/people/search?count=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d '{
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"industry": ["Software Development"],
"employeeRange": ["51-200"],
"emailStatus": ["verified", "catch_all_valid", "catch_all"],
"limit": 1
}' | jq '.meta'The body is flat JSON and every filter is an array of strings. Add cursor from meta.nextCursor to page, and limit can go from 1 to 100. If the REST total and the agent's total differ, the agent changed a filter. Read its tool calls and fix the prompt.
Read the account too. GET /v1/account is free and shows records left, so you can confirm the agent spent what it said.
curl -s https://api.leadocean.io/v1/account -H "x-api-key: $LEADOCEAN_API_KEY" | jqStep 6: Scale past ten rows
Ten rows is a spot-check. When the sample looks right, move the bulk pull out of the chat. Search returns at most 100 rows a page, and a long MCP result floods the context. An export writes a CSV file instead.
An export takes the same filters, a limit and a column preset. It takes up to 50,000 rows a request and 500,000 a day. Bulk CSV export is not on the free plan: it is included on Solo ($97 a month) and Agency ($497). Each row costs one record, and records are reserved when the job starts, so count first.
curl -s https://api.leadocean.io/v1/exports \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d '{
"name": "US VP sales, software, 51-200",
"filters": {
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"industry": ["Software Development"],
"employeeRange": ["51-200"],
"emailStatus": ["verified", "catch_all_valid", "catch_all"]
},
"limit": 500,
"preset": "search"
}' | jq '.data | {id, status, requested, remaining, pollAfter}'We kept leadocean_export_leads out of the subagent on purpose. Running a 500-row export should be a decision you make, not a step the agent takes on its own. The LeadOcean app has the same export on its Exports page, with a filter builder, a column picker, the record price before you start and a Download button.
What you get
The agent returns a count first. This is the free MCP count tool run on 21 October 2026 with the filters from step 4, trimmed.
{
"total": 1649,
"totalIsExact": true,
"totalAll": 4141,
"distinctCompanies": 1125,
"defaults": "Counted only addresses worth sending to (emailStatus: verified or catch_all_valid or catch_all)",
"source": "leadocean"
}That is 1,649 mailable people at 1,125 companies, counted for 0 records. With no email condition the same filters match 4,141. The job-level lookup used leadocean_list_enum_values and returned six values: C-Team, Director, Manager, Other, Staff and VP. Your count will differ as the data is refreshed monthly.
Then it saves the brief. This is the format, with placeholder values.
Audience: jobLevel VP, jobFunction Sales & Business Development, US, Software Development, 51-200
Count: 1,649 mailable people (2026-10-21). Pulled: 10. Enriched: 3.
| # | Name | Title | Company | Domain | First line |
|---|----------|--------------|---------|----------|----------------------------------------------|
| 1 | Jane Doe | VP of Sales | Acme | acme.com | Jane, you run sales at a 51-200 person firm. |
Records spent: 13 of 25.Search rows are thin and carry no career history. The three leadocean_get_lead calls return the full record. Since 17 October 2026 that includes resume_data: past roles with title, company and dates, plus education and skills, each when we hold it. Past employers have no company_id yet. Add a rule to the subagent to use a past role in the first line only when it appears in the record.
A search row from the API has a fixed shape. This is the response shape from the API reference, with placeholder values. The page-level meta carries count, limit, total and nextCursor.
{
"data": [
{
"profile_data": { "full_name": "Jane Doe", "headline": "<headline>" },
"contact_data": { "<email and phone flags, current role and company>": "<values>" },
"meta": { "source_ids": { "person_id": "<digits>" } }
}
],
"meta": { "count": 10, "limit": 10, "total": "<total>", "nextCursor": "<cursor>" }
}Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing, wrong or revoked key on a REST call | Copy the key again from app.leadocean.io and re-export $LEADOCEAN_API_KEY. |
| 429 | Above the plan's rate limit: 5 requests a second on Free, 50 on Solo, 200 on Agency | Wait the Retry-After seconds. Page in blocks of 100 rows instead of sending more calls. |
| 402 | The free plan's 1,000 one-off records are spent | Check GET /v1/account. Lower the pull size, or move to Solo ($97) or Agency ($497) on pricing. |
| 400, or a count of 0 | A filter value outside the catalogue, such as jobLevel: "Vice President" | Resolve it with leadocean_list_enum_values (or GET /v1/enums/<name>) and pass the exact string. |
503 no_source | Search was briefly unavailable on the server | Retry with backoff. Counts and lookups cost nothing while it is down. |
| Subagent fails to launch, or cannot see the tools | A tools entry does not match a real tool name | Run claude mcp list, check the server name, and rewrite each entry as mcp__<server>__<tool>. |
FAQ
Why a subagent and not one long prompt?
A subagent has its own context window and its own tool list. Search rows and enrichment output stay out of your main conversation. The allow-list also makes the safe path the only path.
Why set a model on the subagent?
The Claude Code docs list cost control as one reason to use subagents: you can route a narrow task to a faster, cheaper model. Ranking ten rows and writing ten short lines does not need your largest model. Change the model line if the first lines read thin.
What can this agent not do?
It cannot research a company beyond the fields in the record, and it cannot send mail. It also cannot see anyone LeadOcean does not hold, so a miss on a person_id lookup is a miss, not an error. Treat every first line as a draft that needs your edit before it goes anywhere.
How many records does one run cost?
About 13 here. One record per person returned, so 10 search rows and 3 enrichments. Counts and enum lookups are free. A get_lead call that finds nobody costs nothing.
Can the agent send the emails?
Not as built. It has no email tool, and CLAUDE.md says a human sends. If you add a sending tool later, keep the approval step. Read email_status before anything goes out, because bounces are not refunded.
Do I need an API key for the agent?
No. The MCP server uses OAuth sign-in, so you paste no key into Claude Code. Only the REST check in step 5 uses $LEADOCEAN_API_KEY. Plans are on pricing.
Where do I go next?
For the wider system, read how to build a GTM agent on Claude and the Claude GTM masterclass. For a team of agents, see how to build your Claude sales team for B2B GTM. Setup for this client is on Connect LeadOcean to Claude Code. More recipes are in the blog hub.
Give your Claude Code sales agent 693M people to work from
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →