●TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13●OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude Code●SIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App Store●MAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessage●NATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core ML●SEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round●TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13●OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude Code●SIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App Store●MAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessage●NATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core ML●SEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round
Rork × Gemini Agents SDK: Integrating Multi-Step AI Agents into Your Mobile App
A comprehensive guide to integrating Gemini Agents SDK into Rork apps, covering Function Calling, session management, streaming, and production deployment. Build truly agentic AI experiences with detailed code examples.
Setup and context — Why "Agentic AI" Belongs in Your Mobile App
There's a meaningful difference between a chatbot and an AI agent. A chatbot responds to questions. An AI agent pursues goals — autonomously selecting tools, forming plans, and executing multi-step actions. When a user says "plan my trip next week, find hotels, and add it to my calendar," an agent handles the entire flow end-to-end.
In 2026, Google's Gemini Agents SDK (formerly the Agent Development Kit, or ADK) is gaining traction in the mobile development world. By integrating this SDK into a Rork or Rork Max project — built on React Native — you can embed AI that doesn't just generate text, but actually acts.
This guide takes you from the core architecture of Gemini Agents SDK through integration patterns for Rork apps, session management, and production operations. It covers the deep, practical implementation knowledge that general tutorials skip.
The target reader is a developer with existing experience integrating AI into Rork who is ready to take the next step into agentic patterns.
Understanding the Core Architecture of Gemini Agents SDK
The Three Pillars: Model, Tools, and Instructions
Every Gemini agent is composed of three elements.
Model: The reasoning engine. Choose between gemini-2.0-flash (fast, cost-efficient) and gemini-2.5-pro (highest accuracy). Since mobile apps are latency-sensitive, gemini-2.0-flash is the right default for most use cases.
Tools: The capabilities the agent can invoke. There are three main types:
Function Calling: Invoke any JavaScript function you define
Code Execution: Dynamically generate and run Python code for data analysis
Grounding with Google Search: Use real-time web search results as the basis for answers
Instructions: The system prompt that defines the agent's role, constraints, and behavior. The quality of your system instructions is one of the most important factors in making an agent genuinely useful.
How Function Calling Actually Works
Understanding the internals of Function Calling is essential for debugging and optimization.
User input → Model determines "I should use this tool"
→ Model outputs tool name and arguments as JSON (does NOT execute yet)
→ SDK parses the JSON and executes the actual function
→ Function return value is sent back to the model
→ Model interprets the result and generates a final response
This "decide → execute → interpret" cycle can repeat multiple times, allowing the agent to handle complex, multi-step tasks by chaining tool calls together.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦Learn the full workflow for integrating Gemini Agents SDK's Function Calling, Code Execution, and Grounding into a mobile app
✦Understand best practices for session management, state persistence, and error handling in multi-step AI agents
✦Gain architecture patterns and production operation knowledge to build a practical AI assistant app from scratch
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
A Rork or Rork Max project (React Native / Expo-based)
A Gemini API key from Google AI Studio
Node.js 20 or higher
Installing Dependencies
# Gemini AI SDK (latest Google Generative AI)npm install @google/generative-ai# Agent functionality extensions (ADK-compatible wrapper)npm install @google/generative-ai-agents# Session management and persistencenpm install @react-native-async-storage/async-storage# Streaming-capable UI componentsnpm install react-native-reanimated
Environment Variable Configuration
Add the following to your Rork project's .env file. Always manage API keys as server-side environment variables — never embed them directly in client code.
# .env (exclude from version control)GEMINI_API_KEY=YOUR_GEMINI_API_KEY_HERE# For Expo (direct client exposure is discouraged; use a backend proxy instead)EXPO_PUBLIC_API_BASE_URL=https://your-api.workers.dev
⚠️ Security warning: Embedding an API key directly in your mobile app bundle is a serious risk — it can be extracted through decompilation. In production, always route API calls through a backend proxy such as Cloudflare Workers.
Building Your First Agent
Defining Tools: Designing Effective Function Calls
A great tool definition includes a description clear enough that the model understands when to use it.
// src/agents/tools/weatherTool.tsimport { FunctionDeclaration, Type } from "@google/generative-ai";export const weatherTool: FunctionDeclaration = { name: "get_current_weather", description: "Retrieves current weather information for a specified city or region. " + "Use this when the user asks about the weather or is planning an outing or trip.", parameters: { type: Type.OBJECT, properties: { location: { type: Type.STRING, description: "City name or region (e.g., 'Tokyo', 'New York', 'London, UK')", }, unit: { type: Type.STRING, enum: ["celsius", "fahrenheit"], description: "Temperature unit. Defaults to celsius.", }, }, required: ["location"], },};// The actual API call implementationexport async function executeWeatherTool(args: { location: string; unit?: string;}): Promise<object> { // Using the free Open-Meteo API const geocodeRes = await fetch( `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(args.location)}&count=1` ); const geocodeData = await geocodeRes.json(); if (!geocodeData.results?.length) { return { error: `No location found for "${args.location}"` }; } const { latitude, longitude, name, country } = geocodeData.results[0]; const weatherRes = await fetch( `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,weather_code,wind_speed_10m&timezone=auto` ); const weatherData = await weatherRes.json(); const current = weatherData.current; return { location: `${name}, ${country}`, temperature: current.temperature_2m, unit: args.unit || "celsius", wind_speed: current.wind_speed_10m, weather_code: current.weather_code, // WMO codes: 0=clear, 1-3=partly cloudy, 61-67=rain, 71-77=snow };}
Implementing the Agent Core
// src/agents/GeminiAgent.tsimport { GoogleGenerativeAI, GenerativeModel, ChatSession, FunctionCallingMode, Part,} from "@google/generative-ai";import { weatherTool, executeWeatherTool } from "./tools/weatherTool";// Tool execution map (name → handler function)const TOOL_HANDLERS: Record<string, (args: any) => Promise<any>> = { get_current_weather: executeWeatherTool,};export interface AgentMessage { role: "user" | "model"; content: string; toolCalls?: Array<{ name: string; args: object; result: object }>; timestamp: number;}export class GeminiAgent { private model: GenerativeModel; private chat: ChatSession | null = null; private messageHistory: AgentMessage[] = []; constructor(private apiKey: string) { const genAI = new GoogleGenerativeAI(this.apiKey); this.model = genAI.getGenerativeModel({ model: "gemini-2.0-flash", systemInstruction: this.buildSystemInstruction(), tools: [{ functionDeclarations: [weatherTool] }], toolConfig: { functionCallingConfig: { // AUTO: model decides autonomously when to use tools (recommended) mode: FunctionCallingMode.AUTO, }, }, generationConfig: { maxOutputTokens: 2048, temperature: 0.7, }, }); } private buildSystemInstruction(): string { return `You are a helpful and capable AI assistant.When answering user questions, use the available tools as needed to provide accurate, up-to-date information.Guidelines:- When you use a tool, explain its results naturally in your response- Avoid stating uncertain information as fact; use phrases like "it appears that..." when unsure- Respect user privacy and avoid collecting unnecessary personal information- For complex questions, break them down into manageable steps`; } startSession(history?: Array<{ role: string; parts: Part[] }>) { this.chat = this.model.startChat({ history: history || [] }); this.messageHistory = []; } async sendMessage(userMessage: string): Promise<AgentMessage> { if (!this.chat) this.startSession(); const userEntry: AgentMessage = { role: "user", content: userMessage, timestamp: Date.now(), }; this.messageHistory.push(userEntry); let result = await this.chat!.sendMessage(userMessage); const toolCalls: AgentMessage["toolCalls"] = []; // Function Calling loop — continues while model requests tool calls while (true) { const response = result.response; const functionCalls = response.functionCalls(); if (!functionCalls || functionCalls.length === 0) { break; // No more tool calls → we have the final answer } // Execute multiple tools in parallel const toolResults = await Promise.all( functionCalls.map(async (call) => { const handler = TOOL_HANDLERS[call.name]; if (!handler) { return { name: call.name, response: { error: `Unknown tool: ${call.name}` }, }; } const toolResult = await handler(call.args); toolCalls.push({ name: call.name, args: call.args, result: toolResult }); return { name: call.name, response: toolResult }; }) ); // Return tool results to the model to continue generation result = await this.chat!.sendMessage( toolResults.map((tr) => ({ functionResponse: { name: tr.name, response: tr.response }, })) ); } const modelEntry: AgentMessage = { role: "model", content: result.response.text(), toolCalls: toolCalls.length > 0 ? toolCalls : undefined, timestamp: Date.now(), }; this.messageHistory.push(modelEntry); return modelEntry; } getHistory(): AgentMessage[] { return [...this.messageHistory]; }}
Advanced Patterns: Multi-Step Agents
Session Management and State Persistence
Mobile users expect to pick up conversations where they left off. Here's how to persist sessions using AsyncStorage.
To continuously improve agent quality, collect and analyze these metrics:
Tool Call Rate: Percentage of requests where tools were invoked
Tool Success Rate: Ratio of successful vs. failed tool calls
Latency Breakdown: Model inference time vs. tool execution time
Token Usage: Input and output token counts for cost management
User Satisfaction: Thumbs up/down feedback signals
Cost Optimization Strategies
Several practical strategies help minimize Gemini API costs without sacrificing quality.
Response caching: Cache answers to frequently asked questions (e.g., "what's the weather today?") with a short TTL (15 minutes) to dramatically reduce API calls.
Model tiering: Use the lightweight gemini-2.0-flash-lite for simple intent classification, and only escalate to the more capable model when complex reasoning is needed.
Context compression: The history compression strategy described above keeps input token counts low in long conversations.
Parallel tool execution: Running multiple tool calls concurrently with Promise.all eliminates unnecessary round-trip latency, as shown in the agent core implementation above.
A Note from an Indie Developer
Wrapping Up
This guide has walked through integrating Gemini Agents SDK's multi-step AI agents into Rork — from architecture design to production operations.
The key takeaways: first, internalize how Function Calling works so you can design agents that use tools autonomously. Second, combine session management with AsyncStorage so conversations persist across app sessions. Third, prepare for production-specific challenges — rate limits, timeouts, context overflow — with the implementation patterns shown here.
AI agents represent a step change from "AI that thinks" to "AI that acts." Combined with Rork's rapid UI development capabilities, you can ship apps that make a real difference in users' lives far faster than traditional development.
For advanced patterns like coordinating multiple agents in a collaborative system, see the Rork Multi-AI Orchestration Complete Guide.
Share
Thank You for Reading
Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.