Objective
Tier-1 tickets ("export failed", "password reset", "where is my invoice") eat 60% of support headcount. Generic RAG bots answer the wrong question because they don't see the customer's actual state. This recipe builds an agent that reads the docs AND the customer's recent activity in one call, then either resolves the ticket or escalates with the full context attached.
Step 1: Create accounts, exports, tickets, docs
CREATE TABLE IF NOT EXISTS recipe_sa_accounts (
account_id INTEGER PRIMARY KEY,
email TEXT,
plan TEXT,
created_at TIMESTAMP,
last_login TIMESTAMP
);
CREATE TABLE IF NOT EXISTS recipe_sa_exports (
export_id INTEGER PRIMARY KEY,
account_id INTEGER,
filename TEXT,
status TEXT, -- 'queued' | 'completed' | 'failed'
bytes BIGINT,
started_at TIMESTAMP,
completed_at TIMESTAMP,
error_msg TEXT
);
CREATE TABLE IF NOT EXISTS recipe_sa_tickets (
ticket_id INTEGER PRIMARY KEY,
account_id INTEGER,
subject TEXT,
body TEXT,
opened_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS recipe_sa_docs (
doc_id INTEGER PRIMARY KEY,
title TEXT,
body TEXT,
embedding VECTOR(384)
);
Step 2: Seed
INSERT INTO recipe_sa_accounts VALUES
(1,'alice@example.com','pro', '2025-12-01 09:00:00','2026-05-26 14:33:00'),
(2,'bob@example.com', 'starter', '2026-02-15 10:30:00','2026-05-24 09:11:00'),
(3,'carol@example.com','pro', '2025-06-22 16:45:00','2026-05-22 20:02:00');
INSERT INTO recipe_sa_exports VALUES
(9001,1,'q1-data.csv','completed', 1240000,'2026-05-25 09:00:00','2026-05-25 09:00:42',NULL),
(9002,1,'may-data.csv','completed',2510000,'2026-05-26 11:00:00','2026-05-26 11:01:08',NULL),
(9003,1,'audit.csv','completed', 980000,'2026-05-26 14:30:00','2026-05-26 14:30:31',NULL),
(9004,2,'big-extract.csv','failed', 0, '2026-05-24 09:10:00',NULL,'export size exceeds starter plan limit of 100k rows; upgrade or filter your query'),
(9005,3,'monthly.csv','queued', 0, '2026-05-22 22:00:00',NULL,NULL);
INSERT INTO recipe_sa_tickets VALUES
(4521,1,'Export not arriving','I exported some data this morning but never got an email link. Did it fail?','2026-05-26 14:50:00'),
(4522,2,'Export keeps failing','My exports always fail. What is wrong with the platform?','2026-05-24 09:20:00');
INSERT INTO recipe_sa_docs (doc_id, title, body) VALUES
(1,'Export Delivery','Exports are emailed to the account holder upon completion. Delivery typically takes under 2 minutes from the completion timestamp. If you do not see the email, check spam folders and trusted-sender settings before contacting support.'),
(2,'Export Failures','Export jobs may fail when the result set exceeds the plan limit. Starter plan: 100k rows. Pro: 10M rows. Enterprise: unlimited. Failed exports leave a diagnostic message in the export-status report.'),
(3,'Plan Limits','Plan limits cover storage, API calls, and export size. Limits are listed in your account dashboard. Upgrades take effect immediately and are pro-rated.'),
(4,'Password Reset','Customers can reset passwords from the login page. The reset email arrives within 5 minutes. If not received, check spam, then contact support.'),
(5,'Billing Cycle','Invoices are sent on the first of each month. Plan changes mid-cycle are pro-rated to the day.');
Step 3: Embed
UPDATE recipe_sa_docs SET embedding = EMBED(body);
Step 4: Ground truth — customer state
SELECT account_id, filename, status, completed_at, error_msg
FROM recipe_sa_exports WHERE account_id = 1 ORDER BY started_at DESC LIMIT 5;
Expected: 3 completed exports for Alice on 2026-05-25 and 2026-05-26 — all successful.
Step 5: Ground truth — doc retrieval
SELECT title, COSINE_SIMILARITY(embedding, EMBED('export not arriving by email')) AS sim
FROM recipe_sa_docs ORDER BY sim DESC LIMIT 2;
Expected: Export Delivery ranks first.
Step 6: Triage tickets
SELECT AGENT_RUN(
'aidb-assistant',
'You are tier-1 support. Process ticket 4521 in recipe_sa_tickets. Use execute_query to find the customer''s recent exports and their status. Use rag_search on recipe_sa_docs for the policy. Output: a draft reply to send the customer (warm, specific to their actual state), and a decision: "auto-resolve" or "escalate". Do not invent facts not in the data.'
) AS reply_4521;
SELECT AGENT_RUN(
'aidb-assistant',
'You are tier-1 support. Process ticket 4522 in recipe_sa_tickets. Use execute_query to find this customer''s recent exports — pay attention to status and error messages. Use rag_search on recipe_sa_docs for the policy. Output: a draft reply to send the customer (warm, specific to their actual state), and a decision: "auto-resolve" or "escalate".'
) AS reply_4522;
Expected outcomes:
- Ticket 4521 (Alice): the agent should see 3 successful exports and tell her to check spam — auto-resolve.
- Ticket 4522 (Bob): the agent should see the plan-limit error and recommend upgrading or filtering — likely auto-resolve with a clear next step.
Cleanup
DROP TABLE IF EXISTS recipe_sa_accounts;
DROP TABLE IF EXISTS recipe_sa_exports;
DROP TABLE IF EXISTS recipe_sa_tickets;
DROP TABLE IF EXISTS recipe_sa_docs;
Use it from your agent
- REST/SDK: wrap Step 6 in your ticket-intake pipeline — every new tier-1 ticket gets a triaged draft before a human reads it.
- MCP: call
queryoverws://<host>/mcp?token=<jwt>with the Step-6 SQL. - Why this beats a RAG-only bot: the agent sees the customer's actual rows. The biggest support-bot failure mode is "tell the customer to check spam" when the export actually failed for a real reason — SynapCores eliminates that by giving the agent SQL access to the customer's state.
Key Concepts Learned
- The wedge for agentic support is customer-state grounding — RAG alone can't do it.
- Auto-resolve rate climbs sharply once the agent can read the customer's row.
- One SQL call (
AGENT_RUN) replaces an intake bot + RAG bot + state-lookup service.