One engagement, three parts
Every engagement combines experienced people, agentic teammates, and real engineering. Where we start depends on where you're stuck. Most teams need a bit of all three.
Experienced GTM, RevOps, and engineering people on the engagement from day one. Advice, best practices, and hands-on help, with a human accountable for the work.
Typical first work
Our people take over what's urgent while we figure out what to build.
Custom agents that take on real ops work and live where your team already works, in Slack or Teams. People ask them questions, hand them tasks, and report problems to them.
Typical first work
We build the first teammate out of the work your team does every week.
The engineering the work needs, from hardening a prototype to data-model design, pipelines, integrations, and internal tools that don't exist yet.
Typical first work
We take ownership of the codebase and get it running somewhere real.
Pay for deliverables without any surprises
You pay a fixed monthly price for a defined engagement, so you know the cost going in. Our people take the work on first, then we build. After that it's your call.
To start
Quick wins and transition
We take ownership of what's urgent. Depending on where you're stuck, that means our people picking up the request queue, taking over a prototype's codebase and deployment, or standing up the infrastructure nobody has had time for. You get real value early, before any agent exists.
Then
The build
We build the agentic teammates, the data foundations, and the tools we agreed on, and we fix the standing issues underneath them. By the end, the agents are doing the work and your team can run everything we built.
Optional, month to month
Ongoing services
Keep us on for maintenance and incident response, new teammates as needs come up, flexible ops and engineering help, or larger strategic projects. Scoped and priced during the initial engagement, once we both know what's running.
The teammates we build
Every teammate has a job, the way a person on your team does. These are the jobs that come up most, and each one is built from your systems and your team's actual work rather than off a shelf.
Handles the admin work a fractional agency bills hourly for: automations, field builds, integration troubleshooting, user and permission management, and data cleanup.
Answers stakeholder questions from a unified partner data model, and flags renewal risk in Teams before anyone has to go looking for it.
Delivers scheduled reports in Slack, answers on-demand questions from live data with its sources, and runs a review queue with approvals.
Watches ad spend and web analytics together, reports what each campaign actually sourced, and flags the terms and channels quietly burning budget.
Builds and qualifies target lists and event-attendee lists that sales will actually work.
Flags incomplete opportunities, scores accounts on signals, and surfaces what's actually working in the pipeline.
Where the work happens
Teammates live in Slack or Teams, alongside everyone else. People ask them questions, hand them tasks, and report problems to them, the way they would a colleague.
@account-agent pull the portfolio companies off ridgelinecapital.com/portfolio into a list with Name, Domain, Industry and Description. CSV please.
is anyone else getting stonewalled at Northwind? their switchboard just hangs up on me now
same. i've given up and started going straight to the VP on email
works maybe one time in eight but that's eight times better than the switchboard
one in eight is a rounding error away from zero marcus
and yet it is not zero
the portfolio list is loaded. the five that aren't actually theirs would have gone out in the sequence, so that catch saved me a round of apology emails
# Adapted from a real screenshot, scrubbed. The firm, its portfolio companies,
# the people and the account names are invented; the shape of the exchange, the
# agent's voice, and the kind of thing it catches are not.
#
# Numbered 01 so it's the channel that opens by default: it's the transcript
# that best shows a teammate doing GTM work.
#
# Two things the real screenshot had that this widget can't render: a CSV file
# attachment with a table preview, and bulleted notes. The table becomes prose
# and the notes become paragraphs. The collapsed tool-call step (`meta`) and the
# trailing duration (`footer`) map directly.
title: Pulling a PE firm's portfolio into a target list
channel: sales
actors:
priya:
displayName: priya
dana:
displayName: dana
marcus:
displayName: marcus
account-agent:
displayName: account-agent
bot: true
messages:
- actor: priya
timestamp: 9:12 AM
text: |
<@account-agent> pull the portfolio companies off `ridgelinecapital.com/portfolio` into a list with Name, Domain, Industry and Description. CSV please.
thread:
title: pull the portfolio companies off ridgelinecapital.com
lastReply: Today at 9:15 AM
replies:
- actor: account-agent
timestamp: 9:13 AM
meta: Used 4 tools
- actor: account-agent
timestamp: 9:15 AM
text: |
All 21, pulled from the raw page rather than the summarized fetch, which mangled a couple of the domains.
Three things before you load it. Two of the domains on the page are wrong, so I used the ones I confirmed by search. Five of the 21 aren't Ridgeline deals at all, the page's own disclosure says the partners made those at a previous firm. And seven are marked sold or recapped, which I noted inline in Description rather than adding a column.
file:
name: ridgeline-portfolio.csv
meta: CSV · 21 rows
footer: Worked for 2m 20s
- actor: dana
timestamp: 9:14 AM
text: |
is anyone else getting stonewalled at Northwind? their switchboard just hangs up on me now
- actor: marcus
timestamp: 9:16 AM
text: |
same. i've given up and started going straight to the VP on email
works maybe one time in eight but that's eight times better than the switchboard
- actor: dana
timestamp: 9:17 AM
text: |
one in eight is a rounding error away from zero marcus
- actor: marcus
timestamp: 9:18 AM
text: |
and yet it is not zero
- actor: priya
timestamp: 9:24 AM
text: |
the portfolio list is loaded. the five that aren't actually theirs would have gone out in the sequence, so that catch saved me a round of apology emails
@account-agent pull the portfolio companies off ridgelinecapital.com/portfolio into a list with Name, Domain, Industry and Description. CSV please.
All 21, pulled from the raw page rather than the summarized fetch, which mangled a couple of the domains.
Three things before you load it. Two of the domains on the page are wrong, so I used the ones I confirmed by search. Five of the 21 aren't Ridgeline deals at all, the page's own disclosure says the partners made those at a previous firm. And seven are marked sold or recapped, which I noted inline in Description rather than adding a column.
can we get a field on Opportunity for who we're up against? i've been keeping it in a spreadsheet and it's useful to exactly one person, me
we had one. it sat at 6% fill for two years and got archived in the last cleanup
but if sales actually wants it this time i'll take the bet
i will fill it in every time. for at least three weeks. possibly four
good enough for me. @admin-agent add a Primary Competitor picklist to Opportunity, sales-facing layouts only. values from the win/loss list in the enablement doc
the 2023 field is the part i would have forgotten about until someone ran a report and got two answers
skip the migration, that data is four years stale and half those competitors don't exist anymore
agreed. @admin-agent push it to production and go ahead on the report type
# INVENTED, not adapted from a screenshot. The other two transcripts come from
# real agent sessions; this one shows a stack admin agent, which we haven't
# needed to build yet and certainly can. Keeping it in the set because the
# admin work is the most common thing the buyer is drowning in, and a page
# about taking that work off their plate shouldn't be silent on it.
#
# So the bar here is plausibility rather than provenance: every caveat the
# agent raises is a real thing a careful Salesforce admin checks before
# shipping a field.
title: Adding a competitor field to Opportunity
channel: ops-team
actors:
priya:
displayName: priya
marcus:
displayName: marcus
sam:
displayName: sam
admin-agent:
displayName: admin-agent
bot: true
messages:
- actor: priya
timestamp: 8:46 AM
text: |
can we get a field on Opportunity for who we're up against? i've been keeping it in a spreadsheet and it's useful to exactly one person, me
- actor: sam
timestamp: 8:52 AM
text: |
we had one. it sat at 6% fill for two years and got archived in the last cleanup
but if sales actually wants it this time i'll take the bet
- actor: marcus
timestamp: 8:53 AM
text: |
i will fill it in every time. for at least three weeks. possibly four
- actor: sam
timestamp: 8:55 AM
text: |
good enough for me. <@admin-agent> add a Primary Competitor picklist to Opportunity, sales-facing layouts only. values from the win/loss list in the enablement doc
thread:
title: add a Primary Competitor picklist to Opportunity
lastReply: Today at 8:58 AM
replies:
- actor: admin-agent
timestamp: 8:56 AM
meta: Used 5 tools
- actor: admin-agent
timestamp: 8:58 AM
text: |
Done in sandbox, not production yet. `Primary_Competitor__c` on Opportunity, picklist, 9 values from the enablement doc plus "Other" and "No competitor".
Three notes. There's a deactivated `Competitor__c` from 2023 with 412 populated records, and I left it alone rather than reactivating it, because its values don't map cleanly onto the new list. Say the word if you want that history migrated.
I added it to the three layouts sales actually uses and skipped the CS and finance ones, per sales-facing only. And I left it optional, since making it required would block the 63 open opportunities that predate the field.
One thing I didn't do: it isn't on the Pipeline Review report type yet. That's a shared report and changing it affects everyone's saved views, so I'd want your go-ahead first.
footer: Worked for 1m 12s
- actor: sam
timestamp: 9:04 AM
text: |
the 2023 field is the part i would have forgotten about until someone ran a report and got two answers
- actor: priya
timestamp: 9:06 AM
text: |
skip the migration, that data is four years stale and half those competitors don't exist anymore
- actor: sam
timestamp: 9:07 AM
text: |
agreed. <@admin-agent> push it to production and go ahead on the report type
good enough for me. @admin-agent add a Primary Competitor picklist to Opportunity, sales-facing layouts only. values from the win/loss list in the enablement doc
Done in sandbox, not production yet. Primary_Competitor__c on Opportunity, picklist, 9 values from the enablement doc plus "Other" and "No competitor".
Three notes. There's a deactivated Competitor__c from 2023 with 412 populated records, and I left it alone rather than reactivating it, because its values don't map cleanly onto the new list. Say the word if you want that history migrated.
I added it to the three layouts sales actually uses and skipped the CS and finance ones, per sales-facing only. And I left it optional, since making it required would block the 63 open opportunities that predate the field.
One thing I didn't do: it isn't on the Pipeline Review report type yet. That's a shared report and changing it affects everyone's saved views, so I'd want your go-ahead first.
the territory planning page is finally live. @nina are we putting spend behind it or letting it sit?
spend's already running. i went broad match to see what sticks, which i will either look smart or very stupid for by friday
@growth-agent please get ad metrics from the past 7 days
so we paid eighty dollars to find out people searching for spreadsheet templates are not in market for territory planning
we paid eighty dollars to find out in a week instead of a quarter. i'll take it
for what it's worth the two conversions that did come through both booked. small sample, but they weren't junk
# Adapted from a real screenshot, scrubbed. The people, the product, the
# campaign and every figure are invented; the shape of the report, the agent's
# voice, and the fact that it asks for sign-off before touching the ad account
# are not.
#
# The people carry over from 01-sales.yaml on purpose, so the widget reads as
# one company's Slack rather than three unrelated mockups.
#
# The real reply had a search-term table. This widget has no table renderer, so
# the rows are prose. `meta` is the collapsed tool-call step and `footer` is the
# trailing duration, both straight from the screenshot.
title: Reading a week of ad spend on a new landing page
channel: gtm-leaders
actors:
nina:
displayName: nina
theo:
displayName: theo
priya:
displayName: priya
growth-agent:
displayName: growth-agent
bot: true
messages:
- actor: theo
timestamp: Yesterday at 10:21 AM
text: |
the territory planning page is finally live. <@nina> are we putting spend behind it or letting it sit?
- actor: nina
timestamp: Yesterday at 10:23 AM
text: |
spend's already running. i went broad match to see what sticks, which i will either look smart or very stupid for by friday
- actor: nina
timestamp: Yesterday at 10:25 AM
text: |
<@growth-agent> please get ad metrics from the past 7 days
thread:
title: please get ad metrics from the past 7 days
lastReply: Yesterday at 11:01 AM
replies:
- actor: growth-agent
timestamp: Yesterday at 10:25 AM
meta: Used 6 tools
- actor: growth-agent
timestamp: Yesterday at 10:27 AM
text: |
Search term report, past 7 days.
Caveat first: terms are only visible for $88.40 of the campaign's actual $196.20. Google suppresses query text below its privacy threshold, so read this as directionally right, not complete.
471 of the 486 visible terms got zero clicks, and the top ones are off-target: "salesforce", "smartsheet", "geographic information systems", "spreadsheet templates". Of the spend on terms that did get clicks, 85% went to queries with zero conversions.
Broad match is fanning out into unrelated categories, which explains the impression surge alongside collapsing CTR. Recommendation: add those as campaign-level negatives. I'd need your explicit sign-off before I touch the account.
footer: Worked for 2m 16s
- actor: nina
timestamp: Yesterday at 10:59 AM
text: |
what broad match keywords do we have running?
- actor: growth-agent
timestamp: Yesterday at 11:01 AM
text: |
One campaign is active, `territory-planning-free`, running three broad match terms: "territory planning software", "sales territory mapping", and "account segmentation tool".
The first is doing most of the fanning out. It's the only one loose enough to match "salesforce".
- actor: theo
timestamp: Yesterday at 11:12 AM
text: |
so we paid eighty dollars to find out people searching for spreadsheet templates are not in market for territory planning
- actor: nina
timestamp: Yesterday at 11:14 AM
text: |
we paid eighty dollars to find out in a week instead of a quarter. i'll take it
- actor: priya
timestamp: Yesterday at 11:20 AM
text: |
for what it's worth the two conversions that did come through both booked. small sample, but they weren't junk
@growth-agent please get ad metrics from the past 7 days
Search term report, past 7 days.
Caveat first: terms are only visible for $88.40 of the campaign's actual $196.20. Google suppresses query text below its privacy threshold, so read this as directionally right, not complete.
471 of the 486 visible terms got zero clicks, and the top ones are off-target: "salesforce", "smartsheet", "geographic information systems", "spreadsheet templates". Of the spend on terms that did get clicks, 85% went to queries with zero conversions.
Broad match is fanning out into unrelated categories, which explains the impression surge alongside collapsing CTR. Recommendation: add those as campaign-level negatives. I'd need your explicit sign-off before I touch the account.
what broad match keywords do we have running?
One campaign is active, territory-planning-free, running three broad match terms: "territory planning software", "sales territory mapping", and "account segmentation tool".
The first is doing most of the fanning out. It's the only one loose enough to match "salesforce".
What you keep
You own everything we build. The agents and their configuration, the code, the data models, the context materials they run on, and the applications. It lives in GitHub repositories you own and runs on your infrastructure, and we put that in writing every time.
That includes the toolkit for running the agents. Bishop is our own metaharness, the layer that turns a Claude Code or Codex agent into a teammate people work with in Slack and Teams. We plan to license it under MIT so there's no proprietary runtime to be locked into. It's our default rather than a requirement, and we'll use something else where it fits better.
Tell us where you're stuck
Book a call and walk us through what's on your list. We'll tell you what we'd take off it.
Book a call