diff --git a/flexus_simple_bots/karen/karen_bot.py b/flexus_simple_bots/karen/karen_bot.py index af3d2e68..77e0d4e3 100644 --- a/flexus_simple_bots/karen/karen_bot.py +++ b/flexus_simple_bots/karen/karen_bot.py @@ -174,6 +174,17 @@ "what_people_asked": {"type": "string", "order": 2, "title": "What People Asked"}, }, }, + "section04-resolution-summary": { + "type": "object", + "title": "Resolution Outcomes", + "properties": { + "resolved_success": {"type": "integer", "order": 0, "title": "Resolved: Success"}, + "resolved_fail": {"type": "integer", "order": 1, "title": "Resolved: Fail"}, + "resolved_inconclusive": {"type": "integer", "order": 2, "title": "Resolved: Inconclusive"}, + "resolved_escalated": {"type": "integer", "order": 3, "title": "Resolved: Escalated"}, + "sentiment_notes": {"type": "string", "order": 4, "title": "Sentiment Notes"}, + }, + }, } REPORT_TOOL = ckit_cloudtool.CloudTool( @@ -335,6 +346,13 @@ async def handle_report( refunds = await ckit_erp.erp_table_data(http, "com_refund", ws_id, erp_schema.ComRefund, filters=f"refund_created_ts:>=:{ts0}", limit=1000) refund_amount = float(sum(r.refund_amount for r in refunds)) + all_tasks = await ckit_kanban.bot_get_all_tasks(http, pid) + done_tasks = [t for t in all_tasks if t.ktask_done_ts >= ts0] + by_code = {} + for t in done_tasks: + c = (t.ktask_resolution_code or "UNKNOWN").upper() + by_code[c] = by_code.get(c, 0) + 1 + data = { "section01-crm": { "new_contacts": len(new_contacts), @@ -358,6 +376,13 @@ async def handle_report( "setup_problems": "", "what_people_asked": "", }, + "section04-resolution-summary": { + "resolved_success": by_code.get("SUCCESS", 0), + "resolved_fail": by_code.get("FAIL", 0), + "resolved_inconclusive": by_code.get("INCONCLUSIVE", 0), + "resolved_escalated": by_code.get("ESCALATED", 0), + "sentiment_notes": "", + }, } date_str = now.strftime("%Y%m%d") @@ -377,7 +402,9 @@ async def handle_report( return ( "✍️ %s\nmd5=%s\n\n%s\n\n" - "Task stats (section02-tasks) are zero β€” fill them using your kanban search tool. Then fill in notes. Use flexus_policy_document(op=\"update_at_location\", " + "Task stats (section02-tasks) are zero β€” fill them using your kanban search tool. " + "Resolution outcomes (section04-resolution-summary) are pre-filled from resolution codes; add sentiment_notes if patterns stand out. " + "Then fill in notes. Use flexus_policy_document(op=\"update_at_location\", " "args={\"p\": \"%s\", \"expected_md5\": \"%s\", \"updates\": [[\"karen-report.section02-tasks.tasks_completed\", ...], ...]})" ) % (path, result.md5_after, doc_text, path, result.md5_after) diff --git a/flexus_simple_bots/karen/very_limited__support_ecommerce_fashion.yaml b/flexus_simple_bots/karen/very_limited__support_ecommerce_fashion.yaml new file mode 100644 index 00000000..322de704 --- /dev/null +++ b/flexus_simple_bots/karen/very_limited__support_ecommerce_fashion.yaml @@ -0,0 +1,240 @@ +judge_instructions: | + Fashion e-commerce support scenario. Tests accurate KB retrieval across + multiple policy sections (sizing, returns, international shipping, exchanges). + Score 0 if no flexus_vector_search calls. Penalize fabricated shipping costs, + delivery timelines, or return windows not grounded in search results or + /support/summary. Penalize if assistant invents a specific carrier or customs + fee that wasn't in the KB. Reward precise answers that cite policy details. + +messages: +- role: cd_instruction + content: |- + πŸ“„/company/summary + { + "stage": "Growth", + "mission": "Scandinavian workwear designed for creative professionals", + "tagline": "Dress sharp, work sharper", + "website": "https://nordicthread.com", + "industry": "E-commerce / Fashion / Workwear", + "company_name": "Nordic Thread" + } + + πŸ“„/company/sales-strategy + does not exist yet + + πŸ“„/support/summary + { + "support-policy": { + "meta": { + "created_at": "2026-03-25T14:00:00.000000+00:00" + }, + "section01-product": { + "title": "Product", + "question01-description": { + "a": "Nordic Thread sells Scandinavian-designed workwear for creative professionals β€” architects, designers, agency people. Premium fabrics, minimalist cuts, designed for office-to-meeting versatility. All items designed in Stockholm, manufactured in Portugal.", + "q": "What is the product?" + }, + "question02-features": { + "a": "Men's and women's collections. Core lines: The Studio Blazer, The Draft Trouser, The Pitch Shirt, The Commute Jacket. All wrinkle-resistant. Sizing: EU standard (XS-XXL), detailed size guide on each product page with measurements in cm. Custom hemming available on trousers (free, adds 5 business days).", + "q": "What are the key features?" + }, + "question03-ideal-customer-profile": { + "a": "Creative professionals 25-45 who want polished workwear without corporate stiffness. Architects, UX designers, agency founders, creative directors.", + "q": "Who is the ideal customer (ICP)?" + } + }, + "section02-future-ops": { + "title": "Shipping & Returns", + "question01-shipping": { + "a": "EU: free shipping over €100, otherwise €7.50. Standard delivery 3-5 business days. Express (€12) 1-2 business days. International (non-EU): €15 flat rate, 7-14 business days. Customs/duties are buyer's responsibility. We ship via PostNord (Nordics), DHL (EU), and DHL Express (international).", + "q": "Shipping methods, costs, times?" + }, + "question04-payments": { + "a": "Visa, Mastercard, Klarna (pay in 3), PayPal. All prices in EUR. Currency conversion by payment provider.", + "q": "Payment options & pricing?" + }, + "question02-returns": { + "a": "30-day return window from delivery date. Items must be unworn, tags attached. Free returns within EU (prepaid label in box). International returns: customer pays shipping. Refund processed within 5 business days of receiving the return. Exchanges: same 30-day window, we ship the replacement once we receive the original β€” no cross-shipping.", + "q": "Refund policy?" + }, + "question03-warranty": { + "a": "12-month warranty on manufacturing defects (seam failure, zipper breaks, fabric pilling within normal use). Send photo + order number to support for assessment. If confirmed, free replacement or store credit.", + "q": "Warranty details?" + } + }, + "section03-support": { + "title": "Support", + "question01-channels": { + "a": "Telegram @nordicthread_support, email hello@nordicthread.com", + "q": "Support channels (email, chat, etc.)?" + }, + "question02-escalation": { + "a": "Lost shipments, warranty claims, orders over €500, corporate/bulk orders", + "q": "When to escalate to human?" + } + }, + "section04-restrictions": { + "title": "Restrictions", + "question01-never-say": { + "a": "Never estimate customs fees for international orders. Never promise specific delivery dates, only windows. Never offer discounts without manager approval.", + "q": "What should support NEVER say?" + } + } + } + } +- role: user + content: |- + Telegram private user='Aisha Nakamura' chat_id=77293651 + hi, I'm in Tokyo and want to order the Studio Blazer. I normally wear US size 6 β€” what EU size is that? also what's the return situation for international orders if it doesn't fit? +- role: assistant + tool_calls: + - id: call_fg_01 + type: function + function: + name: flexus_kanban_public + arguments: '{"op": "status_public", "search": null, "resolution": null, "details_json": null, "restart_summary": null}' +- role: tool + content: | + The current task with details: + { + "id": "rN3kX7wQmL", + "title": "Telegram private user='Aisha Nakamura' chat_id=77293651\nhi, I'm in Tokyo and want to order the Studio Blazer...", + "details": { + "chat_id": 77293651, + "chat_type": "private", + "message_id": 3401, + "attachments": [], + "message_text": "hi, I'm in Tokyo and want to order the Studio Blazer. I normally wear US size 6 β€” what EU size is that? also what's the return situation for international orders if it doesn't fit?", + "message_author_id": 77293651, + "message_author_name": "Aisha Nakamura" + } + } + + Inbox: + [ + ] + + In Progress: + [ + {"id": "rN3kX7wQmL", "title": "Telegram private user='Aisha Nakamura' chat_id=77293651\nhi, I'm in Tokyo and want to order the Studio Blazer...", "human": "telegram:77293651"}, + ] + + Done: + [ + ] + call_id: call_fg_01 +- role: title + content: "[telegram] [aisha] [support] Aisha Nakamura β€” Tokyo, Studio Blazer sizing + international returns" +- role: assistant + tool_calls: + - id: call_fg_02 + type: function + function: + name: telegram + arguments: '{"op": "capture", "args": {"chat_id": 77293651}}' +- role: tool + content: | + πŸ“ŒCAPTURED + + The next thing you write will be visible. Don't comment on that fact and think about what do you want to say in '77293651'. + Don't use op=post because now anything you say is visible automatically. + + Reminder: after this point telegram MarkdownV2 markup rules are in effect for your output, there are no tables! Here's markup help for you again. + + + Telegram uses MarkdownV2 markup: + *bold* _italic_ __underline__ ~strikethrough~ + `inline code` + ```python + code block + ``` + [link text](https://example.com) + ||spoiler|| + + > blockquote + > each line must start with > + + No bullet lists or tables. + call_id: call_fg_02 +- role: assistant + tool_calls: + - id: call_fg_03 + type: function + function: + name: flexus_vector_search + arguments: '{"eds": "", "query": "EU sizing size guide US conversion Studio Blazer international returns shipping"}' +- role: tool + content: |+ + For your query 'EU sizing size guide US conversion Studio Blazer international returns shipping' found 3 results in database of 620 chunks across 15 indexed documents. + + + Size conversion guide (women's tops/blazers): US 2 = EU XS (34), US 4 = EU S (36), US 6 = EU S/M (38), US 8 = EU M (40), US 10 = EU L (42), US 12 = EU XL (44). Each product page has a detailed size chart with bust, waist, and sleeve measurements in cm. When between sizes, we recommend sizing up β€” our cuts are slim. + + + + International (non-EU) returns: 30-day return window from delivery date. Items must be unworn with tags attached. Customer pays return shipping. Refund processed within 5 business days of receiving the item. We recommend using a tracked shipping service. No cross-shipping on exchanges β€” we ship the replacement once the original is received. + + + + International (non-EU) shipping: €15 flat rate, 7-14 business days via DHL Express. Customs duties and import taxes are the buyer's responsibility and vary by country. + + + call_id: call_fg_03 +- role: assistant + content: |- + Hi Aisha\. US 6 maps to EU S/M \(38\) for women's blazers\. The Studio Blazer runs slim β€” if you're between sizes, I'd go up to M \(40\)\. Each product page has exact bust, waist, and sleeve measurements in cm so you can compare\. + + International returns from Japan: 30\-day window from delivery, unworn with tags\. You'd pay return shipping \(tracked service recommended\)\. Refund hits within 5 business days after we receive it\. + + For exchanges: same 30\-day window, but we ship the new size only after receiving the original β€” no cross\-shipping\. + + Shipping to Tokyo is €15 flat, 7\-14 business days via DHL Express\. Customs and import duties are on your side β€” I can't estimate those for Japan\. +- role: user + content: + - m_type: text + m_content: |- + πŸ‘€Aisha Nakamura + + ok got it. can I do the exchange for free if it's the wrong size? and do you accept Klarna from Japan? +- role: assistant + tool_calls: + - id: call_fg_04 + type: function + function: + name: flexus_vector_search + arguments: '{"eds": "", "query": "exchange shipping cost free Klarna international payment availability"}' +- role: tool + content: |+ + For your query 'exchange shipping cost free Klarna international payment availability' found 2 results in database of 620 chunks across 15 indexed documents. + + + Klarna (pay in 3 installments) is available for EU customers only. International customers can pay with Visa, Mastercard, or PayPal. + + + + Free returns within EU (prepaid label included in the box). International returns: customer pays shipping both ways β€” return of the original and we cover shipping of the replacement at the standard international rate (€15). + + + call_id: call_fg_04 +- role: assistant + content: |- + Exchange shipping: you'd pay to send back the original, then we ship the replacement at the standard €15 international rate\. So return shipping is on you, outbound replacement is €15\. + + Klarna: EU only, unfortunately\. From Japan you can use Visa, Mastercard, or PayPal\. + + Want to go ahead with the order? +- role: assistant + tool_calls: + - id: call_fg_05 + type: function + function: + name: flexus_kanban_public + arguments: '{"op": "resolve", "resolution": {"code": "SUCCESS", "summary": "Helped Aisha (Tokyo) with Studio Blazer sizing (US 6 β†’ EU 38/S-M, recommended sizing up), international return policy (30 days, customer pays shipping, no cross-ship exchanges), Klarna unavailable outside EU, payment alternatives.", "humanhours": 0.15, "uncapture": true, "pdoc_paths": []}}' +- role: tool + content: |- + Moved to done rN3kX7wQmL + + Uncaptured the chat, no one can see your messages now, all left to do is to say TASK_COMPLETED + call_id: call_fg_05 +- role: assistant + content: TASK_COMPLETED diff --git a/flexus_simple_bots/karen/very_limited__support_fitness_saas.yaml b/flexus_simple_bots/karen/very_limited__support_fitness_saas.yaml new file mode 100644 index 00000000..07413f8e --- /dev/null +++ b/flexus_simple_bots/karen/very_limited__support_fitness_saas.yaml @@ -0,0 +1,229 @@ +judge_instructions: | + B2B fitness studio management SaaS support scenario. Tests KB grounding, + direct factual answers, and no upselling. Score 0 if no flexus_vector_search + calls. Penalize fabricated features, pricing, or integration details not + present in search results or /support/summary. Penalize upselling or pushing + a higher plan when user didn't ask. Reward concise, grounded answers. + +messages: +- role: cd_instruction + content: |- + πŸ“„/company/summary + { + "stage": "Growth", + "mission": "Help fitness studios run their business from one screen", + "tagline": "Studio management, simplified", + "website": "https://fitrunner.io", + "industry": "B2B SaaS / Fitness Studio Management", + "company_name": "FitRunner" + } + + πŸ“„/company/sales-strategy + does not exist yet + + πŸ“„/support/summary + { + "support-policy": { + "meta": { + "created_at": "2026-04-01T09:00:00.000000+00:00" + }, + "section01-product": { + "title": "Product", + "question01-description": { + "a": "FitRunner is a cloud platform for fitness studios. Manages class scheduling, member check-ins, billing, instructor payroll, and retention campaigns. Replaces Mindbody/Glofox for studios that want simpler software without enterprise complexity.", + "q": "What is the product?" + }, + "question02-features": { + "a": "Class scheduling with waitlists, member app (iOS/Android), automated billing via Stripe, instructor availability and sub management, attendance tracking, retention alerts (members inactive >14 days), basic reporting dashboard, Zapier integration.", + "q": "What are the key features?" + }, + "question03-ideal-customer-profile": { + "a": "Independent fitness studios, yoga studios, CrossFit boxes, Pilates studios. 1-5 locations, 200-2000 active members. Currently using spreadsheets, Mindbody, or Glofox and frustrated with cost or complexity.", + "q": "Who is the ideal customer (ICP)?" + } + }, + "section02-future-ops": { + "title": "Billing & Plans", + "question01-shipping": { + "a": "", + "q": "Shipping methods, costs, times?" + }, + "question04-payments": { + "a": "Starter: $49/mo (1 location, up to 500 members). Growth: $99/mo (up to 3 locations, 2000 members, Zapier). Enterprise: custom. Annual billing: 2 months free. All plans include member app.", + "q": "Payment options & pricing?" + }, + "question02-returns": { + "a": "14-day free trial. Monthly plans cancel anytime, no refunds on partial months. Annual contracts refundable pro-rata within first 60 days.", + "q": "Refund policy?" + }, + "question03-warranty": { + "a": "", + "q": "Warranty details?" + } + }, + "section03-support": { + "title": "Support", + "question01-channels": { + "a": "Telegram @fitrunner_support, email help@fitrunner.io, in-app chat", + "q": "Support channels (email, chat, etc.)?" + }, + "question02-escalation": { + "a": "Billing disputes, data migration from Mindbody/Glofox, Stripe account issues, multi-location setup", + "q": "When to escalate to human?" + } + }, + "section04-restrictions": { + "title": "Restrictions", + "question01-never-say": { + "a": "Never promise specific integrations beyond what's listed. Never guarantee data migration timelines without human review. Never share other studios' data or revenue numbers.", + "q": "What should support NEVER say?" + } + } + } + } +- role: user + content: |- + Telegram private user='Marco Diaz' chat_id=55812340 + hey, we run a CrossFit box and just switched to FitRunner. can i connect our scheduling with Google Calendar so coaches see their classes there? also how does the waitlist thing work? +- role: assistant + tool_calls: + - id: call_fg_01 + type: function + function: + name: flexus_kanban_public + arguments: '{"op": "status_public", "search": null, "resolution": null, "details_json": null, "restart_summary": null}' +- role: tool + content: | + The current task with details: + { + "id": "kT5mW2pRnX", + "title": "Telegram private user='Marco Diaz' chat_id=55812340\nhey, we run a CrossFit box...", + "details": { + "chat_id": 55812340, + "chat_type": "private", + "message_id": 8801, + "attachments": [], + "message_text": "hey, we run a CrossFit box and just switched to FitRunner. can i connect our scheduling with Google Calendar so coaches see their classes there? also how does the waitlist thing work?", + "message_author_id": 55812340, + "message_author_name": "Marco Diaz" + } + } + + Inbox: + [ + ] + + In Progress: + [ + {"id": "kT5mW2pRnX", "title": "Telegram private user='Marco Diaz' chat_id=55812340\nhey, we run a CrossFit box...", "human": "telegram:55812340"}, + ] + + Done: + [ + ] + call_id: call_fg_01 +- role: title + content: "[telegram] [marco] [support] Marco Diaz β€” CrossFit box, Google Calendar + waitlist questions" +- role: assistant + tool_calls: + - id: call_fg_02 + type: function + function: + name: telegram + arguments: '{"op": "capture", "args": {"chat_id": 55812340}}' +- role: tool + content: | + πŸ“ŒCAPTURED + + The next thing you write will be visible. Don't comment on that fact and think about what do you want to say in '55812340'. + Don't use op=post because now anything you say is visible automatically. + + Reminder: after this point telegram MarkdownV2 markup rules are in effect for your output, there are no tables! Here's markup help for you again. + + + Telegram uses MarkdownV2 markup: + *bold* _italic_ __underline__ ~strikethrough~ + `inline code` + ```python + code block + ``` + [link text](https://example.com) + ||spoiler|| + + > blockquote + > each line must start with > + + No bullet lists or tables. + call_id: call_fg_02 +- role: assistant + tool_calls: + - id: call_fg_03 + type: function + function: + name: flexus_vector_search + arguments: '{"eds": "", "query": "Google Calendar integration scheduling waitlist class management"}' +- role: tool + content: |+ + For your query 'Google Calendar integration scheduling waitlist class management' found 3 results in database of 950 chunks across 22 indexed documents. + + + FitRunner syncs class schedules to Google Calendar via Zapier. Set up a Zap: trigger = "New Class Created", action = "Google Calendar Create Event". Coaches add the FitRunner Zapier calendar and see all assigned classes. Two-way sync is not supported β€” changes must be made in FitRunner. + + + + Waitlist: when a class reaches max capacity, members can join the waitlist from the app. When a spot opens (cancellation or no-show after 15min), the next person on the waitlist gets a push notification and has 30 minutes to confirm. If they don't confirm, it moves to the next person. Studio owner can set max waitlist size per class (default: 5). + + + call_id: call_fg_03 +- role: assistant + content: |- + Hey Marco\. Google Calendar β€” yes, it works through Zapier\. You set up a Zap with trigger "New Class Created" β†’ Google Calendar "Create Event"\. Coaches subscribe to that calendar and see their classes\. One caveat: it's one\-way, so schedule changes need to be made in FitRunner\. + + Waitlist: when a class hits max capacity, members tap "join waitlist" in the app\. If someone cancels or no\-shows \(15min grace\), next person gets a push notification and has 30 minutes to confirm\. Default max waitlist is 5 per class β€” you can change that in class settings\. + + Need help setting up the Zapier connection? +- role: user + content: + - m_type: text + m_content: |- + πŸ‘€Marco Diaz + + nice, that works. one more thing β€” a few members are complaining they got double-charged this month. how do I check that? +- role: assistant + tool_calls: + - id: call_fg_04 + type: function + function: + name: flexus_vector_search + arguments: '{"eds": "", "query": "double charge billing dispute member payment Stripe refund"}' +- role: tool + content: |+ + For your query 'double charge billing dispute member payment Stripe refund' found 2 results in database of 950 chunks across 22 indexed documents. + + + Billing issues: FitRunner processes payments through Stripe. To check a member's payment history, go to Members β†’ select member β†’ Billing tab. Shows all charges, failed payments, and refunds. For suspected double charges, cross-reference with your Stripe dashboard (Settings β†’ Stripe Integration β†’ "Open Stripe Dashboard"). If confirmed, issue a refund from Stripe directly β€” it will sync back to FitRunner within 1 hour. + + + call_id: call_fg_04 +- role: assistant + content: |- + Go to Members β†’ pick the member β†’ Billing tab\. That shows all charges, failed payments, and refunds\. Compare with your Stripe dashboard \(Settings β†’ Stripe Integration β†’ "Open Stripe Dashboard"\)\. + + If you see a genuine double charge, refund directly from Stripe β€” it syncs back to FitRunner within an hour\. + + If it's affecting multiple members, that's worth escalating to our team so we can check if there's a billing bug\. Want me to flag it? +- role: assistant + tool_calls: + - id: call_fg_05 + type: function + function: + name: flexus_kanban_public + arguments: '{"op": "resolve", "resolution": {"code": "SUCCESS", "summary": "Answered Marco (CrossFit box owner) on Telegram: Google Calendar sync via Zapier (one-way), waitlist mechanics (push notification, 30min confirm window, configurable max), and billing double-charge troubleshooting via Members > Billing tab + Stripe dashboard.", "humanhours": 0.15, "uncapture": true, "pdoc_paths": []}}' +- role: tool + content: |- + Moved to done kT5mW2pRnX + + Uncaptured the chat, no one can see your messages now, all left to do is to say TASK_COMPLETED + call_id: call_fg_05 +- role: assistant + content: TASK_COMPLETED