Skip to content

Part 3 · Operate

Agent access

Connect this product to the agent you already work in, under the same permissions as the screen.

01What it is

An MCP server, a versioned REST API and signed webhooks let an outside agent read your brief, search your accounts and people, capture what it finds, write drafts into the approval queue, and be told when something happens. All three run under a credential you issue, reaching only the ventures you name.

02Why it exists

A product that lives behind a browser login is a product you have to remember to open, and remembering is the overhead this whole system exists to remove. If the founder already runs their working day through an agent, the brief should arrive there.

The rule that makes it safe is one sentence: every agent path enforces the same gates, approvals and limits as the screen. There is no faster path for a program than for a person. A draft an agent writes lands in the same queue, passes the same quality gate, and waits for the same approval. Nothing an agent can hold widens a sending cap or an autonomy stage, because a caller that can widen its own limits has no limits.

The second reason is where this category is going. A product with an MCP server becomes a component inside other people's agents rather than another tab, and that is a better place to be than another dashboard.

03How to use it

  1. 01Open Settings → Agent access and copy the MCP address.
  2. 02Or, for anything that speaks HTTP, read /api/v1/openapi.json — it describes every route and is generated from the same registry the server runs on.
  3. 03Paste it into an agent that speaks MCP. It sends you back here to choose what it may do and which ventures it may reach.
  4. 04For a script or a tool that cannot run a browser redirect, issue a key instead. The secret is shown once and stored hashed.
  5. 05Watch the call log. It records every call, including the refused ones.
  6. 06Add a webhook in Settings → Webhooks so an agent is told when a draft is ready rather than asking every few minutes.
  7. 07Revoke anything you no longer recognise. Revocation takes effect on the next call.

04What good looks like

You give it
A read-only key calls get_brief at 7am with no venture id, in a workspace with one venture.
You get
One response carrying what is waiting on approval, how many follow-ups are overdue, how many companies are watched, and the accounts where something moved with the dated reason for each.
Why
A credential that reaches exactly one venture does not have to name it, and get_brief is deliberately one call rather than four so a morning briefing costs one round trip.

Observed in a real run

05What weak looks like, and what it costs

You give it
The same read-only key calls watch_company.
You get
A refusal naming the missing capability and everything the key does hold, and a 403 in the call log against write:watchlist.
Why
Scopes are checked before the handler runs, so a tool a credential cannot hold never reaches its implementation. The refusal names the scope because an agent told only "forbidden" retries the same call.

Observed in a real run

06Read next

Agent tools

The capabilities reachable over MCP and the REST API. Each declares one scope, checked before the handler runs.

