← Back to all products

AI SDR Agent Kit

$197

An outbound sales-development agent that researches an account, qualifies it with ICP scoring, and writes grounded drafts. Every send goes through an approval gate, sending is dry-run by default, and a do-not-contact list is enforced.

3 filespythonv1.0.0
MarkdownPythonJSONYAMLTOMLLLMOpenAI

Product Preview

Try the interactive reader and demo tools below, or get the full product with all content unlocked.

Interactive Reader (Free Preview) Download Free Sample

File Structure 3 files

ai-sdr-agent-kit/ ├── free_sample ├── interactive └── preview

Documentation Preview README excerpt

AI SDR Agent Kit

A small, auditable outbound pipeline in Python: research -> qualify -> write, then a human approval gate, then

a dry-run-by-default send. A do-not-contact (DNC) list is enforced at three points. Drafts must cite the research

sources they were grounded on; drafts with no citation or an invented source id are rejected.

It vendors the Agent Forge core runtime (src/agent_forge: LLM protocol, MockLLM, guardrails, orchestration) so

the kit is standalone. Everything runs offline against the deterministic MockLLM; no API keys, no network.

Quickstart


python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest                          # offline
python examples/quickstart.py   # synthetic leads -> approval -> dry-run send

Real model: pass any object with complete(messages) -> LLMResponse, e.g. agent_forge.llm.HTTPChatLLM

(OpenAI-compatible; set base URL, key, model). Real research: implement research(lead) -> list[Source].

Pipeline

1. DNC check first - blocked contacts get no research and no model call.

2. Research - FixtureResearch (JSON) ships; plug in your own provider. Sources get ids S1..Sn.

3. Qualify - qualify() is a deterministic ICP score (industry, size, title, buying signal) with a reason for every

point awarded or withheld. Edit ICP weights/threshold.

4. Write - the LLM must cite [S1]-style ids; write_draft rejects uncited or unknown citations.

5. Approve - ApprovalQueue.approve(draft, reviewer); nothing else can move a draft to sendable.

6. Send - send_approved() checks approval, re-checks DNC, and is dry-run unless you pass dry_run=False and

your own Sender. The kit ships no live email transport.

Layout

src/ai_sdr - src/agent_forge (vendored) - data/ (synthetic leads, research, DNC) - tests/ - guide/ - examples/.

What it is not

Not a deliverability tool, not a data provider, not legal advice. Grounding checks verify that cited ids exist, not

that the model's wording is true to the source; the approval step exists for that reason. You are responsible for

complying with anti-spam and privacy law (CAN-SPAM, GDPR/ePrivacy, CASL) and for keeping the DNC list complete.

All companies and people in data/ are synthetic (.example domains).

License: MIT with a no-resale-as-template clause (see LICENSE).

Code Sample .py preview

src/agent_forge/api.py """FastAPI service: per-tenant API keys, blocking + SSE runs, human approval. POST /v1/runs run to completion (or until approval needed) POST /v1/runs/stream same, as Server-Sent Events GET /v1/runs/{id} status / final answer / pending approval POST /v1/runs/{id}/approval approve or reject a paused tool call POST /v1/admin/tenants create tenant + first API key (admin token) GET /healthz liveness (no auth) Auth: ``X-API-Key: afk_...`` (or ``Authorization: Bearer afk_...``). Keys are stored only as HMAC hashes. Runs are tenant-scoped: another tenant's run id returns 404, never 403 (no existence oracle). """ from __future__ import annotations import hmac import json from typing import Any, Iterator from fastapi import Depends, FastAPI, Header, HTTPException, Request from fastapi.responses import JSONResponse, StreamingResponse from pydantic import BaseModel, Field from .config import Settings from .errors import (AgentForgeError, ApprovalNotPending, AuthError, BudgetExceeded, GuardrailViolation, NotFound, PromptInjectionBlocked, ToolNotAllowed) from .runtime import AgentRuntime from .store import Tenant _STATUS = {AuthError: 401, NotFound: 404, ApprovalNotPending: 409, BudgetExceeded: 402, PromptInjectionBlocked: 422, ToolNotAllowed: 403, GuardrailViolation: 422} class RunRequest(BaseModel): task: str = Field(min_length=1, max_length=20000) class ApprovalRequest(BaseModel): approved: bool note: str = Field(default="", max_length=2000) class TenantRequest(BaseModel): id: str = Field(pattern=r"^[a-z0-9][a-z0-9_-]{1,62}$") name: str = "" allowed_tools: list[str] = [] approval_tools: list[str] = [] token_budget: int = Field(default=0, ge=0) usd_budget: float = Field(default=0.0, ge=0) # ... 88 more lines ...
Buy Now — $197 Back to Products