mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-17 23:09:35 +00:00
feat: Dealix GTM Intelligence OS — multi-agent system
8 agents + 4 models + 4 configs + CLI dry-run + 3 docs. Tested on agency/real_estate/clinic/saas — all pass. Safety: LinkedIn scraping PROHIBITED, WhatsApp blast PROHIBITED. https://claude.ai/code/session_01W1rJthWDkasijTdXCfxVHs
This commit is contained in:
parent
abb94f4a4e
commit
20277e0afc
0
salesflow-saas/backend/dealix_gtm_os/__init__.py
Normal file
0
salesflow-saas/backend/dealix_gtm_os/__init__.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
class BaseAgent(ABC):
|
||||||
|
name: str = "base"
|
||||||
|
description: str = ""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def run(self, input_data: dict) -> dict:
|
||||||
|
pass
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
from dealix_gtm_os.agents.base_agent import BaseAgent
|
||||||
|
from dealix_gtm_os.models.message import ChannelType, AutomationLevel
|
||||||
|
|
||||||
|
SECTOR_CHANNELS = {
|
||||||
|
"agency": (ChannelType.EMAIL, ChannelType.LINKEDIN_MANUAL),
|
||||||
|
"real_estate": (ChannelType.EMAIL, ChannelType.WHATSAPP_WARM),
|
||||||
|
"clinic": (ChannelType.WHATSAPP_WARM, ChannelType.EMAIL),
|
||||||
|
"saas": (ChannelType.EMAIL, ChannelType.LINKEDIN_MANUAL),
|
||||||
|
"ecommerce": (ChannelType.EMAIL, ChannelType.INSTAGRAM_INBOUND),
|
||||||
|
"construction": (ChannelType.EMAIL, ChannelType.PHONE),
|
||||||
|
"training": (ChannelType.EMAIL, ChannelType.WHATSAPP_WARM),
|
||||||
|
"consulting": (ChannelType.LINKEDIN_MANUAL, ChannelType.EMAIL),
|
||||||
|
"website_agency": (ChannelType.LINKEDIN_MANUAL, ChannelType.EMAIL),
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChannelStrategyAgent(BaseAgent):
|
||||||
|
name = "channel_strategy"
|
||||||
|
description = "Selects best outreach channel per target"
|
||||||
|
|
||||||
|
async def run(self, input_data: dict) -> dict:
|
||||||
|
sector = input_data.get("sector", "").lower().replace(" ", "_")
|
||||||
|
channels = SECTOR_CHANNELS.get(sector, (ChannelType.EMAIL, ChannelType.LINKEDIN_MANUAL))
|
||||||
|
primary, secondary = channels
|
||||||
|
manual_channels = {ChannelType.LINKEDIN_MANUAL, ChannelType.WHATSAPP_WARM, ChannelType.PHONE}
|
||||||
|
level = AutomationLevel.MANUAL_REQUIRED if primary in manual_channels else AutomationLevel.SEMI_AUTOMATED
|
||||||
|
return {
|
||||||
|
"primary_channel": primary.value,
|
||||||
|
"secondary_channel": secondary.value,
|
||||||
|
"automation_level": level.value,
|
||||||
|
"reason": f"Sector {sector} best reached via {primary.value}",
|
||||||
|
"risk_flags": ["manual_approval_required"] if level == AutomationLevel.MANUAL_REQUIRED else [],
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import json
|
||||||
|
from dealix_gtm_os.agents.base_agent import BaseAgent
|
||||||
|
from dealix_gtm_os.agents.llm_client import call_llm
|
||||||
|
from dealix_gtm_os.models.company import CompanyInput, CompanyIntelligence
|
||||||
|
|
||||||
|
class CompanyResearchAgent(BaseAgent):
|
||||||
|
name = "company_research"
|
||||||
|
description = "Understands a company from available data"
|
||||||
|
|
||||||
|
async def run(self, input_data: dict) -> dict:
|
||||||
|
company = CompanyInput(**input_data)
|
||||||
|
result_json = await call_llm(
|
||||||
|
f"Analyze company: {company.name}, sector: {company.sector}, city: {company.city}",
|
||||||
|
context={"sector": company.sector or ""}
|
||||||
|
)
|
||||||
|
data = json.loads(result_json)
|
||||||
|
intel = CompanyIntelligence(
|
||||||
|
name=company.name,
|
||||||
|
website=company.website,
|
||||||
|
sector=company.sector or data.get("sector", "unknown"),
|
||||||
|
city=company.city or "",
|
||||||
|
confidence=0.7,
|
||||||
|
**{k: v for k, v in data.items() if k in CompanyIntelligence.model_fields}
|
||||||
|
)
|
||||||
|
return intel.model_dump()
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
import yaml
|
||||||
|
from pathlib import Path
|
||||||
|
from dealix_gtm_os.agents.base_agent import BaseAgent
|
||||||
|
from dealix_gtm_os.models.message import AutomationLevel
|
||||||
|
|
||||||
|
RULES_PATH = Path(__file__).parent.parent / "config" / "compliance_rules.yaml"
|
||||||
|
|
||||||
|
class ComplianceAgent(BaseAgent):
|
||||||
|
name = "compliance"
|
||||||
|
description = "Enforces platform safety rules"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
if RULES_PATH.exists():
|
||||||
|
with open(RULES_PATH) as f:
|
||||||
|
self.rules = yaml.safe_load(f)
|
||||||
|
else:
|
||||||
|
self.rules = {}
|
||||||
|
|
||||||
|
async def run(self, input_data: dict) -> dict:
|
||||||
|
channel = input_data.get("channel", "email")
|
||||||
|
action = input_data.get("action", "send_message")
|
||||||
|
channel_key = channel.replace("_manual", "").replace("_warm", "").replace("_inbound", "").replace("_post", "").replace("_reply", "")
|
||||||
|
if channel_key == "linkedin":
|
||||||
|
channel_key = "linkedin"
|
||||||
|
elif channel_key in ("x", "twitter"):
|
||||||
|
channel_key = "x_twitter"
|
||||||
|
rules = self.rules.get(channel_key, {})
|
||||||
|
if rules.get(action) == "prohibited" or rules.get("scraping") == "prohibited" and action == "scraping":
|
||||||
|
return {"allowed": False, "level": AutomationLevel.PROHIBITED.value, "reason": f"{action} on {channel} is prohibited by platform policy"}
|
||||||
|
if channel in ("linkedin_manual", "whatsapp_warm", "phone"):
|
||||||
|
return {"allowed": True, "level": AutomationLevel.MANUAL_REQUIRED.value, "reason": f"{channel} requires manual human approval"}
|
||||||
|
return {"allowed": True, "level": AutomationLevel.SEMI_AUTOMATED.value, "reason": f"{channel} is safe with opt-out"}
|
||||||
53
salesflow-saas/backend/dealix_gtm_os/agents/llm_client.py
Normal file
53
salesflow-saas/backend/dealix_gtm_os/agents/llm_client.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
"""Mock LLM client — returns structured responses. Replace with real LLM later."""
|
||||||
|
import json
|
||||||
|
|
||||||
|
SECTOR_INTELLIGENCE = {
|
||||||
|
"agency": {
|
||||||
|
"business_summary": "وكالة تسويق تقدم خدمات إعلانية ورقمية للشركات",
|
||||||
|
"products_services": ["إعلانات رقمية", "إدارة سوشال ميديا", "تصميم", "محتوى"],
|
||||||
|
"target_customers": ["شركات صغيرة ومتوسطة", "عقارات", "عيادات", "متاجر"],
|
||||||
|
"revenue_model": "رسوم خدمات شهرية + نسبة من ميزانية الإعلان",
|
||||||
|
"lead_channels": ["موقع إلكتروني", "سوشال ميديا", "إحالات"],
|
||||||
|
"pain_points": ["عملاء يلومونهم على ضعف التحويل", "لا recurring revenue", "leads العميل تضيع بعد الإعلان"],
|
||||||
|
"partnership_potential": "عالي — يقدرون يبيعون Dealix كخدمة لعملائهم",
|
||||||
|
"opportunity_types": ["agency_partner", "co_selling_partner"],
|
||||||
|
},
|
||||||
|
"real_estate": {
|
||||||
|
"business_summary": "شركة تسويق أو تطوير عقاري",
|
||||||
|
"products_services": ["بيع وتأجير عقارات", "تسويق مشاريع عقارية"],
|
||||||
|
"target_customers": ["مشترين أفراد", "مستثمرين", "مستأجرين"],
|
||||||
|
"revenue_model": "عمولات بيع/تأجير + رسوم تسويق",
|
||||||
|
"lead_channels": ["واتساب", "اتصالات", "نماذج موقع", "إعلانات"],
|
||||||
|
"pain_points": ["60% من الاستفسارات ما تُتابع", "المنافسة عالية", "فريق مبيعات صغير"],
|
||||||
|
"partnership_potential": "متوسط — عميل مباشر",
|
||||||
|
"opportunity_types": ["direct_customer"],
|
||||||
|
},
|
||||||
|
"saas": {
|
||||||
|
"business_summary": "شركة تقنية تقدم حلول برمجية",
|
||||||
|
"products_services": ["برمجيات سحابية", "تطبيقات", "حلول تقنية"],
|
||||||
|
"target_customers": ["شركات", "مؤسسات"],
|
||||||
|
"revenue_model": "اشتراكات شهرية/سنوية",
|
||||||
|
"lead_channels": ["موقع إلكتروني", "إعلانات Google", "LinkedIn"],
|
||||||
|
"pain_points": ["leads من الموقع تبرد", "SDR مكلّف", "فريق صغير"],
|
||||||
|
"partnership_potential": "متوسط — عميل أو integration partner",
|
||||||
|
"opportunity_types": ["direct_customer", "integration_partner"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFAULT_INTEL = {
|
||||||
|
"business_summary": "شركة تقدم خدمات في السوق السعودي",
|
||||||
|
"products_services": ["خدمات متنوعة"],
|
||||||
|
"target_customers": ["شركات ومؤسسات"],
|
||||||
|
"revenue_model": "رسوم خدمات",
|
||||||
|
"lead_channels": ["واتساب", "إيميل", "موقع"],
|
||||||
|
"pain_points": ["استفسارات ما تُتابع", "بطء الرد"],
|
||||||
|
"partnership_potential": "متوسط",
|
||||||
|
"opportunity_types": ["direct_customer"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def call_llm(prompt: str, context: dict | None = None) -> str:
|
||||||
|
"""Mock LLM — returns sector-based intelligence. Replace with real API later."""
|
||||||
|
sector = (context or {}).get("sector", "")
|
||||||
|
intel = SECTOR_INTELLIGENCE.get(sector, DEFAULT_INTEL)
|
||||||
|
return json.dumps(intel, ensure_ascii=False)
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
from dealix_gtm_os.agents.base_agent import BaseAgent
|
||||||
|
from dealix_gtm_os.models.message import OutreachMessage, ChannelType, AutomationLevel
|
||||||
|
|
||||||
|
SECTOR_MESSAGES = {
|
||||||
|
"agency": {
|
||||||
|
"first_line": "شفت أنكم تقدمون خدمات تسويق/دعاية لعملاء.",
|
||||||
|
"pain": "عملاؤكم يصرفون على إعلانات والـ leads تضيع بعد الكلك.",
|
||||||
|
"offer": "أضف خدمة متابعة leads لعملائك — 20% لك من كل عميل.",
|
||||||
|
},
|
||||||
|
"real_estate": {
|
||||||
|
"first_line": "لاحظت أن نشاطكم في العقار يعتمد على الاستفسارات.",
|
||||||
|
"pain": "60% من استفسارات الأسعار والمواقع ما تُتابع خلال ساعة.",
|
||||||
|
"offer": "Dealix يرد خلال 45 ثانية ويحجز موعد معاينة.",
|
||||||
|
},
|
||||||
|
"saas": {
|
||||||
|
"first_line": "شفت منتجكم — مشروع قوي.",
|
||||||
|
"pain": "الـ leads من الموقع تبرد خلال ساعة.",
|
||||||
|
"offer": "Dealix يرد فوراً ويؤهل ويحجز demo تلقائياً.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageGenerationAgent(BaseAgent):
|
||||||
|
name = "message_generation"
|
||||||
|
description = "Generates personalized Arabic outreach messages"
|
||||||
|
|
||||||
|
async def run(self, input_data: dict) -> dict:
|
||||||
|
company = input_data.get("name", "الشركة")
|
||||||
|
sector = input_data.get("sector", "").lower().replace(" ", "_")
|
||||||
|
channel = input_data.get("channel", "email")
|
||||||
|
msgs = SECTOR_MESSAGES.get(sector, SECTOR_MESSAGES.get("saas"))
|
||||||
|
body = f"""السلام عليكم فريق {company}،
|
||||||
|
|
||||||
|
أنا سامي من Dealix.
|
||||||
|
|
||||||
|
{msgs['first_line']}
|
||||||
|
|
||||||
|
المشكلة: {msgs['pain']}
|
||||||
|
|
||||||
|
الحل: {msgs['offer']}
|
||||||
|
|
||||||
|
نسوي pilot 7 أيام بـ 499 ريال مع ضمان استرداد كامل.
|
||||||
|
يناسبكم ديمو 10 دقائق؟
|
||||||
|
📅 calendly.com/sami-assiri11/dealix-demo
|
||||||
|
|
||||||
|
سامي العسيري | مؤسس Dealix | dealix.me
|
||||||
|
|
||||||
|
إذا ما يناسبكم هالنوع من الرسائل، ردوا "إيقاف"."""
|
||||||
|
|
||||||
|
msg = OutreachMessage(
|
||||||
|
target_company=company,
|
||||||
|
channel=ChannelType(channel) if channel in [c.value for c in ChannelType] else ChannelType.EMAIL,
|
||||||
|
automation_level=AutomationLevel.MANUAL_REQUIRED,
|
||||||
|
subject=f"فريق {company} — فكرة لتحسين متابعة العملاء",
|
||||||
|
first_line=msgs["first_line"],
|
||||||
|
body=body,
|
||||||
|
cta="يناسبكم ديمو 10 دقائق؟",
|
||||||
|
follow_up_24h=f"متابعة سريعة — أقدر أوريكم خلال 10 دقائق كيف Dealix يحول الاستفسارات لمتابعة وحجز.",
|
||||||
|
follow_up_72h=f"آخر متابعة مني. مهتم → رد 'مهتم'. إيقاف → رد 'إيقاف'.",
|
||||||
|
approval_required=True,
|
||||||
|
)
|
||||||
|
return msg.model_dump()
|
||||||
31
salesflow-saas/backend/dealix_gtm_os/agents/scoring_agent.py
Normal file
31
salesflow-saas/backend/dealix_gtm_os/agents/scoring_agent.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
from dealix_gtm_os.agents.base_agent import BaseAgent
|
||||||
|
from dealix_gtm_os.models.score import TargetScore
|
||||||
|
|
||||||
|
SECTOR_SCORES = {
|
||||||
|
"agency": {"fit": 5, "urgency": 4, "partner": 5, "payment": 3, "case_study": 4},
|
||||||
|
"real_estate": {"fit": 5, "urgency": 5, "partner": 2, "payment": 4, "case_study": 3},
|
||||||
|
"saas": {"fit": 4, "urgency": 4, "partner": 3, "payment": 3, "case_study": 3},
|
||||||
|
"clinic": {"fit": 4, "urgency": 4, "partner": 1, "payment": 4, "case_study": 3},
|
||||||
|
"ecommerce": {"fit": 4, "urgency": 3, "partner": 2, "payment": 3, "case_study": 2},
|
||||||
|
"construction": {"fit": 3, "urgency": 3, "partner": 1, "payment": 3, "case_study": 2},
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScoringAgent(BaseAgent):
|
||||||
|
name = "scoring"
|
||||||
|
description = "Scores a target company"
|
||||||
|
|
||||||
|
async def run(self, input_data: dict) -> dict:
|
||||||
|
sector = input_data.get("sector", "").lower().replace(" ", "_")
|
||||||
|
defaults = SECTOR_SCORES.get(sector, {"fit": 3, "urgency": 3, "partner": 2, "payment": 3, "case_study": 2})
|
||||||
|
has_email = bool(input_data.get("email") or input_data.get("website"))
|
||||||
|
score = TargetScore(
|
||||||
|
company_name=input_data.get("name", "Unknown"),
|
||||||
|
fit=defaults["fit"],
|
||||||
|
urgency=defaults["urgency"],
|
||||||
|
access=4 if has_email else 2,
|
||||||
|
partner=defaults["partner"],
|
||||||
|
payment=defaults["payment"],
|
||||||
|
case_study=defaults["case_study"],
|
||||||
|
risk=2,
|
||||||
|
)
|
||||||
|
return score.model_dump()
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
from dealix_gtm_os.agents.base_agent import BaseAgent
|
||||||
|
from dealix_gtm_os.agents.company_research_agent import CompanyResearchAgent
|
||||||
|
from dealix_gtm_os.agents.scoring_agent import ScoringAgent
|
||||||
|
from dealix_gtm_os.agents.channel_strategy_agent import ChannelStrategyAgent
|
||||||
|
from dealix_gtm_os.agents.compliance_agent import ComplianceAgent
|
||||||
|
from dealix_gtm_os.agents.message_generation_agent import MessageGenerationAgent
|
||||||
|
|
||||||
|
class SupervisorAgent(BaseAgent):
|
||||||
|
name = "supervisor"
|
||||||
|
description = "Orchestrates all GTM agents into a complete pipeline"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.research = CompanyResearchAgent()
|
||||||
|
self.scoring = ScoringAgent()
|
||||||
|
self.channel = ChannelStrategyAgent()
|
||||||
|
self.compliance = ComplianceAgent()
|
||||||
|
self.message = MessageGenerationAgent()
|
||||||
|
|
||||||
|
async def run(self, input_data: dict) -> dict:
|
||||||
|
intel = await self.research.run(input_data)
|
||||||
|
score = await self.scoring.run({**input_data, **intel})
|
||||||
|
channel_plan = await self.channel.run(intel)
|
||||||
|
compliance = await self.compliance.run({"channel": channel_plan["primary_channel"], "action": "send_message"})
|
||||||
|
msg_input = {**intel, "channel": channel_plan["primary_channel"]}
|
||||||
|
message = await self.message.run(msg_input)
|
||||||
|
return {
|
||||||
|
"company": input_data.get("name", "Unknown"),
|
||||||
|
"intelligence": intel,
|
||||||
|
"score": score,
|
||||||
|
"channel_plan": channel_plan,
|
||||||
|
"compliance": compliance,
|
||||||
|
"message": message,
|
||||||
|
"next_action": "send" if compliance["allowed"] else "manual_review",
|
||||||
|
"approval_required": message.get("approval_required", True),
|
||||||
|
}
|
||||||
48
salesflow-saas/backend/dealix_gtm_os/config/channels.yaml
Normal file
48
salesflow-saas/backend/dealix_gtm_os/config/channels.yaml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
channels:
|
||||||
|
email:
|
||||||
|
automation_level: semi_automated
|
||||||
|
daily_limit: 10
|
||||||
|
best_for: [b2b, agencies, companies_with_email]
|
||||||
|
requires: [identity, optout, relevant_reason]
|
||||||
|
|
||||||
|
linkedin_manual:
|
||||||
|
automation_level: manual_required
|
||||||
|
daily_limit: 5
|
||||||
|
best_for: [founders, agencies, b2b_decision_makers]
|
||||||
|
requires: [personalization, manual_send]
|
||||||
|
|
||||||
|
whatsapp_warm:
|
||||||
|
automation_level: manual_required
|
||||||
|
daily_limit: 5
|
||||||
|
best_for: [warm_network, optin_leads, demo_confirmations]
|
||||||
|
requires: [existing_relationship_or_optin, stop_condition]
|
||||||
|
|
||||||
|
instagram_inbound:
|
||||||
|
automation_level: semi_automated
|
||||||
|
daily_limit: 3
|
||||||
|
best_for: [local_brands, visual_businesses, inbound_engagement]
|
||||||
|
requires: [prior_engagement, official_api]
|
||||||
|
|
||||||
|
x_post:
|
||||||
|
automation_level: fully_automated
|
||||||
|
daily_limit: 3
|
||||||
|
best_for: [thought_leadership, founder_content, market_insights]
|
||||||
|
requires: [original_content]
|
||||||
|
|
||||||
|
x_reply:
|
||||||
|
automation_level: manual_required
|
||||||
|
daily_limit: 5
|
||||||
|
best_for: [engagement, conversations, founder_community]
|
||||||
|
requires: [value_add, no_spam]
|
||||||
|
|
||||||
|
phone:
|
||||||
|
automation_level: manual_required
|
||||||
|
daily_limit: 3
|
||||||
|
best_for: [warm_leads, post_demo, partner_conversations]
|
||||||
|
requires: [prior_context]
|
||||||
|
|
||||||
|
partner_intro:
|
||||||
|
automation_level: manual_required
|
||||||
|
daily_limit: 2
|
||||||
|
best_for: [agency_partners, referral_partners]
|
||||||
|
requires: [partner_relationship]
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
linkedin:
|
||||||
|
scraping: prohibited
|
||||||
|
auto_dm: prohibited
|
||||||
|
auto_connect: prohibited
|
||||||
|
auto_like: prohibited
|
||||||
|
auto_comment: prohibited
|
||||||
|
manual_dm: allowed
|
||||||
|
manual_dm_daily_limit: 5
|
||||||
|
posts: allowed
|
||||||
|
comments: manual_only
|
||||||
|
research: allowed
|
||||||
|
|
||||||
|
email:
|
||||||
|
cold_b2b: allowed_with_optout
|
||||||
|
max_sequence_length: 3
|
||||||
|
identity_required: true
|
||||||
|
optout_required: true
|
||||||
|
daily_limit_initial: 10
|
||||||
|
daily_limit_proven: 20
|
||||||
|
misleading_subject: prohibited
|
||||||
|
|
||||||
|
whatsapp:
|
||||||
|
cold_blast: prohibited
|
||||||
|
warm_optin: allowed
|
||||||
|
templates_with_approval: allowed
|
||||||
|
daily_limit_initial: 5
|
||||||
|
daily_limit_proven: 10
|
||||||
|
stop_words:
|
||||||
|
- "إيقاف"
|
||||||
|
- "stop"
|
||||||
|
- "لا"
|
||||||
|
- "لا شكراً"
|
||||||
|
- "ما يناسبني"
|
||||||
|
|
||||||
|
instagram:
|
||||||
|
mass_dm: prohibited
|
||||||
|
inbound_reply: allowed
|
||||||
|
official_api: allowed
|
||||||
|
warm_dm_after_engagement: allowed
|
||||||
|
daily_dm_limit: 3
|
||||||
|
|
||||||
|
x_twitter:
|
||||||
|
auto_mentions: prohibited
|
||||||
|
auto_replies: prohibited
|
||||||
|
auto_dms: prohibited
|
||||||
|
posts: allowed
|
||||||
|
scheduled_posts: allowed
|
||||||
|
safe_manual_replies: allowed
|
||||||
|
daily_reply_limit: 5
|
||||||
|
|
||||||
|
tiktok:
|
||||||
|
dm_scraping: prohibited
|
||||||
|
mass_dm: prohibited
|
||||||
|
content: allowed
|
||||||
|
lead_form_ads: allowed_official
|
||||||
|
dm_ads: allowed_official
|
||||||
|
|
||||||
|
general:
|
||||||
|
fake_accounts: prohibited
|
||||||
|
fake_engagement: prohibited
|
||||||
|
buying_lead_lists: prohibited
|
||||||
|
scraping_restricted_sites: prohibited
|
||||||
|
overclaiming_results: prohibited
|
||||||
|
guaranteed_revenue_claims: prohibited
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
offers:
|
||||||
|
speed_to_lead_audit:
|
||||||
|
name_ar: "تحليل سرعة الرد"
|
||||||
|
price_sar: 0
|
||||||
|
alternative_price: 99
|
||||||
|
duration: "30 دقيقة"
|
||||||
|
purpose: "فتح الباب — ليس بيع"
|
||||||
|
deliverables:
|
||||||
|
- "تحليل أين تضيع الاستفسارات"
|
||||||
|
- "تقييم سرعة الرد الحالية"
|
||||||
|
- "توصية flow بسيط"
|
||||||
|
- "اقتراح pilot مخصص"
|
||||||
|
best_for: [real_estate, clinics, ecommerce]
|
||||||
|
cta: "أقدر أعمل لكم audit مجاني"
|
||||||
|
|
||||||
|
pilot:
|
||||||
|
name_ar: "تجربة 7 أيام"
|
||||||
|
price_sar: 499
|
||||||
|
duration: "7 أيام"
|
||||||
|
purpose: "أول دفع + أول proof"
|
||||||
|
deliverables:
|
||||||
|
- "قناة واحدة (واتساب/إيميل/نماذج)"
|
||||||
|
- "حد 20 lead"
|
||||||
|
- "رسائل متابعة مخصصة"
|
||||||
|
- "تصنيف ردود"
|
||||||
|
- "تقرير نهاية التجربة"
|
||||||
|
guarantee: "استرداد كامل"
|
||||||
|
best_for: [all_sectors]
|
||||||
|
cta: "نبدأ بعميل واحد / قناة واحدة / أسبوع واحد"
|
||||||
|
|
||||||
|
starter:
|
||||||
|
name_ar: "المبتدئ"
|
||||||
|
price_sar: 990
|
||||||
|
billing: monthly
|
||||||
|
purpose: "إيراد متكرر"
|
||||||
|
deliverables:
|
||||||
|
- "واتساب + إيميل"
|
||||||
|
- "follow-up sequences"
|
||||||
|
- "lead tracker"
|
||||||
|
- "booking CTA"
|
||||||
|
- "تقرير أسبوعي"
|
||||||
|
best_for: [proven_pilot_customers]
|
||||||
|
cta: "نكمّل بـ Starter"
|
||||||
|
|
||||||
|
agency_addon:
|
||||||
|
name_ar: "باقة الوكالات"
|
||||||
|
price_sar_range: "1499-2999"
|
||||||
|
purpose: "الوكالة تبيع لعملائها"
|
||||||
|
deliverables:
|
||||||
|
- "إعداد لعميل واحد"
|
||||||
|
- "سكريبتات متابعة"
|
||||||
|
- "tracker + تقارير"
|
||||||
|
- "تدريب بسيط للوكالة"
|
||||||
|
- "قوالب بيع للعميل"
|
||||||
|
partner_share: "20% MRR + 50% setup fee"
|
||||||
|
best_for: [marketing_agencies, digital_agencies]
|
||||||
|
cta: "كن شريك وكالة"
|
||||||
|
|
||||||
|
partner_ops:
|
||||||
|
name_ar: "شراكة مخصصة"
|
||||||
|
price_sar: custom
|
||||||
|
purpose: "شراكات استراتيجية"
|
||||||
|
models: [referral, co_selling, implementation, service_exchange]
|
||||||
|
best_for: [strategic_partners, large_agencies]
|
||||||
|
cta: "نصمم النموذج حسب حجمكم"
|
||||||
|
|
||||||
|
payment:
|
||||||
|
bank: "مصرف الإنماء"
|
||||||
|
account_name: "سامي محمد زايد عسيري — ذكاء الاعمال"
|
||||||
|
account_number: "68207328877000"
|
||||||
|
iban: "SA3305000068207328877000"
|
||||||
|
swift: "INMASARIXXX"
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
weights:
|
||||||
|
fit: 1
|
||||||
|
urgency: 1
|
||||||
|
access: 1
|
||||||
|
partner: 1
|
||||||
|
payment: 1
|
||||||
|
case_study: 1
|
||||||
|
risk: -1
|
||||||
|
|
||||||
|
priority_thresholds:
|
||||||
|
send_today: 24
|
||||||
|
send_this_week: 18
|
||||||
|
send_this_month: 12
|
||||||
|
backlog: 0
|
||||||
|
|
||||||
|
sector_defaults:
|
||||||
|
marketing_agency:
|
||||||
|
fit: 5
|
||||||
|
partner: 5
|
||||||
|
urgency: 4
|
||||||
|
real_estate:
|
||||||
|
fit: 5
|
||||||
|
urgency: 5
|
||||||
|
partner: 2
|
||||||
|
clinic:
|
||||||
|
fit: 4
|
||||||
|
urgency: 4
|
||||||
|
partner: 1
|
||||||
|
ecommerce:
|
||||||
|
fit: 4
|
||||||
|
urgency: 3
|
||||||
|
partner: 2
|
||||||
|
website_agency:
|
||||||
|
fit: 4
|
||||||
|
partner: 4
|
||||||
|
urgency: 3
|
||||||
|
consulting:
|
||||||
|
fit: 3
|
||||||
|
partner: 3
|
||||||
|
urgency: 2
|
||||||
|
construction:
|
||||||
|
fit: 3
|
||||||
|
urgency: 3
|
||||||
|
partner: 1
|
||||||
|
training:
|
||||||
|
fit: 3
|
||||||
|
urgency: 3
|
||||||
|
partner: 1
|
||||||
28
salesflow-saas/backend/dealix_gtm_os/models/company.py
Normal file
28
salesflow-saas/backend/dealix_gtm_os/models/company.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class CompanyInput(BaseModel):
|
||||||
|
name: str
|
||||||
|
website: Optional[str] = None
|
||||||
|
sector: Optional[str] = None
|
||||||
|
city: Optional[str] = None
|
||||||
|
description: Optional[str] = None
|
||||||
|
source: Optional[str] = None
|
||||||
|
email: Optional[str] = None
|
||||||
|
phone: Optional[str] = None
|
||||||
|
|
||||||
|
class CompanyIntelligence(BaseModel):
|
||||||
|
name: str
|
||||||
|
website: Optional[str] = None
|
||||||
|
sector: str
|
||||||
|
city: str = ""
|
||||||
|
business_summary: str
|
||||||
|
products_services: list[str] = Field(default_factory=list)
|
||||||
|
target_customers: list[str] = Field(default_factory=list)
|
||||||
|
revenue_model: str = ""
|
||||||
|
lead_channels: list[str] = Field(default_factory=list)
|
||||||
|
pain_points: list[str] = Field(default_factory=list)
|
||||||
|
partnership_potential: str = ""
|
||||||
|
opportunity_types: list[str] = Field(default_factory=list)
|
||||||
|
sources: list[str] = Field(default_factory=list)
|
||||||
|
confidence: float = 0.5
|
||||||
35
salesflow-saas/backend/dealix_gtm_os/models/message.py
Normal file
35
salesflow-saas/backend/dealix_gtm_os/models/message.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from enum import Enum
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class ChannelType(str, Enum):
|
||||||
|
EMAIL = "email"
|
||||||
|
LINKEDIN_MANUAL = "linkedin_manual"
|
||||||
|
WHATSAPP_WARM = "whatsapp_warm"
|
||||||
|
INSTAGRAM_INBOUND = "instagram_inbound"
|
||||||
|
X_POST = "x_post"
|
||||||
|
X_REPLY = "x_reply"
|
||||||
|
TIKTOK_CONTENT = "tiktok_content"
|
||||||
|
PHONE = "phone"
|
||||||
|
PARTNER_INTRO = "partner_intro"
|
||||||
|
WEBSITE_FORM = "website_form"
|
||||||
|
|
||||||
|
class AutomationLevel(str, Enum):
|
||||||
|
FULLY_AUTOMATED = "fully_automated"
|
||||||
|
SEMI_AUTOMATED = "semi_automated"
|
||||||
|
MANUAL_REQUIRED = "manual_required"
|
||||||
|
PROHIBITED = "prohibited"
|
||||||
|
|
||||||
|
class OutreachMessage(BaseModel):
|
||||||
|
target_company: str
|
||||||
|
channel: ChannelType
|
||||||
|
automation_level: AutomationLevel
|
||||||
|
subject: Optional[str] = None
|
||||||
|
first_line: str
|
||||||
|
body: str
|
||||||
|
cta: str
|
||||||
|
follow_up_24h: str = ""
|
||||||
|
follow_up_72h: str = ""
|
||||||
|
stop_condition: str = "إذا ما يناسبكم، ردوا 'إيقاف'"
|
||||||
|
approval_required: bool = True
|
||||||
|
risk_flags: list[str] = Field(default_factory=list)
|
||||||
32
salesflow-saas/backend/dealix_gtm_os/models/opportunity.py
Normal file
32
salesflow-saas/backend/dealix_gtm_os/models/opportunity.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from enum import Enum
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
class OpportunityType(str, Enum):
|
||||||
|
DIRECT_CUSTOMER = "direct_customer"
|
||||||
|
AGENCY_PARTNER = "agency_partner"
|
||||||
|
REFERRAL_PARTNER = "referral_partner"
|
||||||
|
CO_SELLING_PARTNER = "co_selling_partner"
|
||||||
|
IMPLEMENTATION_PARTNER = "implementation_partner"
|
||||||
|
SERVICE_EXCHANGE = "service_exchange"
|
||||||
|
INTEGRATION_PARTNER = "integration_partner"
|
||||||
|
CONTENT_PARTNER = "content_partner"
|
||||||
|
RESELLER_LATER = "reseller_later"
|
||||||
|
WHITELABEL_LATER = "whitelabel_later"
|
||||||
|
|
||||||
|
class Opportunity(BaseModel):
|
||||||
|
company_name: str
|
||||||
|
opportunity_type: OpportunityType
|
||||||
|
fit_score: int = Field(ge=1, le=5)
|
||||||
|
urgency_score: int = Field(ge=1, le=5)
|
||||||
|
access_score: int = Field(ge=1, le=5)
|
||||||
|
partner_score: int = Field(ge=1, le=5)
|
||||||
|
payment_score: int = Field(ge=1, le=5)
|
||||||
|
risk_score: int = Field(ge=1, le=5)
|
||||||
|
total_score: int = 0
|
||||||
|
reason: str = ""
|
||||||
|
recommended_offer: str = ""
|
||||||
|
recommended_channel: str = ""
|
||||||
|
|
||||||
|
def model_post_init(self, __context):
|
||||||
|
self.total_score = (self.fit_score + self.urgency_score + self.access_score +
|
||||||
|
self.partner_score + self.payment_score - self.risk_score)
|
||||||
27
salesflow-saas/backend/dealix_gtm_os/models/score.py
Normal file
27
salesflow-saas/backend/dealix_gtm_os/models/score.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from pydantic import BaseModel, Field, computed_field
|
||||||
|
|
||||||
|
class TargetScore(BaseModel):
|
||||||
|
company_name: str
|
||||||
|
fit: int = Field(ge=1, le=5)
|
||||||
|
urgency: int = Field(ge=1, le=5)
|
||||||
|
access: int = Field(ge=1, le=5)
|
||||||
|
partner: int = Field(ge=1, le=5)
|
||||||
|
payment: int = Field(ge=1, le=5)
|
||||||
|
case_study: int = Field(ge=1, le=5)
|
||||||
|
risk: int = Field(ge=1, le=5)
|
||||||
|
|
||||||
|
@computed_field
|
||||||
|
@property
|
||||||
|
def total(self) -> int:
|
||||||
|
return self.fit + self.urgency + self.access + self.partner + self.payment + self.case_study - self.risk
|
||||||
|
|
||||||
|
@computed_field
|
||||||
|
@property
|
||||||
|
def priority(self) -> str:
|
||||||
|
if self.total >= 24:
|
||||||
|
return "send_today"
|
||||||
|
elif self.total >= 18:
|
||||||
|
return "send_this_week"
|
||||||
|
elif self.total >= 12:
|
||||||
|
return "send_this_month"
|
||||||
|
return "backlog"
|
||||||
124
salesflow-saas/backend/scripts/gtm_os_dry_run.py
Normal file
124
salesflow-saas/backend/scripts/gtm_os_dry_run.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Dealix GTM OS — Dry Run CLI
|
||||||
|
Analyzes a company and generates a complete GTM pack.
|
||||||
|
DRY-RUN ONLY — does NOT send any messages.
|
||||||
|
"""
|
||||||
|
import asyncio
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
|
from dealix_gtm_os.agents.supervisor_agent import SupervisorAgent
|
||||||
|
|
||||||
|
|
||||||
|
async def run(company_name: str, website: str, sector: str, city: str, email: str):
|
||||||
|
supervisor = SupervisorAgent()
|
||||||
|
result = await supervisor.run({
|
||||||
|
"name": company_name,
|
||||||
|
"website": website,
|
||||||
|
"sector": sector,
|
||||||
|
"city": city,
|
||||||
|
"email": email,
|
||||||
|
})
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print(f" DEALIX GTM OS — DRY RUN")
|
||||||
|
print(f" Company: {company_name}")
|
||||||
|
print(f" ⚠️ DRY-RUN ONLY — لا يرسل رسائل")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
intel = result["intelligence"]
|
||||||
|
print(f"\n{'━' * 40}")
|
||||||
|
print("1. COMPANY INTELLIGENCE")
|
||||||
|
print(f"{'━' * 40}")
|
||||||
|
print(f" Sector: {intel.get('sector', '?')}")
|
||||||
|
print(f" Summary: {intel.get('business_summary', '?')}")
|
||||||
|
print(f" Services: {', '.join(intel.get('products_services', []))}")
|
||||||
|
print(f" Customers: {', '.join(intel.get('target_customers', []))}")
|
||||||
|
print(f" Pain Points: {', '.join(intel.get('pain_points', []))}")
|
||||||
|
print(f" Partnership: {intel.get('partnership_potential', '?')}")
|
||||||
|
print(f" Opportunity: {', '.join(intel.get('opportunity_types', []))}")
|
||||||
|
print(f" Confidence: {intel.get('confidence', 0):.0%}")
|
||||||
|
|
||||||
|
score = result["score"]
|
||||||
|
print(f"\n{'━' * 40}")
|
||||||
|
print("2. TARGET SCORE")
|
||||||
|
print(f"{'━' * 40}")
|
||||||
|
print(f" Fit: {score['fit']}/5 | Urgency: {score['urgency']}/5 | Access: {score['access']}/5")
|
||||||
|
print(f" Partner: {score['partner']}/5 | Payment: {score['payment']}/5 | Case Study: {score['case_study']}/5")
|
||||||
|
print(f" Risk: {score['risk']}/5")
|
||||||
|
print(f" TOTAL: {score['total']} → Priority: {score['priority']}")
|
||||||
|
|
||||||
|
channel = result["channel_plan"]
|
||||||
|
print(f"\n{'━' * 40}")
|
||||||
|
print("3. CHANNEL STRATEGY")
|
||||||
|
print(f"{'━' * 40}")
|
||||||
|
print(f" Primary: {channel['primary_channel']}")
|
||||||
|
print(f" Secondary: {channel['secondary_channel']}")
|
||||||
|
print(f" Automation: {channel['automation_level']}")
|
||||||
|
print(f" Reason: {channel['reason']}")
|
||||||
|
if channel.get("risk_flags"):
|
||||||
|
print(f" Risk Flags: {', '.join(channel['risk_flags'])}")
|
||||||
|
|
||||||
|
comp = result["compliance"]
|
||||||
|
print(f"\n{'━' * 40}")
|
||||||
|
print("4. COMPLIANCE")
|
||||||
|
print(f"{'━' * 40}")
|
||||||
|
print(f" Allowed: {'✅' if comp['allowed'] else '❌'}")
|
||||||
|
print(f" Level: {comp['level']}")
|
||||||
|
print(f" Reason: {comp['reason']}")
|
||||||
|
|
||||||
|
msg = result["message"]
|
||||||
|
print(f"\n{'━' * 40}")
|
||||||
|
print("5. MESSAGE (DRAFT — NOT SENT)")
|
||||||
|
print(f"{'━' * 40}")
|
||||||
|
print(f" Channel: {msg['channel']}")
|
||||||
|
print(f" Subject: {msg.get('subject', 'N/A')}")
|
||||||
|
print(f" Approval Required: {'✅ YES' if msg['approval_required'] else 'No'}")
|
||||||
|
print(f"\n --- BODY ---")
|
||||||
|
for line in msg["body"].split("\n"):
|
||||||
|
print(f" {line}")
|
||||||
|
print(f" --- END ---")
|
||||||
|
print(f"\n Follow-up 24h: {msg['follow_up_24h'][:80]}...")
|
||||||
|
print(f" Follow-up 72h: {msg['follow_up_72h'][:80]}...")
|
||||||
|
print(f" Stop: {msg['stop_condition']}")
|
||||||
|
|
||||||
|
print(f"\n{'━' * 40}")
|
||||||
|
print("6. NEXT ACTION")
|
||||||
|
print(f"{'━' * 40}")
|
||||||
|
print(f" Action: {result['next_action']}")
|
||||||
|
print(f" Approval Required: {'✅ YES — Sami must approve before sending' if result['approval_required'] else 'No'}")
|
||||||
|
|
||||||
|
prohibited = []
|
||||||
|
if "linkedin" in channel["primary_channel"]:
|
||||||
|
prohibited.append("LinkedIn scraping")
|
||||||
|
prohibited.append("LinkedIn auto-DM")
|
||||||
|
prohibited.extend(["WhatsApp cold blast", "Instagram mass DM", "Fake accounts"])
|
||||||
|
print(f"\n{'━' * 40}")
|
||||||
|
print("7. PROHIBITED ACTIONS")
|
||||||
|
print(f"{'━' * 40}")
|
||||||
|
for p in prohibited:
|
||||||
|
print(f" ❌ {p}")
|
||||||
|
|
||||||
|
print(f"\n{'=' * 60}")
|
||||||
|
print(" ⚠️ DRY-RUN COMPLETE — NO MESSAGES SENT")
|
||||||
|
print(f"{'=' * 60}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Dealix GTM OS Dry Run")
|
||||||
|
parser.add_argument("--company-name", required=True)
|
||||||
|
parser.add_argument("--website", default="")
|
||||||
|
parser.add_argument("--sector", default="agency")
|
||||||
|
parser.add_argument("--city", default="الرياض")
|
||||||
|
parser.add_argument("--email", default="")
|
||||||
|
args = parser.parse_args()
|
||||||
|
asyncio.run(run(args.company_name, args.website, args.sector, args.city, args.email))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
73
salesflow-saas/docs/gtm_os/CHANNEL_AUTOMATION_POLICY.md
Normal file
73
salesflow-saas/docs/gtm_os/CHANNEL_AUTOMATION_POLICY.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Dealix GTM OS — Channel Automation Policy
|
||||||
|
|
||||||
|
## Per-Channel Rules
|
||||||
|
|
||||||
|
### LinkedIn
|
||||||
|
| Action | Level | Rule |
|
||||||
|
|--------|-------|------|
|
||||||
|
| Profile viewing | Manual | Research only |
|
||||||
|
| Post publishing | Allowed | Via Sami's account |
|
||||||
|
| Commenting | Manual | Value-add only, no spam |
|
||||||
|
| Connection requests | Manual | Max 10/day with personal note |
|
||||||
|
| DMs | Manual | Max 5/day, personalized |
|
||||||
|
| Scraping | **PROHIBITED** | LinkedIn ToS violation |
|
||||||
|
| Auto-DM bots | **PROHIBITED** | Account ban risk |
|
||||||
|
|
||||||
|
### Email
|
||||||
|
| Action | Level | Rule |
|
||||||
|
|--------|-------|------|
|
||||||
|
| Targeted B2B | Semi-auto | With opt-out, max 10/day initially |
|
||||||
|
| Follow-up sequence | Semi-auto | Max 3 per target |
|
||||||
|
| Mass cold | **PROHIBITED** | Until email infrastructure ready |
|
||||||
|
| Fake sender | **PROHIBITED** | Always use real identity |
|
||||||
|
|
||||||
|
### WhatsApp
|
||||||
|
| Action | Level | Rule |
|
||||||
|
|--------|-------|------|
|
||||||
|
| Warm messages | Manual | People who know Sami |
|
||||||
|
| Opt-in follow-up | Semi-auto | Via Green API templates |
|
||||||
|
| Demo confirmation | Allowed | After booking |
|
||||||
|
| Cold blasting | **PROHIBITED** | Account ban + legal risk |
|
||||||
|
| Status updates | Allowed | Daily |
|
||||||
|
|
||||||
|
### Instagram
|
||||||
|
| Action | Level | Rule |
|
||||||
|
|--------|-------|------|
|
||||||
|
| Posts/Stories/Reels | Allowed | Content + engagement |
|
||||||
|
| Inbound DM reply | Allowed | Within 24h window |
|
||||||
|
| Cold DM | **PROHIBITED** | Platform risk |
|
||||||
|
| Comment engagement | Manual | Value-add only |
|
||||||
|
|
||||||
|
### X / Twitter
|
||||||
|
| Action | Level | Rule |
|
||||||
|
|--------|-------|------|
|
||||||
|
| Posts/Threads | Allowed | Scheduled or manual |
|
||||||
|
| Safe replies | Manual | Value-add, no spam |
|
||||||
|
| Auto mentions | **PROHIBITED** | X ToS violation |
|
||||||
|
| Auto DMs | **PROHIBITED** | X ToS violation |
|
||||||
|
|
||||||
|
### TikTok
|
||||||
|
| Action | Level | Rule |
|
||||||
|
|--------|-------|------|
|
||||||
|
| Organic content | Allowed | Videos/posts |
|
||||||
|
| Lead form ads | Allowed | Official ad system |
|
||||||
|
| DM scraping | **PROHIBITED** | Platform risk |
|
||||||
|
| Mass DM | **PROHIBITED** | Platform risk |
|
||||||
|
|
||||||
|
## Daily Limits (Initial)
|
||||||
|
|
||||||
|
| Channel | Daily Limit | After Proof |
|
||||||
|
|---------|------------|-------------|
|
||||||
|
| Email | 10 | 20 |
|
||||||
|
| LinkedIn DM | 5 (manual) | 5 |
|
||||||
|
| WhatsApp warm | 5 | 10 |
|
||||||
|
| X replies | 5 | 10 |
|
||||||
|
| Instagram DM | 2 (inbound only) | 3 |
|
||||||
|
|
||||||
|
## Approval Gates
|
||||||
|
- First message to any new person: **Sami approval**
|
||||||
|
- WhatsApp to non-warm: **Sami approval**
|
||||||
|
- Claims about results: **Sami approval**
|
||||||
|
- Payment link: **Sami approval**
|
||||||
|
- Partner terms: **Sami approval**
|
||||||
|
- Sending >10 messages/day: **Sami approval**
|
||||||
33
salesflow-saas/docs/gtm_os/DATA_SOURCES_POLICY.md
Normal file
33
salesflow-saas/docs/gtm_os/DATA_SOURCES_POLICY.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Dealix GTM OS — Data Sources Policy
|
||||||
|
|
||||||
|
## Allowed Sources
|
||||||
|
|
||||||
|
| Source | Type | Usage | Risk |
|
||||||
|
|--------|------|-------|------|
|
||||||
|
| Uploaded company files (Excel/CSV) | User data | Primary targeting | Low |
|
||||||
|
| Public company websites | Public | Research + enrichment | Low |
|
||||||
|
| Google Programmable Search | Official API | Web search | Low |
|
||||||
|
| Tavily | AI search API | Structured web results | Low |
|
||||||
|
| Official social media APIs | Official | Inbound + public data | Low |
|
||||||
|
| CRM data | Internal | Lead tracking | Low |
|
||||||
|
| Inbound messages | Opt-in | Customer conversations | Low |
|
||||||
|
| Manual imports by Sami | User action | Ad-hoc targeting | Low |
|
||||||
|
| Public business directories | Public | Company discovery | Low |
|
||||||
|
|
||||||
|
## Prohibited Sources
|
||||||
|
|
||||||
|
| Source | Reason |
|
||||||
|
|--------|--------|
|
||||||
|
| LinkedIn scraping/crawling | Platform ToS violation |
|
||||||
|
| Instagram profile scraping | Platform ToS violation |
|
||||||
|
| Purchased email/phone lists | Privacy + spam risk |
|
||||||
|
| Unauthorized data brokers | Legal risk |
|
||||||
|
| Scraping restricted websites | ToS violation |
|
||||||
|
| Personal data without consent | PDPL violation |
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
1. Every data point must have a traceable source
|
||||||
|
2. No invented/hallucinated company data
|
||||||
|
3. No personal data collection without legitimate basis
|
||||||
|
4. All enrichment from public or API-approved sources only
|
||||||
|
5. User can request deletion of their data
|
||||||
66
salesflow-saas/docs/gtm_os/GTM_OS_ARCHITECTURE.md
Normal file
66
salesflow-saas/docs/gtm_os/GTM_OS_ARCHITECTURE.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Dealix GTM OS — Architecture
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
```
|
||||||
|
Company Input → Research → Enrichment → ICP Detection → Opportunity Mapping
|
||||||
|
→ Channel Strategy → Message Generation → Compliance Check
|
||||||
|
→ Human Approval / Safe Automation → CRM Tracking → Learning Loop
|
||||||
|
```
|
||||||
|
|
||||||
|
## Layers
|
||||||
|
|
||||||
|
### A. Data Layer
|
||||||
|
Collects from allowed sources only:
|
||||||
|
- Uploaded company files
|
||||||
|
- Public websites
|
||||||
|
- Google Programmable Search / Tavily
|
||||||
|
- Official APIs
|
||||||
|
- CRM data
|
||||||
|
- Inbound messages
|
||||||
|
- Manual imports
|
||||||
|
|
||||||
|
### B. Intelligence Layer
|
||||||
|
13 specialized agents understand companies, markets, and opportunities.
|
||||||
|
|
||||||
|
### C. Compliance Layer
|
||||||
|
Decides: allowed / manual_required / opt_in_required / prohibited
|
||||||
|
|
||||||
|
### D. Execution Layer
|
||||||
|
Only safe actions: drafts, CRM tasks, scorecards, content packs, approved campaigns.
|
||||||
|
|
||||||
|
### E. Learning Layer
|
||||||
|
Tracks replies, demos, conversions. Updates ICP, scoring, messages, channels weekly.
|
||||||
|
|
||||||
|
## 13 Agents
|
||||||
|
|
||||||
|
| Agent | Role | Input | Output |
|
||||||
|
|-------|------|-------|--------|
|
||||||
|
| Supervisor | Orchestrates all | CompanyInput | Full GTM Pack |
|
||||||
|
| Company Research | Understands company | Name/URL/sector | CompanyIntelligence |
|
||||||
|
| Web Search | Searches allowed sources | Query | SearchResults |
|
||||||
|
| Enrichment | Adds data | CompanyInput | EnrichedCompany |
|
||||||
|
| ICP Strategist | Determines ideal customers | CompanyIntelligence | ICPList |
|
||||||
|
| Partnership Strategist | Maps partnership types | CompanyIntelligence | PartnershipMap |
|
||||||
|
| Channel Strategy | Picks best channel | Company + Compliance | ChannelPlan |
|
||||||
|
| Message Generation | Writes Arabic messages | Company + Channel | OutreachMessage |
|
||||||
|
| Compliance | Enforces platform rules | Channel + Action | Decision |
|
||||||
|
| Campaign Orchestrator | Builds sequences | Company + Messages | CampaignSequence |
|
||||||
|
| Negotiation | Handles objections | Reply + Context | NegotiationResponse |
|
||||||
|
| CRM & Revenue | Tracks status | Events | StatusUpdate |
|
||||||
|
| Learning | Improves system | Results | UpdatedStrategy |
|
||||||
|
|
||||||
|
## Automation Boundaries
|
||||||
|
|
||||||
|
| Level | What | Examples |
|
||||||
|
|-------|------|---------|
|
||||||
|
| Fully Automated | Internal processing | Research, scoring, drafts, CRM tasks, reports |
|
||||||
|
| Semi-Automated | Approved channels | Email with opt-out, inbound chatbot, WhatsApp templates |
|
||||||
|
| Manual Required | Risky channels | LinkedIn DMs, Instagram DMs, phone calls |
|
||||||
|
| Prohibited | Policy violation | LinkedIn scraping, WhatsApp blast, fake accounts |
|
||||||
|
|
||||||
|
## Safety Rules
|
||||||
|
- LinkedIn: NO scraping/bots/automated DMs
|
||||||
|
- X: NO unsolicited automated replies/mentions
|
||||||
|
- WhatsApp: opt-in only, stop on "إيقاف"
|
||||||
|
- Instagram: inbound/official API only
|
||||||
|
- TikTok: content + official ads/lead forms only
|
||||||
Loading…
Reference in New Issue
Block a user