NameValueWhat it does
list_venturesno scope neededThe ventures this credential can reach, with their id, name and what each one sells. Call this first when you do not already have a venture id: almost every other tool takes one, and a credential covering more than one venture will refuse to guess. Cheap.
get_briefread:briefEverything waiting this morning, in one call: accounts where something moved and why, how many drafts need review, how many follow-ups are overdue, and what is being watched. This is the right first call for a daily briefing — it replaces four separate list calls and returns roughly a page of text. Cheap; it reads stored state and generates nothing.
list_approvalsread:approvalsDrafts a human has yet to allow: outreach messages and content, with the evidence behind each one. Use this to triage — read the grounding, decide, then call approve_outreach or approve_content per item. Nothing here has been sent or published. Cheap.
list_followupsread:followupsPeople owed a next touch, oldest first, with what was agreed and when they were last contacted. The second message is the one that wins and also the one that gets dropped, so this is usually the highest-value read in the product. Cheap.
list_companiesread:companiesSearch watched companies by name, domain or window state. Returns the score, the window and the one-line reason, not the full timeline — call get_company for that. Use this to answer "which accounts are hot" or to find a company id. Cheap.
get_companyread:companiesThe dated evidence behind a company: every change observed, in order, each with its source URL and confidence, plus the current window verdict. This is what to read before writing to anyone there — it is also the only place the reasons are dated, and a message that cites an undated reason reads as a guess. Moderate: returns up to 40 events.
list_peopleread:peoplePeople in the CRM by name, stage or what is owed them. Returns identity and stage, not their history — call get_person for that. Use it to find a person id before logging a touchpoint. Cheap.
get_personread:peopleEverything on one person: stage, every touch on every channel in order, and the intel gathered about them with source URLs and dates. Read this before drafting to them — the whole point of the second message is that it refers to the first, and this is where the first is recorded. Moderate.
list_contentread:contentArtifacts by channel and state: drafts in the gates, pieces waiting for approval, and what has been published. Returns titles and state by default; pass include_body to get the text, which is much larger. Cheap without bodies.
get_channel_performanceread:performanceWhat each channel produced against what it cost, by period, with the learned rank and whether it is below the floor. Use this to answer "where is effort paying off" — it is the allocation view, not a vanity count. Cheap.
get_learningread:learningAggregate patterns: which message angles against which company states produced replies, with attempt counts and confidence. Counts only — no identities and no message bodies ever cross this boundary, by construction. Use it to ask what is working before drafting something new. Cheap.
list_mentionsread:mentionsThings people said in public that may be worth answering: comments on your posts, threads captured from communities, and anything forwarded in. Each carries its category, a strength score and the source URL. Use it to triage what deserves a reply. Cheap.
watch_companywrite:watchlistAdd a company to the watchlist by domain. It starts being read on the normal cadence; changes show up in get_company and, when several land together, in get_brief. Use this when a company comes up in conversation and is worth tracking. Idempotent: calling it twice is safe and returns the existing row. Cheap.
add_personwrite:peoplePut a person into the CRM with a name, a title and optionally a LinkedIn URL. Creates the relationship record too, at stage `identified`. Use this when somebody comes up who is worth tracking; log what was said with log_touchpoint afterwards. Cheap.
log_touchpointwrite:touchpointsRecord that something happened with a person: a call, a reply, a DM, a meeting. This is what keeps the timeline honest when a conversation happens somewhere the product cannot see, and it is the single most useful thing an agent can write here. Updates the relationship’s last-touch date. Cheap.
capture_threadwrite:capturesHand the system a public thread, post or question somebody asked — a Reddit URL, a forum post, a Slack message the user pasted to you. It classifies the intent and, when it reads as somebody looking for what this venture sells, writes a reply draft into the approval queue. Use it whenever the user mentions a conversation worth answering. Moderate: this runs a classifier and may run a drafting model.
submit_ideawrite:ideasQueue an idea for content without writing anything yet. Use this when the user says something worth posting but does not want it drafted now — draft_content is the call that turns an idea into posts. Cheap.
request_readwrite:watchlistAsk for a watched company to be re-read before its next scheduled pass. Use it when something is known to have changed and waiting for the cadence would be too slow. Returns immediately; the read happens in the background and shows up in get_company. Cheap to call, and it costs a fetch rather than a model call.
draft_contentdraft:contentTurn one idea into a native post for each channel this venture runs — the phrasing, length and shape differ per channel rather than one text being reposted. Everything produced runs the quality gate and lands in the approval queue at state `passed`; nothing is published. Expensive: this is several model calls, one per channel. Call it once per idea, not in a loop.
draft_replydraft:outreachWrite a reply to a comment or a thread somebody posted — from list_mentions. Produces a public reply and, where the platform allows one, a private one, both through the full gate stack, both landing in the approval queue. There is deliberately no way to open a conversation with somebody who has not engaged first: this replies, it does not approach. Expensive: one model call.
draft_followupdraft:outreachWrite the follow-up to somebody already contacted, grounded in what was sent before and anything observed since. Requires a previous message on record; it will not open a conversation. Lands in the approval queue and sends nothing. Expensive: one model call.
approve_contentact:approveRecord a human-authorised approval for one artifact and move it to `approved`. This does not publish: publishing is a separate act, and content in `approved` sits until it is scheduled or posted. Refuses anything that has not passed the quality gate. One artifact per call, by id. Cheap.
approve_outreachact:approveApprove one drafted message and hand it to the send pipeline. **This sends.** It is the same thing the approve button in the app does, and it runs the identical pre-send gate — suppression list, excluded domains, per-domain caps, sending-identity health, autonomy stage and budget, all checked in one transaction. If any of those refuse, nothing goes out and the reason comes back. One draft per call, by id: read it before you approve it. Moderate.
mark_publishedact:publish_markRecord that an approved piece went out, with the URL it went out at. Use it when the user posts by hand — most channels are published by a person, and without this the system cannot measure what happened. It does not post anything; it records that somebody did. Cheap.
advance_relationshipact:relationshipSet where a person is in the pipeline: identified, researched, first_touch, engaged, conversation, proposal, won, lost, ghosted or nurture. Use it when the user tells you what happened — a stage that only ever moves forward automatically is a stage nobody trusts. Cheap.
snooze_followupact:snoozeMove when a person is next owed a touch, or clear it entirely. Use it when the user says "not until next month" — an overdue list full of things that are not actually overdue is a list people stop reading. Cheap.
explain_readexplain:readThe reasoning behind a company read: which observed changes carried the conclusion, which were treated as noise, what the confidence is and what would raise it. Use it whenever a conclusion needs to be defended or checked — and use it before repeating a claim to anybody, because it names the dated sources. Cheap.

Webhook events

What a signed webhook can carry. Each maps to the read scope that would let you fetch the same thing, so an endpoint cannot subscribe its way past a permission.

NameValueWhat it does
read.producedread:companiesA company was read and something changed. Carries the company, what moved and the new confidence.
window.openedread:companiesEnough changed at one company inside a few weeks to open a buying window. This is the event most worth acting on.
draft.readyread:approvalsSomething was written and is waiting for a person. Carries the id and the channel, not the text.
approval.grantedread:approvalsA person allowed a draft. Fires whether the approval came from the app, an agent or the API.
message.sentread:approvalsA message left the mailbox, or a post was published.
outcome.recordedread:learningA reply, a bounce, a meeting or a silence was classified. Negative outcomes fire too; they are the useful half.
mention.classifiedread:mentionsA mention or capture was classified and cleared the strength floor. Carries the category and the source URL.
followup.overdueread:followupsSomebody is owed a touch and the date has passed.
identity.pausedread:approvalsA sending identity stopped sending: a bounce rate, a complaint, or a token that expired. Sending is already halted when this fires.
hypothesis.killedread:learningA hypothesis was retired because it stopped earning its allocation.
channel.rank_changedread:performanceA channel moved in the learned ranking. Only fires above the sample floor, because a rank below it means nothing.
Agent access · InstinctGTM