skills/initiate-inboxmate-knowledge/SKILL.md
Load this before any InboxMate work — gives the full architecture: how systems connect, what IDs link what, object states, and the data flow from demo creation through email outreach. Use whenever starting InboxMate pipeline work, debugging cross-system issues, or when a skill references objects/states you don't understand.
npx skillsauth add psquared-development/psquared-skills initiate-inboxmate-knowledgeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This is a context-loading skill. Read it, internalize the model, then proceed with whatever task you were doing.
InboxMate spans five independent systems. Each owns its data and exposes its own API. No system directly reads another's database — they're connected through shared IDs.
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Twenty CRM │ │ AgentHub DB │ │ Notif. Svc │
│ (GraphQL) │ │ (Supabase) │ │ (REST) │
│ │ │ │ │ │
│ Opportunities│────▶│ demo_pages │ │ email_drafts │
│ Companies │ ↑ │ agents │ │ email_queue │
│ Campaigns │ │ │ knowledge_* │ │ │
│ People/Notes │ │ │ │ │ │
└──────────────┘ │ └──────────────┘ └──────────────┘
│ │ │
│ serves demo │
│ page content │
│ ▼ │
│ ┌──────────────┐ │
│ │ Demo Pages │ │
│ │ (frontend) │ │
│ │demo.inboxmate│ │
│ │.psquared.dev │ │
│ └──────────────┘ │
│ │
│ ┌──────────────┐ │
└──│ Ackee │◀────────────┘
│ (analytics) │ (tracks views)
└──────────────┘
The CRM Opportunity is the central record. Everything else hangs off it.
CRM Opportunity
├── .id → used as crm_opportunity_id in email_drafts
├── .demoId → points to demo_pages.id in AgentHub DB
├── .companyId → points to CRM Company
├── .campaignId → points to CRM Campaign
└── .demoStatus → state machine (see below)
AgentHub: demo_pages
├── .id → this IS the demoId stored in CRM
├── .agent_id → points to agents table
└── .crm_opportunity_id → backlink (often NULL, don't rely on it)
AgentHub: agents
├── .knowledge_bucket_ids → uuid[] pointing to knowledge_buckets
└── .published_at → non-null means live
AgentHub: knowledge_buckets → knowledge_bucket_items → knowledge_bucket_chunks
└── items have: source_type ('url' | 'knowledge_link' | 'text' | 'pdf')
└── items have: embedding_status ('pending' | 'processing' | 'completed' | 'failed')
Notification Service: email_drafts
├── .crm_opportunity_id → links back to CRM Opportunity
├── .crm_company_id → links to CRM Company
├── .draft_type → 'outreach' | 'followup'
├── .parent_draft_id → followup points to its outreach draft
└── .status → 'DRAFT' | 'QUEUED' | 'SENT' | 'FAILED'
Critical rule: The CRM opportunity's demoId field is the only reliable cross-system link between CRM and AgentHub. The demo_pages.crm_opportunity_id column exists but is often NULL. When resolving CRM → demo page, always query CRM for demoId, don't query Supabase by crm_opportunity_id.
┌─────────────────┐
│ PENDING_REVIEW │ ← demo built, awaiting QA
└────────┬────────┘
pass │ │ fail
▼ ▼
┌────────────┐ ┌───────────┐
│ OK_TO_SEND │ │ NEEDS_FIX │ → fix → back to PENDING_REVIEW
└─────┬──────┘ └───────────┘
│ campaign + email sent
▼
┌──────────┐
│ SENT │ ← outreach email sent, outreachSentAt set
└─────┬────┘
│ follow-up sent
▼
┌─────────────────┐
│ FOLLOW_UP_SENT │
└─────────────────┘
Skip states (terminal): SKIP_FAULTY_WEBSITE, SKIP_IRRELEVANT, SKIPPED, DISQUALIFIED
| Stage | Meaning |
|---|---|
| SCREENING | Outreach phase (all demo pipeline work happens here) |
| MEETING | Prospect responded / call scheduled |
| PROPOSAL | Quoted or decision-maker demo |
| CUSTOMER | Paying customer |
DRAFT → (schedule) → QUEUED → (send job) → SENT
→ FAILED
Follow-up drafts are created alongside initial outreach (linked via parent_draft_id), with send_after_days controlling when they queue.
Campaigns group opportunities into sendable batches. A campaign has offerExpiresAt and offerText which are injected into demo pages dynamically (not stored on demo_pages directly — the API merges them at read time with a 5-min cache).
create_agent)create_demo_page) → returns demo_pages.iddemoId = the demo page UUIDdemoUrl = https://demo.inboxmate.psquared.dev/?id=<demoId>/review-demos fetches PENDING_REVIEW opportunities/plan-campaign creates a CRM CampaigncampaignIdofferText and offerExpiresAt on the campaign/setup-email-drafts queries OK_TO_SEND opportunitiescrm_opportunity_id for back-linkingemail_queuesend_after_daysdemo_pages.claimed = true| System | Endpoint | Auth Token |
|---|---|---|
| CRM | POST https://crm.psquared.dev/graphql | $PSQUARED_CRM_TOKEN |
| MCP | POST https://app.psquared.dev/api/mcp | $NUXT_MCP_DEMO_TOKEN |
| Demo API | GET https://app.psquared.dev/api/demo/<id> | None (public) |
| Notif. Svc | https://notifications.psquared.dev/drafts/* | $EMAIL_DRAFT_ONLY_BEARER |
| Sanity Check | POST https://notifications.psquared.dev/drafts/sanity-check | $EMAIL_DRAFT_ONLY_BEARER |
| Ackee | POST https://ackee.psquared.dev/api | $ACKEE_TOKEN |
| Supabase | mcp__plugin_supabase_supabase__execute_sql | project: fevtfywriufbqnvbgyrm |
The notification service exposes a sanity check that validates demo agent health. Accepts three input modes:
// By opportunity IDs
{ "crm_opportunity_ids": ["uuid", ...] }
// By campaign
{ "campaign_id": "uuid" }
// By draft IDs
{ "draft_ids": ["uuid", ...] }
Returns per-item: healthy boolean + issues array + warnings array. Checks:
Response includes demo_page_id for cross-system debugging, and avg_tokens for knowledge quality assessment.
CRM uses inline IDs, not parameterized variables. Twenty CRM's GraphQL does NOT support $id: ID! parameters. Always inline UUIDs directly in the query string.
Don't source .env — values contain semicolons. Use Read tool or grep to extract specific values.
MCP token is NUXT_MCP_DEMO_TOKEN (not INBOXMATE_DEMO_MCP_TOKEN). Some older skills use the wrong name.
knowledge_link = URL-sourced. In knowledge_bucket_items.source_type, items scraped from URLs are stored as knowledge_link, not url. Both are valid URL-sourced content.
Campaigns manage deadlines, not individual demos. Never set offerExpiresAt or offerText directly on demo_pages — these come from the campaign and are merged dynamically at API read time.
Follow-up emails: never mention "follow-up" in the subject. Body must be unique, not a generic template. Always include variables in PUT body when updating drafts.
Never guess URLs for scraping. Always discover real pages from the homepage navigation first. Generic patterns (/kontakt/, /ueber-uns/, /leistungen/) fail on 60%+ of sites.
Tavily failures → WebFetch fallback. scrape_and_build_knowledge uses Tavily. Some sites block it (all URLs timeout). When this happens, use WebFetch to scrape pages manually and add via add_to_bucket with sourceUrl. Never leave a bucket empty.
Skip junk URLs: /wp-json/, /xmlrpc.php, /feed/, /favicon.ico, .webp, .ico — these produce garbage knowledge items.
Content limit is 50K characters per knowledge item. Tavily advanced mode can return large pages — they won't be truncated.
404 pages are auto-detected by scrape_and_build_knowledge — pages with "nicht gefunden"/"not found"/"404" in the title are rejected and returned in the failed array. No need to check manually.
Based on what you're trying to do, use:
| Goal | Skill |
|------|-------|
| Need new leads | /find-leads [N] |
| Create demos for CRM leads | /inboxmate-batch-demo or /inboxmate-demo <company> |
| QA existing demos | /review-demos |
| Fix flagged demos | /fix-demos |
| Check if demos are healthy | /sanity-check |
| Group demos into a campaign | /plan-campaign |
| Create outreach emails | /setup-email-drafts [campaignId] |
| Edit email drafts | /refine-email-drafts |
| Check how outreach is doing | /check-outreach-status |
| Full funnel analytics | /check-demo-analytics |
| Upgrade demo knowledge | /refurbish-demos |
| Change pricing | /price-change |
| Deep debugging / raw queries | /analyse-inboxmate |
If starting from scratch, follow this sequence:
/find-leads → /inboxmate-batch-demo → /review-demos → /fix-demos (if needed)
→ /sanity-check → /plan-campaign → /setup-email-drafts → /refine-email-drafts (if needed)
→ 👤 send → /check-outreach-status → /check-demo-analytics
tools
Generate a polished psquared client offer as a multi-page PDF (title, project description, screenshots, Angebot/pricing, AGB). Walks the user through gathering inputs (or accepts a JSON config), renders branded HTML templates with Playwright in two passes (title page edge-to-edge + body pages with margins and pagination), then merges with pdf-lib.
data-ai
Create email drafts for approved InboxMate demos. Verifies all demos are ready, pulls contacts from CRM, creates CRM tasks, and creates draft emails via the notification service. Run after /review-demos has processed all pending demos.
development
Audit or fix SEO issues for a single website or page. Checks meta tags, structured data, technical SEO, content quality, i18n, and AI readiness using only WebFetch — no external APIs. Pass a URL and mode (audit or fix) as parameters.
development
Run SEO audit or fix across all psquared websites autonomously. Dispatches parallel agents for psquared.dev, inboxmate.psquared.dev, ki-linz.at, and agenthub.psquared.dev, then presents a combined report. Pass mode (audit or fix) as parameter.