From Design to Code – Building Agentic AI into “Your BMI Buddy” with Flutter and Gemini [Part 3]

From Design to Code – Building Agentic AI into “Your BMI Buddy” with Flutter and Gemini [Part 3]
Image Generated by Gemini

At Women in Tech Africa, Mauritius Chapter, I spoke about "Building Agentic Applications Using Flutter and Gemini".

During my session, I explained the core concepts of agents, their evolution into AI agents, and how Agentic AI differs from traditional AI. We also explored the idea of Generative AI Agents as they are intelligent models that can reason, decide, and act within defined boundaries.

I even demoed a fun example where the agent could decide whether to change a button color in an app based on context, and reason. That was a small but powerful example of an AI that doesn’t just follow instructions, but thinks in context.

In this article, we’ll explore another side of Agentic AI — this time, through a friendly wellness coach that can guide users based on their BMI.
(If you missed my talk, you can catch the full session on my YouTube channel!)

Meet your Agentic BMI Buddy 💙

Ever wondered what it would be like to have a wellness coach right inside your app? One that takes into account your height, weight, age, sex, and more, and then gives you short, actionable advice?

That's exactly what Your Agentic BMI Buddy does.

After you calculate your BMI, your virtual coach will

  • Offer a few personalised tips,
  • Propose weekly goals
  • Remind you to stay on track (if you ask it to)

Setting up Firebase

Before diving into the AI part, we will connect our app to Firebase since we will be using Firebase AI Tools to enable our agentic features.

Step 1: Login and Configure your project by running the following commands:

firebase login
flutterfire configure

Firebase CLI will ask you to either create a new project or select an existing one. You can choose the platforms you need, for example; Android, IOS, Web or Windows.

Once done, each platform will be assigned an App ID, and a firebase_options.dart file will be automatically generated inside your lib/ folder.

Step 2: Add dependencies in pubspec.yaml

Here is the list of packages we will be using

dependencies:
  firebase_core: ^latest
  firebase_ai: ^latest   
  hive: ^latest
  hive_flutter: ^latest
  gap: ^latest

Step 3: Initialise Firebase and Hive

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Hive.initFlutter();
  await Hive.openBox('profile');
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const MyApp());
}
  • We initialise the widget binding so the framework can talk to native OS.
  • Then we setup Firebase with platform-specific configurations using the DefaultFirebaseOptions.

And that's it! Your Firebase Project is ready and the app is connected. Let us move into the fun part.

The agent (how it thinks and act)

We start by creating an instance of the Gemini Model 2.5 Flash model through Firebase AI and expose a few tools so it knows what it's allowed to do. [For development purposes, we will be using Gemini Developer API, but in production, it is best to use vertexAI]

late final GenerativeModel _model = FirebaseAI.googleAI().generativeModel(
  model: 'gemini-2.5-flash',
  systemInstruction: Content.text('''
    You are "Your BMI Buddy"—a friendly, concise wellness coach.
    Always personalize using provided context. Avoid diagnoses/medications/calorie targets.
    When BMI very low/high, gently suggest seeing a clinician.
    Outputs must be short, practical, and culturally neutral.
  '''),
  tools: [Tool.functionDeclarations([
    setUserContextTool,
    storeGoalTool,
    storePlanTool,
    logDailyTool,
    scheduleReminderTool,
  ])],
);

The systemInstruction defines the agent's role; giving our application an intelligent layer that can reason, respond and perform contextual actions.

GenAI Limitations

Since Generative AI models can access external information, we use function calling to call external API or functions.

To implement this pattern:

  1. write a function that provides the model with the information it needs.
  2. create a function declaration for the model to know which function to use.
  3. send all declared tools to the model.
  4. provide the function response back to the model.

Tool Configuration

Tool configurations are defined in order to tell our model what it is allowed to do. For instance, we could request the agent to store our goals.

Function Declarations

Allows us to define our tool's api contract.

