AI Trainer Integration
Overview
The AI Personal Trainer is a guided chat experience that walks the user through a personalized session: profile setup → readiness assessment → workout → check-in → scheduling the next session.
Your app only needs to mount the trainer view, optionally pre-fill demographic data, and listen for the events below — most importantly trainer_schedule_next_workout, which fires when the user picks a date/time for their next session and is the trigger for your reminder logic.
Requirements
Camera permission, an internet connection, and a recent SDK that supports the Trainer Chat integration:
| Platform | Minimum SDK |
| React Native | kinestex-sdk-react-native ≥ 1.2.9 |
| Flutter | kinestex_sdk_flutter ≥ 1.4.7 |
| React TS (Web) | kinestex-sdk-react-ts ≥ 0.0.3 |
| HTML & JS | iframe at https://ai.kinestex.com (HTTPS host page required) |
If you haven't installed the SDK yet, follow the installation guide first — only trainer-specific concerns are covered below.
Launching the Trainer
Mount the trainer with the AI_TRAINER_CHAT integration option (or, on Flutter, call createTrainerChatView). The trainer flow is rendered entirely inside the SDK.
1import KinestexSDK from "kinestex-sdk-react-native";
2import { IPostData, IntegrationOption } from "kinestex-sdk-react-native/src/types";
3
4const postData: IPostData = {
5 key: "<YOUR_API_KEY>",
6 company: "<YOUR_COMPANY>",
7 userId: "<USER_ID>",
8 style: { style: "dark" },
9};
10
11<KinestexSDK
12 data={postData}
13 integrationOption={IntegrationOption.AI_TRAINER_CHAT}
14 handleMessage={handleMessage}
15/>Pre-filling user data
The trainer asks profile questions on first use. You can skip the basic demographics by passing them when you mount the SDK — anything you omit, the trainer will simply ask for.
| Field | Unit / Allowed values |
age | years |
height | cm (UI lets users switch to imperial after) |
weight | kg |
gender | "male" or "female" |
Don't pass empty strings or zero — omit the field instead. On Flutter the UserDetails constructor requires all fields, so either pass the complete object or skip the user: parameter entirely.
1const postData: IPostData = {
2 key: "<YOUR_API_KEY>",
3 company: "<YOUR_COMPANY>",
4 userId: "<USER_ID>",
5 age: 32,
6 height: 178, // cm
7 weight: 76, // kg
8 gender: "male",
9 style: { style: "dark" },
10};Handling messages
The trainer emits the standard SDK events plus two trainer-specific ones:
workout_exit_request— the user exited a workout that was launched from the trainer.trainer_schedule_next_workout— the user picked a date/time for their next session (see below).
Add the new cases to your existing handler.
1const handleMessage = (type: string, data: { [key: string]: any }) => {
2 switch (type) {
3 case "exit_kinestex":
4 // User exited the trainer screen via the back button.
5 break;
6 case "workout_exit_request":
7 // User exited a workout that was launched from the trainer.
8 break;
9 case "trainer_schedule_next_workout":
10 // NEW — see "Scheduling the next workout" below.
11 // data: { type, scheduledFor: "YYYY-MM-DDTHH:MM" }
12 scheduleNextWorkoutReminder(data.scheduledFor);
13 break;
14 case "error_occurred":
15 console.warn("KinesteX error", data);
16 break;
17 }
18};Scheduling the next workout
When the AI generates the user's next plan, the SDK fires:
1{
2 "type": "trainer_schedule_next_workout",
3 "scheduledFor": "2026-04-29T14:30"
4}scheduledFor is `YYYY-MM-DDTHH:MM` with no timezone — interpret it as the device's local time (new Date(scheduledFor) in JS and DateTime.parse(scheduledFor) in Dart both do this correctly). The event is not sent if the user skips scheduling.
The SDK does not schedule the reminder for you — it just tells you when. The host app delivers the reminder. Two options:
- Local notification (recommended for native). No backend, works offline, fires even if the app is force-quit. Example below.
- Server-side push. POST
{ userId, scheduledFor, timezone }to your backend and queue a push (APNs / FCM / web-push / OneSignal). Use this when the user has multiple devices, you want delivery analytics, or the platform has no reliable local-notification path (e.g. plain web).
Whichever you pick, use a stable identifier per user (e.g. "trainer-next-workout") so a re-schedule replaces the previous reminder instead of stacking, skip past timestamps, and request notification permission early.
1import * as Notifications from "expo-notifications";
2
3const TRAINER_REMINDER_ID = "trainer-next-workout";
4
5async function scheduleNextWorkoutReminder(scheduledFor: string) {
6 const date = new Date(scheduledFor); // local time, no timezone in the string
7 if (Number.isNaN(date.getTime()) || date.getTime() - Date.now() < 5_000) return;
8
9 const { granted } = await Notifications.getPermissionsAsync();
10 if (!granted && !(await Notifications.requestPermissionsAsync()).granted) return;
11
12 // Replace the previous reminder so re-schedules don't stack.
13 await Notifications.cancelScheduledNotificationAsync(TRAINER_REMINDER_ID).catch(() => {});
14
15 await Notifications.scheduleNotificationAsync({
16 identifier: TRAINER_REMINDER_ID,
17 content: {
18 title: "Time for your workout",
19 body: "Your AI Trainer has your next session ready.",
20 sound: "default",
21 },
22 trigger: { type: Notifications.SchedulableTriggerInputTypes.DATE, date },
23 });
24}Quick checklist
kinestex-sdk-react-native≥ 1.2.9 installed.Mount with
IntegrationOption.AI_TRAINER_CHAT.Pre-fill
age,height(cm),weight(kg),gender("male"/"female") onpostDatawhen known.Handle
trainer_schedule_next_workoutand schedule a reminder (local notification or server-side push).Use a stable identifier so re-schedules replace the previous reminder.
Want early access for your team?
AI Trainer Chat is in limited rollout. Reach out and we'll enable it for your account.