MedBridge Sales Ops — Condition Fewshot Skill
Environment
API_BASE_URL=http://34.46.77.124:8002
All task prompts reference API_BASE_URL, BASE_URL, or a localhost placeholder. Always resolve to the remote base above. The API is a read-only shared data source with 12 collections.
API Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /api |
List all collections and endpoints |
| GET | /api/health |
Health check |
| GET | /api/customers |
List all customers |
| GET | /api/customers/<id> |
Single customer |
| GET | /api/products |
List all products |
| GET | /api/products/<code> |
Single product with price tiers |
| GET | /api/quotes |
List all quotes |
| GET | /api/quotes/<id> |
Single quote with line items |
| GET | /api/rfqs |
List all RFQs |
| GET | /api/rfqs/<id> |
Single RFQ with requested modules |
| GET | /api/freight-quotes |
List all freight quotes |
| GET | /api/freight-quotes/<id> |
Single freight quote |
| GET | /api/policies |
List all business policies |
| GET | /api/opportunities |
List all opportunities |
| GET | /api/opportunities/<id> |
Single opportunity with phases |
| GET | /api/invoices |
List all invoices |
| GET | /api/payments |
List all payments |
| GET | /api/revenue-journals |
List all revenue journals |
| GET | /api/events |
List all events |
| GET | /api/vouchers |
List all vouchers |
| GET | /api/search?q=<text> |
Text search across collections |
The API is deterministic (fixed seed per task group). All monetary values are in USD with two decimal places. Dates are ISO 8601 (YYYY-MM-DD).
Task Type 1: Quote Revision with Freight
Trigger: Prompt mentions a quote ID (e.g., Q-TR-WC-1187, Q-TR-LD-5521), a product code, a confirmed quantity, and asks for EXW pricing plus freight comparison.
Step-by-step procedure
Fetch the quote —
GET /api/quotes/<quote_id>. Extractcustomer_id,quote_date,primary_product_code,confirmed_quantity.Fetch the customer —
GET /api/customers/<customer_id>. Determine payment terms frompayment_profile:NET_30_AFTER_PO→ used for recurring NGO and commercial accountsPREPAY_100→ used for new/unapproved clientsMILESTONE_BILLING→ used for implementation services accounts
Fetch the product —
GET /api/products/<product_code>. Match the confirmed quantity to the correct price tier:- Each tier has
min_qty,max_qty(nullable for the top tier),unit_price_usd,lead_time_days. - Select the tier where
min_qty <= confirmed_quantity <= max_qty(treatnullmax_qty as infinity). - Also capture
shelf_life_months.
- Each tier has
Calculate EXW total —
confirmed_quantity × unit_price_usd.Fetch all freight quotes —
GET /api/freight-quotes. Filter to records wherequote_idmatches the current quote. Exclude distractors:- Records whose
iddoesn't follow the expected naming pattern for this quote - Records with status
"stale"whosevalid_untilis before thequote_date— these are still listed but flagged
- Records whose
Process each freight option:
- Use
mode(normalize:"air"→"AIR","sea"→"SEA","road"→"ROAD") freight_cost_usdcomes fromcost_usdtransit_dayscomes fromtransit_days_textvalid_untilis the freight quote expiry- Validity check: If
valid_until < quote_date, the freight is STALE (validity_status: "STALE",source_is_stale: true). Otherwise"VALID",false. - Risk assessment — read
risk_notestext, NOTroute_riskalone:- If
risk_notesmentions "customs" or "border" AND "high" →customs_border_risk: "HIGH" - If
risk_notesmentions "border" AND "medium" →customs_border_risk: "MEDIUM"or use template-specific field likerisk_level: "MEDIUM",risk_flag: "MEDIUM_BORDER_RISK" - If
risk_notesmentions only transit-time, shelf-life, or capacity concerns →customs_border_risk: "LOW"/risk_level: "LOW",risk_flag: "NONE"
- If
- Grand total:
exw_total_usd + freight_cost_usd
- Use
Determine recommended mode — Default to
"SEA"(lowest cost valid option). Override if the only valid options have concerns.Freight reconfirmation — Always
trueper policy POL-FREIGHT-RECONFIRM: "Freight rates need reconfirmation at final order."Policy flags / warnings:
all_freight_options_valid_on_quote_date:trueif every freight option'svalid_until >= quote_dateroad_quote_invalid_or_stale:trueif the ROAD freight is stale or invalidfreight_warning: Compose a warning string mentioning any stale freight and high-risk routesquote_basis:"EXW"for template v1,"EXW_PLUS_FREIGHT_OPTIONS"for template v4customer_policy: Usesegmentfield from customer, uppercased (e.g.,recurring_ngo→"RECURRING_NGO")
Template-specific output notes
Template v1 (train_001 style): Top-level quote_summary with unit_price_usd, lead_time_days, shelf_life_months, quote_basis: "EXW", exw_total_usd. Then freight_options array (always 3: AIR, SEA, ROAD) with risk_level / risk_flag. Then policy_flags with recommended_mode, freight_reconfirmation_required, all_freight_options_valid_on_quote_date, customer_policy, payment_terms.
Template v4 (train_004 style): Top-level pricing with nested catalog_tier object (including min_quantity, max_quantity). Then transport_decisions with freight_options array using validity_status, source_is_stale, customs_border_risk. Then client_warnings with road_quote_invalid_or_stale, freight_warning string, and policy_terms block.
Task Type 2: Indicative RFQ / Module Quote (No Freight)
Trigger: Prompt mentions an RFQ ID (e.g., RFQ-TR-IEHK-204), asks for indicative EXW-only pricing, often mentions a new NGO account or no destination.
Step-by-step procedure
Fetch the RFQ —
GET /api/rfqs/<rfq_id>. Extractcustomer_id,quote_date,requested_modulesarray (each hasproduct_code,quantity).Fetch the customer —
GET /api/customers/<customer_id>. New NGO (is_recurring: false,segment: "new_ngo") →PREPAY_100. Checkcustomer_type: "NGO".Fetch each module product —
GET /api/products/<product_code>for each requested module. Capture:article_numberunit_price_usdfrom price tiers (IEHK modules typically have a single tier withmin_qty: 1, max_qty: null)lead_time_daysshelf_life_months
Calculate line totals —
quantity × unit_price_usdfor each module.Calculate grand total — Sum of all
line_totalvalues.Quote controls:
quote_basis: "EXW_ONLY"— no destination means no freightfreight_excluded: trueoffer_validity_days: 30— per policy POL-QUOTE-VALIDITYwho_documentation_required: true— for IEHK/emergency health kit productspayment_terms:"PREPAY_100"for new NGO clients
Critical rule: Module-level quoting
Per policy POL-MODULE-GRANULARITY, quote at the module level only. Do NOT expand into component SKUs even though the API returns components arrays on products and the RFQ may include component_composition_distractors. The narrative field on the RFQ may explicitly say "do not split into component SKUs" — always respect this.
Task Type 3: Opportunity Reconciliation with Event/Voucher
Trigger: Prompt mentions an opportunity ID (e.g., OPP-TR-HELIOS, OPP-TR-MERIDIAN), a customer, a contact name, and asks for reconciliation of milestones, invoices, payments, revenue recognition, and linked events/vouchers.
Step-by-step procedure
Fetch the opportunity —
GET /api/opportunities/<opportunity_id>. Extract:stage(normalize:"closed_won"→"WON")won_amount_usdcustomer_idcontactnamephasesarray (each hasphase_id,amount_usd,completion_date,invoice_id)
Fetch the customer —
GET /api/customers/<customer_id>. Getname, verify contact.Fetch invoices —
GET /api/invoices. Filter byopportunity_idmatching the current opportunity. Each invoice hasid,amount_usd,status("paid","unpaid","draft","overdue"),due_date,paid_amount_usd,outstanding_amount_usd,phase_id.Fetch payments —
GET /api/payments. Filter byopportunity_id. Cross-reference with invoices viainvoice_id.Fetch revenue journals —
GET /api/revenue-journals. Filter byopportunity_id. Each journal hasphase_id,invoice_id,status,debit_account,credit_account,amount_usd.Fetch events —
GET /api/events. Filter byopportunity_idorcustomer_id. Getid,event_date,status,voucher_code,primary_contact.Fetch vouchers —
GET /api/vouchers. Filter byopportunity_idor match byevent_id. Getcode,discount_percent,max_redemptions,status.
Revenue recognition logic
For each milestone/phase, determine recognition_status by cross-referencing invoice payment state with revenue journal existence:
| Invoice Paid? | Revenue Journal Exists? | Recognition Status |
|---|---|---|
| Yes | Yes | RECOGNIZED |
| Yes | No | MISSING_REVENUE_JOURNAL or REQUIRED_MISSING |
| No | — | NOT_REQUIRED_UNPAID |
Revenue recognition summary:
recognition_status:"COMPLETE_FOR_PAID_MILESTONES"if every paid milestone has a revenue journal;"MISSING_FOR_PAID_MILESTONES"if any paid milestone lacks onerecognized_milestones: array of milestone IDs that are RECOGNIZEDmissing_required_milestones: array of milestone IDs that are PAID but MISSING a revenue journalrecognized_amount: sum of amounts for recognized milestones
Invoice / accounting actions
Identify the primary accounting action:
- If any paid milestone lacks a revenue journal → action is
RECORD_REVENUE_MS2(or whichever milestone ID is missing), with:debit_account: "DEFERRED_REVENUE"credit_account: "IMPLEMENTATION_SERVICES_REVENUE"owner_queue: "ACCOUNTING"amount: the milestone amount
- If all paid milestones are recognized →
VERIFY_REVENUE_ONLYorNO_ACCOUNTING_ACTION
Collection logic
For unpaid invoices with future due_date (relative to the as-of date, typically 2026-06-01):
- Action:
MONITOR_UNPAID_NOT_DUE - Owner:
ACCOUNT_MANAGEMENT
For unpaid invoices with past due_date:
- Action:
COLLECT_UNPAID_MILESTONEorSEND_COLLECTION_NOTICE - Owner:
COLLECTIONS
Event / voucher actions
- If the event is associated with the opportunity and has status
"scheduled"or"confirmed"→ action isSEND_EVENT_INVITATIONorSEND_BRIEFING_INVITE - Voucher values:
discount_amount: thediscount_percentvalue from the voucher (NOT a computed discount; just the percent number itself)max_uses:max_redemptionsfrom the vouchervoucher_status: uppercase the status ("active"→"ACTIVE")
- Invite task owner:
ACCOUNT_MANAGEMENT
Follow-up task construction
Each task object needs:
task_type:"COLLECTION"or"EVENT_INVITATION"task_title: Descriptive title mentioning the action and customer namelinked_customer_id/linked_opportunity_id: from the opportunitycontact_name: from the opportunity or promptdue_datefor collection: from the invoicedue_date; for events: typically 21 days before the event datenext_action: controlled vocabulary per template- Nullable fields (
milestone_id,amount_due,event_id,voucher_code): fill only what's relevant to the task type
Key validations
- Opportunity matches milestones:
won_amount == sum(phase amounts)→true - Outstanding balance: Sum of all unpaid invoice amounts (or
won_amount - total_paid) - Phase total amount: Sum of all phase/milestone amounts
Task Type 4: Engagement Reconciliation (Full Accounting View)
Trigger: Similar to Task Type 3 but uses a different output template with engagement_reconciliation, invoice_actions, and event_actions top-level keys. Often mentions an "as of" date.
Additional template-specific rules
The output structure has three major sections:
engagement_reconciliation:
as_of_date: the current business date (usually2026-06-01unless specified)phase_total_amount: sum of all milestone phase amounts from the opportunitytotal_paid_amount: sum of paid amounts across all invoicesoutstanding_balance:won_amount - total_paid_amountmilestonesarray: ordered ascending by milestone ID (MS1, MS2, MS3...)invoice_state: map invoice status ("paid"→"PAID","unpaid"→"OPEN","draft"→"VOID"/"OPEN")payment_state: map from payment data ("PAID"if payment posted,"UNPAID"if no payment)paid_amount: actual amount paid from the payment record
invoice_actions:
primary_accounting_action: derived from the most critical accounting needcollection_action: derived from whether any unpaid invoices exist and their due datesaccounting_actionnested object with full journal entry detailscollection_tasknested object with collection follow-up details
event_actions:
invite_action:"SEND_BRIEFING_INVITE"for scheduled/confirmed eventsinvite_taskwith action, event_id, voucher_code, owner_queue, contact_name, customer_id
Cross-Cutting Business Rules
Payment terms by customer segment
| Customer Segment | Payment Profile | Terms Code |
|---|---|---|
new_ngo |
NEW_CLIENT_REVIEW |
PREPAY_100 |
recurring_ngo |
NET_30_AFTER_PO |
NET_30_AFTER_PO |
recurring_commercial |
NET_30_AFTER_PO |
NET_30_AFTER_PO |
implementation_services |
MILESTONE_BILLING |
Based on milestone due dates |
Price tier selection
Products have a price_tiers array. Each tier defines a quantity bracket [min_qty, max_qty] with max_qty possibly null (meaning no upper bound). Select the single tier where min_qty <= quantity <= max_qty. Derive unit_price_usd, lead_time_days, and shelf_life_months from the matched tier.
Freight validity staleness
A freight quote is stale when valid_until < quote_date. Stale freight:
- Still listed in the freight options array
- Marked with
validity_status: "STALE",source_is_stale: true - Should trigger a warning in
freight_warning/client_warnings - Should NOT be the recommended mode
Freight distractor detection
The freight-quotes collection may include records linked to the quote but that are distractors:
- Wrong CBM / shipment dimensions compared to the actual product × quantity
- Status
"stale"withvalid_untilfar in the past - Different
destinationorforwardernot matching the quote's known lanes - IDs not matching the expected naming pattern for the quote
Filter by exact quote_id match first, then sanity-check the records.
Risk classification from risk_notes
Do NOT mechanically map route_risk to output risk fields. Instead, read the risk_notes text:
| risk_notes contains | Output risk |
|---|---|
| "customs" or "border" + "high" | "HIGH" |
| "border" + "medium" | "MEDIUM" + flag "MEDIUM_BORDER_RISK" |
| only transit/shelf-life/capacity mentions | "LOW", flag "NONE" |
Revenue recognition account pair
When recording missing revenue:
- Debit:
DEFERRED_REVENUE - Credit:
IMPLEMENTATION_SERVICES_REVENUE
This pair is consistent across all templates.
Offer validity
Standard offer validity is 30 calendar days from quote date (policy POL-QUOTE-VALIDITY). Freight validity may expire sooner.
Controlled value enums
quote_basis: "EXW", "EXW_ONLY", "EXW_PLUS_FREIGHT_OPTIONS"
payment_terms: "NET_30_AFTER_PO", "PREPAY_100"
opportunity_stage / stage: "WON", "OPEN", "LOST"
payment_status / invoice_state: "PAID", "OPEN", "UNPAID", "PARTIAL", "VOID", "UNKNOWN"
recognition_status (milestone): "RECOGNIZED", "MISSING_REVENUE_JOURNAL", "NOT_REQUIRED_UNPAID", "REQUIRED_MISSING"
recognition_status (summary): "COMPLETE_FOR_PAID_MILESTONES", "MISSING_FOR_PAID_MILESTONES", "NOT_REQUIRED"
risk_level / customs_border_risk: "LOW", "MEDIUM", "HIGH"
risk_flag: "NONE", "MEDIUM_BORDER_RISK"
validity_status: "VALID", "STALE"
task_type: "COLLECTION", "EVENT_INVITATION"
next_action / action: "COLLECT_UNPAID_MILESTONE", "SEND_EVENT_INVITATION", "SEND_BRIEFING_INVITE", "MONITOR_UNPAID_NOT_DUE", "RECORD_REVENUE_MS2", "VERIFY_REVENUE_ONLY", "NO_ACCOUNTING_ACTION", "NO_COLLECTION_ACTION"
event_status: "SCHEDULED", "ACTIVE", "COMPLETED", "CANCELLED", "UNKNOWN"
voucher_status: "ACTIVE", "DRAFT", "EXPIRED", "DISABLED", "UNKNOWN"
debit_account / credit_account: "DEFERRED_REVENUE", "IMPLEMENTATION_SERVICES_REVENUE", "ACCOUNTS_RECEIVABLE", "CASH", "NONE"
owner_queue: "ACCOUNTING", "ACCOUNT_MANAGEMENT", "COLLECTIONS", "EVENTS", "NONE"
quote_type: "quote_revision_with_freight", "indicative_module_quote"
Common Pitfalls
Wrong price tier. Always match the confirmed quantity to the correct
min_qty/max_qtybracket. Theprior_unit_price_usdin the quote's line items is the OLD price — the new tier overrides it.Including distractor freight records. Not every freight record with a matching
quote_idbelongs. Checkidnaming patterns,shipment_cbmconsistency, andstatus. The API may include old/stale records from other lanes.Mapping route_risk directly to risk output. The
route_riskfield ("low"/"medium"/"high") is a general indicator. Customs/border risk specifically comes from readingrisk_notes. A SEA shipment withroute_risk: "medium"due to transit time should still havecustoms_border_risk: "LOW".Splitting modules into components. RFQ responses for IEHK-style modules must stay at the module level. The API returns
componentsarrays as medical review information only — do not expand them into line items unless the prompt explicitly requests component-level pricing.Missing freight reconfirmation flag. Per policy POL-FREIGHT-RECONFIRM, every freight-inclusive quote needs
freight_reconfirmation_required: true. This is not conditional.Confusing EXW and EXW_ONLY.
"EXW"means the quote includes freight options alongside EXW pricing."EXW_ONLY"means freight is excluded entirely (no destination). Don't mix them.Revenue recognition gaps. A milestone that is PAID but has no matching revenue journal entry is
MISSING_REVENUE_JOURNAL— this drives the primary accounting action. An UNPAID milestone is alwaysNOT_REQUIRED_UNPAIDregardless of journal existence.Voucher discount_amount confusion. The
discount_percentfrom the voucher API is output asdiscount_amountin the response, but it's the raw percent number (e.g., 50, 100), not a calculated discount value. The field name in the template saysdiscount_amountbut it carries the percent.Event due dates. The due_date for an event invitation task is typically set to 21 days before the event date (e.g., event on 2026-07-22 → due 2026-07-01). Collection task due dates come from the invoice
due_dateor the opportunity phasecompletion_dateplus an offset.Currency and number format. All USD amounts use exactly two decimal places (
42480.00, not42480). Usenullfor optional date/number fields when no value exists, not empty strings or zero.
Response Format
Return only valid JSON matching the provided answer_template.json. No markdown fences, no explanatory text outside the JSON. Use the exact field names, nesting structure, and controlled vocabulary values from the template.
Always resolve entity IDs from API data rather than hardcoding. All monetary fields are numbers (not strings). All dates are ISO 8601 strings. Boolean fields use true/false (not strings).