
How to Build a Sales Ops Agent in 30 Minutes
From amodal init to a working deal triage agent in Slack. Every command, every file, every decision explained.
This is a real walkthrough. Not a concept. Not a pitch. By the end, you'll have an agent that connects to Salesforce, triages your pipeline using your methodology, and answers questions in Slack. Every command is real. Every file is shown.
Initialize the project
Start with a directory. amodal init scaffolds the project structure, creates the config file, and sets up .gitignore.
What you get:
.amodal/packages/ directory is gitignored — it's a local cache of installed packages, like node_modules/.Connect Salesforce
amodal connect does three things in one command: installs the connection package from the registry, runs the OAuth flow, and verifies the connection works against live data.
What just happened:
- 1.The
salesforce@2.1.0package was downloaded to the local cache - 2.The package contains 5 files:
spec.json,surface.md(47 endpoints),access.json,entities.md,rules.md - 3.OAuth tokens stored in
.env(gitignored). Never in the snapshot. Never in git. - 4.Lock file updated:
packages.locknow pinssalesforce@2.1.0 - 5.No files created in your repo. Package is in the gitignored cache.
Now connect Slack:
Write the deal triage skill
This is where your domain expertise goes. A skill is a markdown file that tells the agent how to think about a class of problem. It's not code. It's methodology.
First, install the community deal-triage skill as a starting point:
The community skill works out of the box. But your sales process is specific to Acme. Create an override file that adds your domain context on top of the package:
import: deal-triage header means this file inherits the community skill's base methodology and appends your additions. The community skill has generic deal triage logic. Your file adds Acme-specific thresholds, rules, and custom fields. When the package updates (new best practices), you get them automatically. Your overrides stay.Your repo now looks like:
One file in your repo. Everything else comes from packages. That's the point.
Test locally
amodal dev starts a local dev server with a chat UI. It hot-reloads when you edit skills or knowledge.
Open the chat UI. Try it:
The agent queried Salesforce live, applied your staleness thresholds from the skill, checked for decision makers per your rule, and used the custom health score field. All from the markdown file you wrote.
SKILL.md and save. The agent picks up the changes immediately. Change a threshold from 21 days to 14. Ask again. The results change. This is the dev loop: edit markdown, test in chat, iterate.Add a weekly automation
Instead of asking manually, schedule the agent to post a pipeline review every Monday.
The automation defines a prompt + schedule + output channel. On deploy, the platform runs it every Monday at 8am and posts results to #sales-ops in Slack.
Validate and build
Before deploying, validate that everything resolves correctly. Then build the snapshot.
resolved-config.json is a single JSON blob with every package merged, every import resolved, every override applied. No package references remain. This is what the runtime loads. You can inspect it, diff it, or bake it into Docker. This is the free, OSS deploy path — no platform account needed.Deploy
Two options. Pick one:
Option A: Self-hosted (free)
Zero platform dependency. Your Docker, your infra, your data.
Option B: Platform (paid)
Adds: rollback, environments, secrets store, observability, admin UI.
The sales team uses it
The developer is done. Now the actual users take over.
Monday morning: the sales manager asks a question
It's 8:05am. The weekly pipeline automation already posted to #sales-ops. But Sarah, the sales manager, has a specific question before the 9am pipeline meeting:
30 seconds. The agent queried Salesforce live, pulled opportunities + activities + contacts, applied the staleness rules from the skill, found the missing executive engagement, and made a specific recommendation. Sarah didn't open Salesforce. She didn't run a report. She asked a question in Slack.
The VP of Sales customizes it
Jane doesn't use git. She uses the admin UI.
Jane updates the playbook
After the pipeline meeting, Jane decides the Proposal threshold should be 21 days, not 14. She opens the admin UI in her browser:
Jane clicks Preview. A sandbox chat opens. She tests: "Which deals in Proposal are stale?" The agent uses the new 21-day threshold. Looks right.
Jane clicks Publish. Behind the scenes, the platform merges her branch to main. Webhook fires. New snapshot deploys. The production agent now uses 21 days for Proposal.
The developer sees a clean commit on main:
Jane talks to the agent to add a rule
Jane has another change in mind, but this time it's easier to just tell the agent:
30 seconds. A new business rule is in production. Jane described what she wanted in English. The agent translated it to the skill format, saved it, and deployed it.
The controller monitors it
Cost, quality, and the agent's own learning.
Cost check
The controller, Mike, opens the admin UI dashboard on the last day of the month:
$12.40/month for 340 sessions across 8 users. Cheaper than one hour of a BDR's time. Mike clicks the Model Arena suggestion and saves $1.80/month on the automation.
Session replay: is it actually answering correctly?
Mike clicks into a specific session to see exactly what happened:
Full transparency. Every tool call, every skill activation, every token, every penny. Mike can see exactly why the agent said what it said.
The agent learns
Month 1 is good. Month 6 is transformational.
Knowledge proposals: the agent discovers a pattern
After 30 days of triaging 847 opportunities, the agent notices something:
"Deals with no activity for 14+ days in Negotiation stage close at 8% vs 34% baseline."
I analyzed all 847 opportunities closed in the last 6 months. Of the 123 that went silent for 14+ days in Negotiation, only 10 closed-won (8.1%). Baseline close rate for Negotiation-stage deals is 34%. Recommend auto-flagging these as high-risk.
Source: 847 opportunities, 6-month lookback, Salesforce Activity + Opportunity data
"Rep Marcus Rivera consistently leaves deals in Discovery 2x longer than team average."
Marcus's deals average 22 days in Discovery vs 11 days team average. His Qualification-to-Proposal conversion rate is the same as the team (68%), suggesting the extra Discovery time isn't adding value. Consider flagging his Discovery deals at 14 days instead of 21.
Source: per-rep stage duration analysis, last 90 days
Sarah approves the first proposal. The agent now auto-flags silent Negotiation deals. The second proposal she edits: she changes it from a flag to a private note to Marcus's manager, not a public flag. Then approves.
The full lifecycle
What you built
One markdown file with your sales methodology. Two amodal connect commands. One amodal install for the skill. One amodal install for the automation. The agent now triages 847 deals using your specific thresholds, checks for decision makers per your rules, and uses your custom Salesforce fields. Every Monday at 8am, it posts a pipeline summary to Slack.
Connect a second system
The real power: the agent sees across systems.
Add LinkedIn Sales Navigator
The sales team wants the agent to cross-reference deal contacts with LinkedIn data. Who's the decision maker? Have they changed jobs recently? Are they connected to anyone at Acme?
One command. Now the agent can see both Salesforce and LinkedIn. Update the skill to use it:
Now Sarah asks the same question, but gets a richer answer:
Add a third connection tomorrow? amodal connect gong gives the agent call transcripts. amodal connect hubspot gives it marketing engagement. Each connection adds a dimension. The skill tells the agent what to do with it. The connections are just plumbing. The skill is where your expertise lives.
This tutorial used real CLI commands and real file structures. Fork the reference repo and try it yourself.