Maintained by NForce.ai
SDRBot is an advanced CLI agent built for Revenue Operations (RevOps) and Sales Development Representatives (SDRs). It is an open-source project by NForce.ai, dedicated to empowering these teams with intelligent automation. It uses Schema Sync to generate strongly-typed tools that match your exact CRM schema, ensuring reliable operations with your custom objects and fields.
It is built on top of LangChain and DeepAgents, capable of planning multi-step workflows, researching prospects, and managing data across multiple CRMs.
SDRbot is provided "as is", without warranty of any kind.
By using this software, you acknowledge that:
- You are responsible for your data: SDRbot is a powerful tool capable of creating, updating, and deleting records in your CRM. We are not liable for any data loss, corruption, or unintended modifications.
- Review Plans Carefully: Always review the agent's proposed plan before approving execution.
- Third-Party Terms: You are responsible for ensuring your use of this tool complies with the Terms of Service of any third-party platforms it interacts with.
sdrbot syncs with your CRM to generate tools with exact field names and types.
- Salesforce: Full support for SOQL, SOSL, and CRUD on Standard & Custom Objects.
- HubSpot: Support for Contacts, Companies, Deals, and Custom Objects via the v3 API.
- Zoho CRM: Full support for all modules including custom modules, COQL queries, and lead conversion.
- Pipedrive: Full support for Deals, Persons, Organizations, Products, Activities, and Leads via the v1 API.
- Attio: Next-gen CRM support using the Attio v2 API (Objects & Attributes).
- Twenty: Open-source CRM support via REST API with OpenAPI-based schema sync.
- Web Search: Native web search capability for basic web searching and investigation.
- Apollo.io Integration: Search 210M+ contacts, enrich people and companies with emails, phone numbers, and firmographic data.
- Lusha Integration: Find prospects by role/industry and enrich them with B2B emails and phone numbers.
- Hunter.io Integration: Find and verify email addresses for any domain.
- Tavily: AI-powered research that can find recent news, revenue data, or strategic insights before reaching out.
- Safe Mode: The agent MUST ask for permission before creating, updating, or deleting records.
- Plan Review: For complex tasks, it writes a TODO list and asks you to review the plan before execution.
- Shell Allow-List: Read-only commands (
ls,grep,git status, etc.) are auto-approved without prompting, keeping the workflow fast while blocking anything destructive.
- Run SDRbot from cron jobs, CI/CD pipelines, or scripts — no TUI needed.
- Supports text and JSON output formats.
- Pipe prompts via stdin:
echo "Enrich today's leads" | sdrbot -n
- Conversations are saved to a local SQLite database and can be resumed across restarts.
- Browse and resume past threads from the Sessions screen.
| Service | Auth Method | Sync Required | Capabilities |
|---|---|---|---|
| Salesforce | OAuth 2.0 | ✓ | SOQL, SOSL, CRUD on all objects |
| HubSpot | OAuth 2.0 or PAT | ✓ | Search, CRUD, Pipelines, Associations |
| Zoho CRM | OAuth 2.0 | ✓ | COQL, CRUD, Lead Conversion, Notes |
| Pipedrive | API Token or OAuth | ✓ | Search, CRUD, Pipelines, Notes, Activities |
| Attio | API Key | ✓ | Query, CRUD, Notes |
| Twenty | API Key | ✓ | Search, CRUD, Notes, Opportunities, Tasks |
| Apollo.io | API Key | — | People/Company Search, Enrichment |
| Lusha | API Key | — | Prospecting, Person/Company Enrichment |
| Hunter.io | API Key | — | Domain Search, Email Finder, Verification |
| PostgreSQL | Connection String | — | SQL Queries, Table Management |
| MySQL | Connection String | — | SQL Queries, Table Management |
| MongoDB | Connection URI | — | CRUD Operations, Collection Management |
| Tavily | API Key | — | Web Search, News Retrieval |
| Gmail | OAuth 2.0 | — | Read, Send, Draft, Labels, Threads |
| Outlook | OAuth 2.0 | — | Read, Send, Draft, Schedule, Folders, Conversations |
| Generic Email | IMAP/SMTP | — | Read, Send, Draft, Search, Folders (Yahoo, AOL, ProtonMail, etc.) |
- Python 3.10+
- Credentials for the services you wish to use.
-
Clone the repository:
git clone <your-repo-url> sdrbot cd sdrbot
-
Create a virtual environment:
python3 -m venv .venv source .venv/bin/activate -
Install the package:
pip install -e .
If you want to distribute sdrbot to non-technical users without requiring them to install Python, you can build a standalone executable file (e.g., .exe on Windows or a binary on Mac/Linux).
-
Build the executable:
make build_executable
-
Locate the binary: The executable will be created in the
dist/folder:- Linux/Mac:
dist/sdrbot - Windows:
dist/sdrbot.exe
You can verify it works by running:
./dist/sdrbot
- Linux/Mac:
Option 1: Interactive Setup (Recommended)
Just run the bot! The first time you launch sdrbot, it will detect missing configuration and guide you through an interactive setup wizard to enter your API keys.
sdrbotYou can also reconfigure settings at any time using /setup to re-run the interactive setup wizard.
Option 2: Manual Configuration (.env)
If you prefer to configure it manually, copy the example environment file and fill in your keys:
cp .env.example .env
nano .envRequired for Agent Brain:
- At least one LLM provider (see LLM Providers below)
TAVILY_API_KEY(Recommended for web research)
CRM & Tools (Fill only what you use):
- Salesforce:
SF_CLIENT_ID,SF_CLIENT_SECRET(Requires a Connected App) - HubSpot:
HUBSPOT_ACCESS_TOKEN(Legacy App Token) ORHUBSPOT_CLIENT_IDandHUBSPOT_CLIENT_SECRET(OAuth) - Zoho CRM:
ZOHO_CLIENT_ID,ZOHO_CLIENT_SECRET,ZOHO_REGION(us, eu, in, au, cn, or jp) - Pipedrive:
PIPEDRIVE_API_TOKENORPIPEDRIVE_CLIENT_IDandPIPEDRIVE_CLIENT_SECRET(OAuth) - Attio:
ATTIO_API_KEY - Twenty:
TWENTY_API_KEY,TWENTY_API_URL(optional, for self-hosted instances) - Apollo.io:
APOLLO_API_KEY - Lusha:
LUSHA_API_KEY - Hunter.io:
HUNTER_API_KEY - PostgreSQL:
POSTGRES_HOST,POSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_PORT,POSTGRES_SSL_MODE(optional: disable, require, verify-ca, verify-full) - MySQL:
MYSQL_HOST,MYSQL_DB,MYSQL_USER,MYSQL_PASSWORD,MYSQL_PORT,MYSQL_SSL(optional: true/false) - MongoDB:
MONGODB_URI,MONGODB_DB,MONGODB_TLS(optional: true/false) - Gmail:
GMAIL_CLIENT_ID,GMAIL_CLIENT_SECRET(OAuth - see Gmail Setup) - Outlook:
OUTLOOK_CLIENT_ID,OUTLOOK_CLIENT_SECRET(OAuth - see Outlook Setup) - Generic Email:
IMAP_HOST,IMAP_PORT,IMAP_USER,IMAP_PASSWORD,SMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASSWORD(see Generic Email Setup)
SDRbot supports multiple LLM providers. Configure your preferred provider through the setup wizard (/setup → Models) or by setting environment variables.
| Provider | Type | Environment Variables |
|---|---|---|
| OpenAI | Cloud | OPENAI_API_KEY |
| Anthropic | Cloud | ANTHROPIC_API_KEY |
| Google Gemini | Cloud | GOOGLE_API_KEY |
| Azure OpenAI | Cloud | AZURE_OPENAI_API_KEY |
| Amazon Bedrock | Cloud | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION |
| HuggingFace | Cloud | HUGGINGFACE_API_KEY |
| Ollama | Local | — (runs locally) |
| vLLM | Local | CUSTOM_API_KEY (optional) |
| Custom Endpoint | Any | CUSTOM_API_KEY (optional) |
Primary providers (thoroughly tested):
- OpenAI
- Anthropic
- Google Gemini
Secondary providers (functional but less tested):
- Azure OpenAI
- Amazon Bedrock
- HuggingFace
- Ollama
- vLLM
- Custom endpoints
You can switch between providers at any time using /models or /setup. Your configuration for each provider is saved, so you can easily switch back without re-entering credentials.
SDRbot uses OAuth 2.0 to securely connect to Salesforce, HubSpot, Zoho CRM, and Pipedrive. You'll need to create your own app credentials in each platform.
Salesforce requires OAuth via an External Client App.
- Log in to Salesforce and go to Setup
- Search for App Manager in the Quick Find box
- Click New External Client App
- Fill in the basic information:
- Name:
SDRbot(or any name you prefer) - API Name: Will auto-populate as
SDRbot - Contact Email: Your email
- Distribution State:
Local
- Name:
- Expand Enable OAuth and configure:
- Callback URL:
http://localhost:8080/callback/salesforce - Selected OAuth Scopes:
Manage user data via APIs (api)- Required for all CRM operationsPerform requests at any time (refresh_token, offline_access)- Required for token refresh
- Callback URL:
- Under Security settings:
- Uncheck Require Proof Key for Code Exchange (PKCE)
- Check Require Secret for Web Server Flow
- Check Require Secret for Refresh Token Flow
- Click Create
- On the app page, select the
Settningstab, then click Consumer Key and Secret - Copy the Consumer Key → This is your
SF_CLIENT_ID - Copy the Consumer Secret → This is your
SF_CLIENT_SECRET
Important: If using a Salesforce Sandbox, set SF_LOGIN_URL=https://test.salesforce.com in your .env.
Admin Tools (Tooling API): The admin tools for creating, updating, and deleting custom fields use the Salesforce Tooling API. These don't require additional OAuth scopes, but the authenticating user must have the "Customize Application" or "Modify All Data" permission in their Salesforce profile.
HubSpot offers two options:
This is the simplest method - no OAuth callback server needed.
- Log in to HubSpot and go to Settings (gear icon)
- Navigate to Integrations → Legacy Apps
- Click Create a legacy app
- Give it a name (e.g.,
SDRbot) - Go to the Scopes tab and add:
- CRM Objects (read/write):
crm.objects.contacts.read/crm.objects.contacts.writecrm.objects.companies.read/crm.objects.companies.writecrm.objects.deals.read/crm.objects.deals.writecrm.objects.owners.read(for listing team members)
- Additional Objects:
tickets(for ticket access)e-commerce(for line items, products, quotes)
- Schema Access (read):
crm.schemas.contacts.read,crm.schemas.companies.read,crm.schemas.deals.readcrm.schemas.custom.read(for custom objects)
- Schema Access (write) - for admin tools:
crm.schemas.contacts.write,crm.schemas.companies.write,crm.schemas.deals.writecrm.schemas.custom.write(for creating custom objects)
- CRM Objects (read/write):
- Click Create app
- Copy the Access token → This is your
HUBSPOT_ACCESS_TOKEN
Use this if you need refresh tokens or plan to distribute SDRbot to others.
- Log in to HubSpot and go to Settings (gear icon)
- Go to developers.hubspot.com and create a developer account (or sign in to your existine one)
- Create a new app and fill in the details
- Go to the Auth tab:
- Redirect URL:
http://localhost:8080/callback/hubspot - Add the same scopes as listed in Option 1 above
- Redirect URL:
- Copy the Client ID → This is your
HUBSPOT_CLIENT_ID - Copy the Client Secret → This is your
HUBSPOT_CLIENT_SECRET
Admin Tools: The crm.schemas.*.write scopes are required for the admin tools that create, update, or delete custom properties and objects. If you don't need these capabilities, you can omit the write scopes.
Zoho CRM requires OAuth 2.0 authentication. The simplest method is creating a "Self Client" for server-side access.
- Log in to Zoho API Console at api-console.zoho.com (use your region's domain: .eu, .in, .com.au, etc.)
- Click Add Client and select Self Client
- Give it a name (e.g.,
SDRbot) - Go to the Client Secret tab:
- Copy the Client ID → This is your
ZOHO_CLIENT_ID - Copy the Client Secret → This is your
ZOHO_CLIENT_SECRET
- Copy the Client ID → This is your
- Set your region in
.env:ZOHO_REGION=usfor zoho.com (United States)ZOHO_REGION=eufor zoho.eu (Europe)ZOHO_REGION=infor zoho.in (India)ZOHO_REGION=aufor zoho.com.au (Australia)ZOHO_REGION=cnfor zoho.com.cn (China)ZOHO_REGION=jpfor zoho.jp (Japan)
Important: Use the API console that matches your Zoho account's data center. If your Zoho account is on zoho.eu, use api-console.zoho.eu.
Pipedrive offers two options:
This is the easiest method - no OAuth callback server needed.
- Log in to Pipedrive and go to Settings (gear icon)
- Navigate to Personal preferences → API
- Copy your Personal API token → This is your
PIPEDRIVE_API_TOKEN
Use this if you need refresh tokens or plan to distribute SDRbot to others.
- Log in to Pipedrive as an admin
- Go to Settings → Tools and apps → Developer hub
- Click Create an app and select Create private app
- Fill in the basic information:
- App name:
SDRbot(or any name you prefer)
- App name:
- Go to the OAuth & access scopes tab:
- Callback URL:
http://localhost:8080/callback/pipedrive - Add these scopes:
deals:full- Manage dealscontacts:full- Manage persons and organizationsactivities:full- Manage activitiesproducts:full- Manage productsleads:full- Manage leadsadmin- Access pipelines, stages, users
- Callback URL:
- Click Save
- Go to the Basic info tab:
- Copy the Client ID → This is your
PIPEDRIVE_CLIENT_ID - Copy the Client Secret → This is your
PIPEDRIVE_CLIENT_SECRET
- Copy the Client ID → This is your
SDRbot supports email services for reading, sending, and managing emails directly from the agent.
Gmail requires OAuth 2.0 authentication via Google Cloud Console.
-
Create a Google Cloud Project
- Go to Google Cloud Console
- Click Select a project → New Project
- Name it (e.g.,
SDRbot Gmail) → Create
-
Enable Gmail API
- Go to APIs & Services → Library
- Search for "Gmail API"
- Click Gmail API → Enable
-
Configure OAuth Consent Screen
- Go to APIs & Services → OAuth consent screen
- Select External → Create
- Fill in required fields:
- App name:
SDRbot - User support email: Your email
- Developer contact: Your email
- App name:
- Click Save and Continue
- Scopes: Click Add or Remove Scopes, add:
https://mail.google.com/(Full Gmail access)
- Save and Continue
- Test users: Click Add Users → Add your Gmail address
- Save and Continue → Back to Dashboard
-
Create OAuth Credentials
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Application type: Desktop app
- Name:
SDRbot Desktop - Click Create
- Copy the Client ID → This is your
GMAIL_CLIENT_ID - Copy the Client Secret → This is your
GMAIL_CLIENT_SECRET
If you have a Google Workspace account, you can use Internal instead of External for the OAuth consent screen:
- Follow the same steps above, but select Internal at step 3
- No need to add test users - all users in your organization can authenticate
- No Google verification required
Note: The app stays in "Testing" mode for personal use, which is fine - only test users you added can authenticate. Publishing requires Google verification (unnecessary for personal/internal use).
Outlook requires OAuth 2.0 authentication via Microsoft Azure Portal (Entra ID).
-
Go to Azure Portal
- Navigate to Azure Portal
- Sign in with your Microsoft account
-
Register an Application
- Go to Microsoft Entra ID (formerly Azure AD) → App registrations
- Click New registration
- Fill in:
- Name:
SDRbot - Supported account types: Select based on your needs:
- "Accounts in any organizational directory and personal Microsoft accounts" (most flexible)
- "Accounts in this organizational directory only" (single tenant)
- Redirect URI: Select "Web" and enter
http://localhost:8080/callback/outlook
- Name:
- Click Register
-
Configure API Permissions
- Go to API permissions → Add a permission
- Select Microsoft Graph → Delegated permissions
- Add these permissions:
Mail.ReadWrite- Read and write mailMail.Send- Send mailUser.Read- Read user profile (required)offline_access- Maintain access (for refresh tokens)
- Click Add permissions
- If admin consent is required, click Grant admin consent (or ask your admin)
-
Create Client Secret
- Go to Certificates & secrets → Client secrets
- Click New client secret
- Add a description and select expiry
- Copy the Value immediately → This is your
OUTLOOK_CLIENT_SECRET - Go to Overview and copy the Application (client) ID → This is your
OUTLOOK_CLIENT_ID
Note: Client secrets expire. Set a calendar reminder to rotate them before expiry.)
When you first use an email tool (Gmail or Outlook):
- SDRbot opens your browser to the provider's OAuth consent page
- Sign in and grant permissions
- Token is stored securely in your system keyring
- Future requests use the stored token (auto-refreshes)
For Generic Email (IMAP/SMTP), no browser flow is needed - credentials are used directly from your configuration.
For email providers that don't have OAuth integrations (Yahoo, AOL, ProtonMail, iCloud, etc.), SDRbot supports direct IMAP/SMTP connections.
The setup wizard includes presets for common providers:
| Provider | IMAP Host | SMTP Host | Notes |
|---|---|---|---|
| Yahoo Mail | imap.mail.yahoo.com:993 | smtp.mail.yahoo.com:465 | Requires App Password |
| AOL Mail | imap.aol.com:993 | smtp.aol.com:465 | Requires App Password |
| iCloud | imap.mail.me.com:993 | smtp.mail.me.com:587 | Requires App Password |
| ProtonMail | 127.0.0.1:1143 | 127.0.0.1:1025 | Requires ProtonMail Bridge |
| Fastmail | imap.fastmail.com:993 | smtp.fastmail.com:465 | Supports App Passwords |
| Zoho Mail | imap.zoho.com:993 | smtp.zoho.com:465 | Enable IMAP in settings |
Most providers require "App Passwords" instead of your regular password:
Yahoo/AOL:
- Go to Account Security settings
- Enable 2-Step Verification (required)
- Scroll to "App Passwords" and generate one for "Other App"
- Use this password in SDRbot
iCloud:
- Go to appleid.apple.com
- Sign in and go to Security → App-Specific Passwords
- Generate a password for "SDRbot"
- Use this password in SDRbot
ProtonMail:
- Install and run ProtonMail Bridge
- Sign in to Bridge with your ProtonMail account
- Get the IMAP/SMTP credentials from Bridge settings
- Use localhost:1143 (IMAP) and localhost:1025 (SMTP)
For other providers or self-hosted email servers, use these environment variables:
# IMAP (Incoming mail)
IMAP_HOST=imap.example.com
IMAP_PORT=993
IMAP_USER=your@email.com
IMAP_PASSWORD=your-app-password
IMAP_SSL=true
# SMTP (Outgoing mail)
SMTP_HOST=smtp.example.com
SMTP_PORT=465
SMTP_USER=your@email.com
SMTP_PASSWORD=your-app-password
SMTP_SSL=trueNote: For ports 993 (IMAP) and 465 (SMTP), use SSL=true. For port 587 (SMTP), use SSL=false (STARTTLS is automatic).
Start the agent:
sdrbot| Command | Description |
|---|---|
/help |
View the user guide with commands and shortcuts |
/setup |
Configure models and services |
/agents |
Manage agent profiles |
/skills |
Manage agent skills |
/services |
Manage CRM integrations |
/mcp |
Manage MCP servers |
/tools |
View all loaded tools (built-in, services, MCP) |
/sync |
Re-sync service schemas |
/tokens |
View token usage stats |
/context |
View context usage and summarization status |
/models |
Configure LLM provider |
/tracing |
Configure tracing/observability |
/exit |
Exit SDRbot |
| Shortcut | Description |
|---|---|
Enter |
Submit message |
Ctrl+J |
New line in input |
Ctrl+A |
Toggle auto-approve mode |
Ctrl+S |
Open setup menu |
Ctrl+T |
Cycle tool scope |
Ctrl+C |
Interrupt agent |
Note: For copy/paste, use Cmd+C/Cmd+V on macOS or Ctrl+Shift+C/Ctrl+Shift+V on Windows/Linux.
Controls which tools are available to the agent:
| Scope | Description |
|---|---|
| Standard | Core CRM tools only (contacts, companies, deals, opportunities) |
| Extended | Standard + custom objects and advanced tools |
| Privileged | All tools including admin/schema management |
Cycle through scopes with Ctrl+T. The current scope is shown in the header next to the tool count.
Run SDRbot without the TUI for scripting, automation, and CI/CD:
# Basic usage with a prompt
sdrbot -n -p "List the top 10 deals closing this month"
# Pipe prompt via stdin
echo "Enrich all leads added today" | sdrbot -n
# JSON output for programmatic consumption
sdrbot -n -p "Count contacts by lifecycle stage" --output-format json
# Limit agent turns and auto-approve all tool calls
sdrbot -n -p "Run data quality check" --max-turns 20 --auto-approve| Flag | Description |
|---|---|
-n / --non-interactive |
Enable headless mode (no TUI) |
-p / --prompt |
The prompt to execute |
--output-format |
text (default) or json |
--max-turns |
Max agent turns before stopping (default: 50) |
--auto-approve |
Approve all tool calls without prompting |
In non-interactive mode, commands on the shell allow-list are auto-approved. All other tool calls require --auto-approve or the run will abort.
When enabled, tools run without confirmation prompts. Toggle with Ctrl+A or start with --auto-approve:
sdrbot --auto-approveSDRbot auto-approves read-only shell commands so the agent can inspect files and check status without interrupting you. Commands containing pipes (|), semicolons (;), subshells, or other shell meta-characters are always blocked.
Default allowed commands include: ls, cat, head, tail, grep, find, git status, git log, git diff, pwd, wc, echo, and more.
Customizing the list: Create .sdrbot/shell_allowlist.json in your project to extend the defaults:
["docker ps", "kubectl get", "terraform plan"]Conversations are automatically saved to .sdrbot/sessions.db (SQLite). You can resume past threads or start fresh.
The sessions screen is accessible from the TUI and shows past conversations sorted by most recent. You can resume a selected thread or delete old ones.
- Salesforce: The first time you ask for Salesforce data, the bot will open a browser for you to log in. It saves the token securely in your system keyring.
- HubSpot (OAuth): Similar to Salesforce, it will launch a browser flow if you are not using a Personal Access Token (PAT).
- Zoho CRM: Opens a browser for OAuth login. Tokens are saved securely in your system keyring with automatic refresh.
- Pipedrive: Uses API Token directly, or launches browser OAuth flow if using Client ID/Secret. Tokens are saved securely with automatic refresh.
- Twenty: Uses API Key directly. Supports both cloud (api.twenty.com) and self-hosted instances.
- Attio / Apollo / Lusha / Hunter: Uses the API Keys defined in your
.env. - Gmail: Launches browser OAuth flow on first use. Tokens are saved securely in your system keyring with automatic refresh.
- Outlook: Launches browser OAuth flow via Microsoft. Tokens are saved securely in your system keyring with automatic refresh.
- Generic Email: Uses IMAP/SMTP credentials directly from config. No browser flow needed.
1. The "Researcher" Workflow
"Find the VP of Sales at 'Datadog' using Lusha. Get their email, and then research recent news about Datadog using the web. Summarize the news and their contact info for me."
2. The "RevOps" Workflow (Salesforce)
"I need to fix some data. Find all Leads in Salesforce created today that are missing a 'Country'. Update them to 'USA' if their phone number starts with +1."
3. The "Cross-Platform" Workflow
"Find the contact 'Elon Musk' in HubSpot. If he exists, create a corresponding record in Attio in the 'People' object."
SDRbot uses a service architecture that generates strongly-typed tools based on your CRM schema. This eliminates errors like "property doesn't exist" by ensuring the agent knows exactly what fields are available.
All service configuration is done through the interactive setup wizard:
# Run the setup wizard
/setupThe wizard allows you to:
- Configure and switch LLM providers (OpenAI, Anthropic, Google, Azure, Bedrock, HuggingFace, Ollama, vLLM, Custom)
- Enable/disable services
- Configure service credentials
- View service status
For CRM services (HubSpot, Salesforce, Zoho CRM, Pipedrive, Attio, Twenty), SDRbot syncs your schema to generate strongly-typed tools.
Automatic sync on startup: When you launch SDRbot, if a service hasn't synced in 24 hours, it will automatically sync.
Manual re-sync: Use /sync when your CRM schema changes:
# Re-sync all enabled services
/sync
# Re-sync a specific service
/sync hubspot- Enable a service: Use
/setupto configure and enable a CRM service - Automatic sync: On startup, SDRbot fetches your CRM schema (objects, fields, types)
- Code generation: Strongly-typed tools are generated (e.g.,
hubspot_create_contactwith exact field names) - Ready to use: The agent now has tools that match your exact schema
Run /sync when:
- You add new custom fields to your CRM
- You create new custom objects
- You modify field types or picklist values
Service configuration is stored in .sdrbot/services.json in your project directory.
SDRbot supports the Model Context Protocol (MCP), allowing you to connect to external MCP servers and use their tools directly within the agent.
MCP is a standardized protocol for AI/tool communication. Many services now offer MCP servers that expose their APIs as tools. SDRbot can connect to these servers as a client and make their tools available to the agent.
Use the MCP wizard to add, manage, and test MCP server connections:
# Open MCP configuration
/mcpOr access it from the main setup wizard via /setup → MCP Servers.
| Transport | Description | Use Case |
|---|---|---|
| stdio | Run MCP server as a subprocess | Local servers (npx, uvx, python) |
| HTTP | Streamable HTTP (modern) | Hosted services like Composio |
| SSE | Server-Sent Events (legacy) | Older MCP servers |
Example: Hosted MCP Service (HTTP)
Server name: gmail
Transport: HTTP
URL: https://mcp.example.com/gmail
Authentication: API Key
API Key: your-api-key-here
Example: Local MCP Server (stdio)
Server name: filesystem
Transport: stdio
Command: npx
Arguments: -y @modelcontextprotocol/server-filesystem /path/to/allowed/dir
For HTTP/SSE servers, SDRbot supports:
- None - No authentication
- Bearer Token -
Authorization: Bearer <token> - API Key -
X-API-Key: <key> - Custom Headers - Define your own headers
Use ${VAR_NAME} syntax to reference environment variables instead of storing secrets in plaintext.
If an MCP connection fails during use, SDRbot will:
- Automatically attempt to reconnect once
- If reconnection fails, disable the server and notify you
- Use
/mcpto re-enable after fixing the issue
MCP server configuration is stored in ~/.sdrbot/mcp_servers.json.
SDRbot integrates with popular tracing platforms to debug and monitor agent runs.
| Platform | Description |
|---|---|
| LangSmith | LangChain's native tracing platform |
| Langfuse | Open-source LLM observability (cloud or self-hosted) |
| Opik | Comet's LLM tracing and evaluation tool |
Enable tracing through the setup wizard:
/tracingOr set environment variables directly:
LangSmith:
LANGSMITH_API_KEY=your-api-key
LANGSMITH_PROJECT=SDRbot # optionalLangfuse:
LANGFUSE_PUBLIC_KEY=your-public-key
LANGFUSE_SECRET_KEY=your-secret-key
LANGFUSE_HOST=https://cloud.langfuse.com # optional, for self-hostedOpik:
OPIK_API_KEY=your-api-key
OPIK_WORKSPACE=your-workspace # optional
OPIK_PROJECT=SDRbot # optionalWhen enabled, traces are automatically sent to the configured platform for every agent interaction.
SDRbot stores agent profiles in the ./agents/ folder in your current directory. Each agent is a folder containing a prompt and memory file.
agents/
├── agent/ # default agent
│ ├── prompt.md # agent instructions
│ └── memory.md # learned preferences (persistent)
├── sales/ # custom agent for sales workflows
│ ├── prompt.md
│ └── memory.md
└── support/ # custom agent for support tasks
├── prompt.md
└── memory.md
Use the /agents command to manage agent profiles directly within the app:
- Create new agent profiles
- Edit agent prompts and memory with the tabbed editor
- Switch between different agents
- Delete agents you no longer need
You can also click on the agent name in the status bar to open the agents manager.
sdrbot --agent sales # Uses ./agents/sales/
sdrbot --agent support # Uses ./agents/support/If the agent folder doesn't exist, it will be created with the default prompt.
SDRbot creates these folders in your working directory (all gitignored):
| Folder | Purpose |
|---|---|
agents/ |
Agent profiles ({name}/prompt.md + memory.md) |
skills/ |
Custom skills ({name}/SKILL.md) - created when you add skills |
files/ |
Agent-generated exports, reports, CSVs - created on first run |
generated/ |
Schema-synced CRM tools (hubspot_tools.py, etc.) - created on sync |
.sdrbot/ |
Service configuration (services.json), sessions DB, shell allow-list |
.sdrbot/subagents/ |
Project-level custom subagent definitions (.md files) |
.sdrbot/sessions.db |
SQLite database for conversation persistence |
.sdrbot/shell_allowlist.json |
Custom shell allow-list (optional) |
Each agent has a persistent memory that survives across sessions. This allows the agent to learn your preferences, remember important context, and improve over time.
- Memory file: Each agent stores memory in
./agents/{name}/memory.md - Auto-loaded: Memory is automatically loaded into the agent's context at startup
- No approval needed: The agent can update its memory freely using dedicated memory tools
The agent has three tools for managing its memory (no approval required):
| Tool | Description |
|---|---|
read_memory() |
Read the current memory file |
write_memory(content) |
Overwrite the entire memory file |
append_memory(content) |
Add to the end of the memory file |
The agent is instructed to update its memory:
- Immediately when you describe how it should behave or its role
- Immediately when you give feedback on its work
- When you explicitly ask it to remember something
- When patterns or preferences emerge during conversations
## Preferences
- User prefers concise responses without lengthy explanations
- Always use metric units for measurements
## Learned Patterns
- When creating HubSpot contacts, always set lifecycle_stage to "lead"
- User's company uses "ACME-" prefix for all deal names
## Project Context
- Main CRM is Salesforce, HubSpot is used for marketing only
- Q4 pipeline review happens every FridayYou can edit an agent's memory directly:
- Use
/agentscommand - Select the agent
- Switch to the Memory tab
- Edit and save
Or edit the file directly at ./agents/{name}/memory.md.
SDRbot automatically manages conversation context to prevent hitting model token limits during long sessions. When context grows too large, older messages are automatically summarized to free up space.
- Monitoring: SDRbot tracks token usage throughout your conversation
- Threshold: When context reaches 85% of the model's limit, summarization triggers (adjustable via SUMMARIZATION_THRESHOLD env param)
- Summarization: Older messages are summarized into a condensed form
- Preservation: 10% of context is preserved after summarization
- Continuation: The conversation continues seamlessly with the summarized history
The summarization system adapts to each model's context window:
| Model Type | Trigger | Preserved |
|---|---|---|
| OpenAI, Anthropic, Google | 85% of max context | 10% of context |
| Ollama, vLLM, Custom | 170k tokens (fallback) | 6 messages |
Use the /context command to see your current context status.
- Older conversation turns (user messages + assistant responses + tool call results)
- The summary captures key context, decisions made, and important information
- System prompt and agent instructions
- Recent messages (10% of context or last 6 messages)
- AI/Tool message pairs are never split
Skills are reusable instructions that extend the agent's capabilities. SDRbot loads skills from three locations (later overrides earlier):
| Source | Location | Purpose |
|---|---|---|
| Built-in | Shipped with SDRbot | Core skills like CRM migration |
| Agent | ./agents/{agent}/skills/ |
Agent-specific skills |
| User | ./skills/ |
Project-wide custom skills |
Use the /skills command to manage skills directly within the app:
- View all available skills (built-in + user)
- Create new skills with a template
- Edit skill instructions with the built-in editor
- Delete skills you no longer need
You can also click on the skills count in the status bar to open the skills manager.
Each skill is a .md file with YAML frontmatter:
---
name: web-research
description: Structured approach to conducting thorough web research
---
# Web Research Skill
## When to Use
- User asks you to research a topic
...SDRbot ships with these built-in skills:
- crm-migration - Efficiently migrate data between CRMs using Python scripts with batching and pagination
Create a skill with the same name in ./skills/ to override a built-in skill with your own version.
Subagents are specialized agents that the main agent can delegate tasks to. SDRbot ships with a built-in CRM Migration Executor subagent and supports loading custom definitions from .md files.
Create .md files with YAML frontmatter in either location:
| Source | Location | Priority |
|---|---|---|
| Built-in | sdrbot_cli/subagents/*.md |
Base |
| Project | .sdrbot/subagents/*.md |
Overrides built-in |
---
name: lead-scorer
description: Scores and prioritizes leads based on firmographic signals
tools:
- shell
- write_file
---
You are a lead scoring specialist. Given a list of leads...The name and description fields are required. The tools list is optional. The body of the file becomes the subagent's system prompt.
Project-level definitions with the same name override built-in ones, letting you customize behavior per project.
SDRbot has a comprehensive test suite covering tool loading, CRUD operations, and service integrations.
We use make and uv to manage tests.
# Run all tests (unit + integration)
make test
# Run only integration tests (requires API keys in .env)
make test_integration
# Run tests in watch mode (re-runs on file change)
make test_watchAlternatively, you can run pytest directly via uv:
# Run all tests
uv run pytest tests/ -v
# Run only unit tests (fast, no API calls)
uv run pytest tests/ -v -m "not integration"
# Run only integration tests (requires API keys in .env)
uv run pytest tests/ -v -m integration
# Run tests for a specific service
uv run pytest tests/services/hubspot/ -vtests/
├── conftest.py # Shared fixtures
├── services/
│ ├── hubspot/
│ │ ├── test_tool_loading.py # Tool discovery tests
│ │ ├── test_crud_operations.py # Create/search/get tests
│ │ └── test_associations.py # Association API tests
│ ├── hunter/
│ │ └── test_hunter_tools.py # Email finder/verifier tests
│ ├── lusha/
│ │ └── test_lusha_tools.py # Enrichment/prospecting tests
│ ├── test_registry.py # Service config tests
│ └── test_tool_loading.py # get_enabled_tools tests
- Unit tests use mocked API clients and run without credentials
- Integration tests are marked with
@pytest.mark.integrationand require API keys - Use the
patch_hubspot_clientfixture for mocking HubSpot API calls - Reset cached clients with
reset_client()before each test
sdrbot is an implementation of the DeepAgents architecture:
- Planner: Breaks down vague requests ("Fix the data") into executable steps.
- Tool Use: Uses LangChain tools to interact with external APIs.
- Memory: Remembers context across the conversation.
- Sandboxing: Capable of running code locally or in remote sandboxes (Modal/Daytona) if configured.
We welcome contributions to SDRbot, an NForce.ai project! If you're interested in helping build the future of AI SDRs:
- Code: Check out our repository at github.com/Revhackers-ai/SDRbot
- Website: Visit us at sdr.bot
- Community: Join our Discord