final storeGoalTool = FunctionDeclaration(
  'storeGoal',
  'Persist a single user-selected wellness goal.',
  parameters: {
    'goal_id': Schema.string(description: 'Machine id like "walk_20_min_5x"'),
    'goal_text': Schema.string(description: 'What the user chose/typed'),
  },
);

The Function Declaration takes a function name called storeGoal. It is given a description "Persist a single user selected wellness goal.". And it takes parameters; goal id and goal text.

Pushing contexts to the model

Whenever the user opens the coach, their profile data is pushed to the model. This ensures that the AI does not re ask for the same information.

Future<void> pushContextToAgent() async {
  final ctx = getProfile().toJson();
  await chat.sendMessage(Content.text('''
    SYSTEM CONTEXT (do not ignore). Use this as the user's current profile.
    If "bmi_value" and "bmi_category" exist, DO NOT ask for height/weight again.

    ```json
    ${jsonEncode(ctx)}
  '''));
}

Handing Function Calls

If the model decides to call one of the functions, for example, storeGoal we can capture that call, perform the action, and then send back a confirmation using functionResponse.

 case 'storeGoal':
          final goalId = (call.args['goal_id'] as String?) ?? '';
          final goalTxt = (call.args['goal_text'] as String?) ?? '';
          if (goalId.isNotEmpty && goalTxt.isNotEmpty) {
            await saveGoal(goalId, goalTxt);
          }
          await chat.sendMessage(
            Content.functionResponse('storeGoal', {"ok": true}),
          );
          break;

The agent only suggests what to do (save a goal, create a reminder) and the Flutter app decides on how to persist this information.

Putting it all together

In order to make this application work properly, we will be prompting the user to enter his weight and height, then we calculate the BMI.

Once the BMI is computed, it is categorized using:

String bmiCategoryKey(double bmi) {
  if (bmi < 18.5) return 'underweight';
  if (bmi < 25.0) return 'healthy';
  if (bmi < 30.0) return 'overweight';
  if (bmi < 35.0) return 'obesity_class_1';
  if (bmi < 40.0) return 'obesity_class_2';
  return 'obesity_class_3';
}

The information is saved in the user's profile.

And we pass that BMI data to the model to get context-specific advice:

final tips = await _agent.adviseForBmi(
  bmi: _profile.bmiValue!,
  category: _profile.bmiCategory!,
);
setState(() => _aiTips = tips);

As a result, the agent returns some tips and weekly goals.

Saving goals

If I respond with “Save Goal 1”, the model calls:

storeGoal(goal_id, goal_text)

The app persists the goal locally using Hive. Later if i ask: "What is my goal for this week", the agent retrieves and restates my saved goal.

Scheduling reminders!

The agent can also set reminders!

I said: “Since I’ve to walk 3 times a week, send me a reminder on Monday, Wednesday and Friday at 5 PM.”

The agent replied:

So, I responded with: "yes, 10th, 12th, and 14th November "

And here is what was logged in my console.

 Schedule reminder: Time to Walk! @ 2024-11-10T17:00:00
flutter: Remember your 10-15 minute walk!
flutter: Schedule reminder: Time to Walk! @ 2024-11-12T17:00:00
flutter: Remember your 10-15 minute walk!
flutter: Schedule reminder: Time to Walk! @ 2024-11-14T17:00:00
flutter: Remember your 10-15 minute walk!

And... That was the agent in action!

I hope you liked it!.


About Me

I am Zaahra, a Google Women Techmakers Ambassador who enjoy mentoring people and writing about technical contents that might help people in their developer journey. I also enjoy building stuffs to solve real life problems.

To reach me:

LinkedIn: https://www.linkedin.com/in/faatimah-iz-zaahra-m-0670881a1/

X (previously Twitter): _fz3hra

GitHub: https://github.com/fz3hra

Cheers,

Umme Faatimah-Iz-Zaahra Mujore | Google Women TechMakers Ambassador | Software Engineer