Send a message to the AI athlete assistant
Send a chat message to the AI assistant. The public request and two-item athlete/assistant response envelope are unchanged across both server-selected execution paths. *
- Loop dispatch and rollback: After the global feature gate, athlete allowlist, request validation, idempotent replay lookup, and conversation lifecycle checks, the server-side
AI_ATHLETE_ASSISTANT_LOOP_ENABLEDflag selects the implementation. When enabled (the development default), messages use the bounded tool loop. Duplicateclient_message_idexecution remains serialized for longer than the bounded outbound request plus persistence and delivery side effects. When disabled, the existing v3 semantic-resolution and answer path remains available as a server-side rollback. The flag is operational configuration and is never accepted from the client. - Loop routing: Free text, exact server-rendered quick-button labels, and ordinal references are interpreted by the loop through its authorized tool surface. A complete legacy
scope=deal/deal_type/job_idtuple is still parsed, authorized, and logged for compatibility, but it does not choose the loop’s route or bypass tool authorization. Invalid or unauthorized complete tuples are rejected without numeric coercion. - Deterministic loop fast paths: Explicit MOGL Support requests and reviewed safe no-deal knowledge questions may return the same strict loop result without model or tool calls. All other loop turns use bounded model/tool budgets. Public source IDs are filtered to successful current-turn evidence; malformed or contradictory loop results fail closed rather than exposing untrusted data.
- Loop portfolio parity: A fresh unqualified portfolio request is normalized to all lifecycles, the
allsegment, and offset zero. Overview output is grouped from canonical server counts across current and historical deals; count output uses the canonical requested-segment total rather than page length. List output preserves backend order and renders each deal once. Lists of three or fewer deals may include next-deliverable and next-action detail, while lists of four or more remain compact. Multiple actions compose in the fixed overview, count, list, guidance order. Athlete-facing active, open, current, and high-level in-progress requests usework_remaining(in_progress+resubmit_needed). Legacyactiveremains a deprecated compatibility count. Thevoidedsegment includes fully voided deals plus partial-void conditions; exclusivesummary_counts.voidedcounts fully voided deals only. - V3 rollback semantic routing and answer rendering: When the loop flag is disabled, the AI service owns free-text interpretation and returns an advisory typed resolution. Laravel validates the complete resolution shape, enforces confidence and authorization against backend-supplied candidates, verifies referenced-turn metadata, derives trusted continuity values, and reloads current authorized facts. The AI answer stage then renders the athlete response from that validated resolution and bounded current data. Raw model proposals are never exposed as public
context_resolution. - V3 rollback mechanical fast paths: An authorized complete structured deal hint, an explicit
portfolio_cursor, an exact server-rendered deal label, or an ordinal reference to a server-rendered deal list bypasses v3 free-text semantic interpretation. Structured hints support both partner jobs and athlete-owned fan requests; Laravel authorizes the referenced record before routing. Partial legacy fields are logged and discarded so the normalized request proceeds through v3 semantic routing. - V3 rollback safe fallback: Malformed, incomplete, unsupported, low-confidence, stale, or unauthorized semantic proposals become a generic clarification instead of selecting a guessed deal or status.
- Conversation handling:
conversation_idis the canonical conversation identifier.session_idis accepted as a backwards-compatible alias. If neither is supplied, or the supplied conversation cannot be reused, the server creates a new conversation. - V3 rollback fresh and anchored portfolio routing: A fresh portfolio request returns
resolution_reason=portfolio_query, starts at offset zero, and has noreferenced_turn_idorreferenced_count; Laravel builds it from current authorized data. A status/count follow-up returnsportfolio_follow_uponly afterreferenced_turn_idmatches a bounded assistant turn; Laravel reloads that turn’s server-ownedportfolio_groups, derivesreferenced_count, and compares it with the current authorized total to producecount_mismatch. A naturalportfolio_continuationmust anchor a bounded assistant turn containing a valid server-owned continuation cursor. An explicitportfolio_cursoris separately validated as a mechanical continuation request. Continuation cursors apply only to truncated portfolio lists, not to oversized deal-ambiguity results, and do not promise that an arbitrary text list can be continued. - V3 rollback routing clarification: Ambiguous status references return
resolution_reason=ambiguous,clarification_segments,choice_count=0, no deal quick buttons, and noclarification_draft. Ambiguous deal references expose no raw choices, but may return two or three authorized, ID-suffixed deal labels as quick buttons withchoice_countset to the full hidden choice count. More than three deal matches are rendered as a text-only bounded list without a continuation promise. Athlete-facing copy uses deal-status language rather than internal continuity metadata names. - V3 rollback assistant help:
portfolio_statuses,mogl_overview,support_contact, andknowledge_lookuproute ascontext_mode=assistant_helpwith a validatedhelp_topic. Canonical assistant-help proposals and enforced responses have no requested or resolved deal ID, deal type, portfolio metadata, history anchor, or clarification metadata; public array fields such asresolved_job_ids,requested_actions, andclarification_segmentsremain non-null empty arrays. - Quick buttons and proactive continuity: Loop turns always return
quick_button_suggestions=[]. On the v3 rollback path, athlete-prompted responses remain empty except for the backend-owned ambiguous-deal routing clarification described above. Availability confirmation may persist a proactive welcome turn with the server-owned originating standard job and the labelsTell me about the dealandRough schedule please. The labels express intent only and never carry identity authority. Bounded history projects the originating job as trustedselected_deal_id; the loop may inherit it only from that assistant history, and everyget_deal/get_timelinecall reauthorizes it. Detail uses current deal evidence; rough schedule uses current timeline evidence and athlete-local display dates. Missing, fan-scoped, malformed, or ambiguous continuity clarifies instead of silently selecting a job. Future routing replacements must preserve ENG-1180/ENG-1181 same-intent behavior. - Hybrid answer contract (jobs only): In the answer stage,
direct_answer_with_clarificationreturns both a factual answer and a persisted brand-message draft, and draft-bearing job responses return a non-nullclarification_draftwith no quick buttons. Brand draft text is validated natural brand-facing copy; machine-only clarification reasons/topics remain tracing metadata and known internal namespaces are repaired or rejected before persistence. A backend-owned routing clarification is the exception: it may useresponse_type=clarificationbut returnsclarification_draft=nulland may expose bounded deal-choice buttons. - Contact support: Existing job-scoped support remains supported. A no-deal support request uses
assistant_help/support_contact, returnsjob_id=nullandresolved_job_ids=[], and may returnresponse_type=escalation, a sanitizedsupport_request_summary, and a review-onlysupport_actionmailto. The athlete must click, review, and send the email; the backend never sends it automatically. For example, “Please contact MOGL support about my payout” can return an escalation with the summary “The athlete needs help resolving a payout issue.” and no deal metadata. - Knowledge lookup: A safe no-deal KB question uses
assistant_help/knowledge_lookupand returns a direct curated answer with itsathlete_kb:*source IDs. It hasjob_id=null,resolved_job_ids=[], no support summary/action, no clarification draft, and no quick buttons. For example, “What is MOGL?” can return a direct MOGL overview sourced byathlete_kb:what-is-mogl. - Access control: Athlete must be allowlisted. Portfolio data is rebuilt from the authenticated athlete’s authorized jobs. Job-scoped questions require a non-cancelled application. Fan requests require ownership (
fan_request_service.athlete_id). Returns 403 otherwise.
Authorizations
JWT Bearer token authentication. Use the /api/login endpoint to obtain a token.
Body
The athlete's message to the assistant (max 2000 characters).
2000"Which 3 am I waiting on payment for?"
Legacy compatibility discriminator. With allowlisted deal_type and a strictly integral positive job_id it forms a complete tuple. The tuple is authorized and logged on both paths; it routes only the v3 rollback path and does not direct loop tool selection. Partial tuples are logged and discarded.
athlete, deal "deal"
Legacy tuple type: job references a partner job and fan_req references an athlete-owned, non-deleted fan service request. The complete tuple routes only v3; the loop resolves the message through authorized tools.
job, fan_req "job"
Polymorphic legacy tuple ID: partner_jobs.id for job or fan_request_service.id for fan_req. Laravel authorizes and logs complete tuples on both paths, rejects invalid or unauthorized values, and never truncates decimal or floating-point values. The value does not direct loop routing.
x >= 142
Canonical ID of an existing conversation to continue.
255"550e8400-e29b-41d4-a716-446655440000"
Backwards-compatible alias for conversation_id.
255"550e8400-e29b-41d4-a716-446655440000"
Idempotency key required for modern requests. Optional only for legacy payloads that include a non-null deal_type or job_id.
64"8dc1b7b7-716e-4f26-b4fa-cc9c8d300c18"
Opaque v3 compatibility cursor from a truncated portfolio list. On the v3 rollback path it bypasses free-text semantic routing only after Laravel validates and decodes it. Loop turns resolve the message through the tool loop and do not promise cursor continuation for arbitrary lists.
512Response
Message sent. Returns the unchanged two-item envelope containing the athlete message and assistant reply. The assistant item may include either a historical/v3 semantic context_resolution or a loop-1 trace context_resolution; top-level compatibility fields remain available in both cases. Loop-1 portfolio turns may persist optional strict compact portfolio_state metadata inside context_resolution for trusted continuity, without exposing raw tool arguments or full results. No-deal support replies may include a sanitized support_request_summary and review-only support_action. Safe knowledge replies contain curated text/source IDs and omit support actions, drafts, and buttons.