Documentation Index
Fetch the complete documentation index at: https://liquidai-fix-android-sdk-qa-issues.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Function calling lets the model invoke predefined functions provided by your app β query an API, run a calculation, fetch external state. Register LeapFunction definitions on the Conversation, run generation as usual, and the modelβs tool-call tokens come back as MessageResponse.functionCalls.
Not all models support function calling. Check the model card on Hugging Face before assuming a checkpoint supports tool use.
Vision and audio-capable models require companion files. Bundles embed these references; GGUF checkpoints expect siblings such as mmproj-*.gguf (vision) and audio decoder/tokenizer files. When detected, you can attach ChatMessageContent.image / .audio parts to your tool responses as well as user messages.
Register functions on the conversation
Conversation.registerFunction takes a LeapFunction instance describing name, parameters, and purpose.
Swift (iOS / macOS)
Kotlin (all platforms)
The Kotlin LeapFunction / LeapFunctionParameter constructors carry @ObjCName annotations on description:, so the Swift labels are functionDescription: and parameterDescription:. LeapFunctionParameterβs optional parameter has no Swift default β pass optional: false for required parameters.conversation.registerFunction(
function: LeapFunction(
name: "get_weather",
functionDescription: "Query the weather of a city",
parameters: [
LeapFunctionParameter(
name: "city",
type: LeapFunctionParameterType.LeapStr(enumValues: nil, description: nil),
parameterDescription: "The city to query weather for",
optional: false
),
LeapFunctionParameter(
name: "unit",
type: LeapFunctionParameterType.LeapStr(
enumValues: ["celsius", "fahrenheit"],
description: nil
),
parameterDescription: "Temperature unit (celsius or fahrenheit)",
optional: false
),
]
)
)
val conversation = modelRunner.createConversation("You are a helpful assistant.")
conversation.registerFunction(
LeapFunction(
name = "get_weather",
description = "Get the weather forecast of a city",
parameters = listOf(
LeapFunctionParameter(
name = "city",
type = LeapFunctionParameterType.LeapStr(),
description = "The city name",
),
LeapFunctionParameter(
name = "unit",
type = LeapFunctionParameterType.LeapStr(
enumValues = listOf("celsius", "fahrenheit")
),
description = "Temperature unit",
),
),
),
)
Use normal identifiers β letters, underscores, and digits (not starting with a digit). Most models trained for tool use recognize that shape.
The Kotlin parameter type classes are named with a Leap prefix (LeapStr, LeapNum, LeapInt, LeapBool, LeapArr, LeapObj, LeapNull) to avoid collisions with Kotlinβs built-in String, Number, Int, Boolean, etc. The Swift bindings expose the same names β there are no separate .string(...) / .number(...) aliases; SKIE preserves the Kotlin nested-class names.
Handle the response
Function calls arrive as the MessageResponse.FunctionCalls variant on both platforms, wrapping a list of LeapFunctionCall payloads.
Swift (iOS / macOS)
Kotlin (all platforms)
LeapFunctionCall is a Kotlin data class bridged into Swift. arguments is a Kotlin Map<String, Any?> exposed as Swift [String: Any] (the ObjC bridge collapses Any? to non-optional id):public class LeapFunctionCall {
public var name: String
public var arguments: [String: Any]
}
let userMessage = ChatMessage(role: .user, textContent: "What's the weather in NYC?")
for try await response in conversation.generateResponse(message: userMessage) {
switch onEnum(of: response) {
case .functionCalls(let payload):
for call in payload.functionCalls {
print("Function call: \(call.name) \(call.arguments)")
// dispatch to your tool implementation
}
case .chunk, .reasoningChunk, .audioSample, .complete:
break
}
}
data class LeapFunctionCall(
val name: String,
val arguments: Map<String, Any?>,
)
conversation.generateResponse(userMessage).onEach { response ->
when (response) {
is MessageResponse.Chunk -> { /* text chunk */ }
is MessageResponse.FunctionCalls -> {
response.functionCalls.forEach { call ->
Log.d(TAG, "Call ${call.name} with ${call.arguments}")
// dispatch to your tool implementation
}
}
is MessageResponse.Complete -> {
// Tool calls are also surfaced on the assembled assistant message:
response.fullMessage.functionCalls?.forEach { /* ... */ }
}
else -> {}
}
}.collect()
Tool calls are also attached to the final assistant message on the Complete event β useful if youβd rather batch-process tool calls once generation finishes.
The model may emit missing or invalid arguments β defensively validate the arguments map against your toolβs expected shape before dispatching.
Append the toolβs output as a tool-role message and continue the conversation. Both platforms use the same shape β see also Quick Start β Add tool results back to history.
Swift (iOS / macOS)
Kotlin (all platforms)
let toolMessage = ChatMessage(
role: .tool,
textContent: #"{"temperature":72,"conditions":"sunny"}"#
)
let updatedHistory = conversation.history + [toolMessage]
let nextConversation = conversation.modelRunner.createConversationFromHistory(history: updatedHistory)
// Continue generation against `nextConversation`.
val toolMessage = ChatMessage(
role = ChatMessage.Role.TOOL,
content = listOf(
ChatMessageContent.Text("""{"temperature":72,"conditions":"sunny"}""")
)
)
val updatedHistory = conversation.history + toolMessage
val nextConversation = modelRunner.createConversationFromHistory(updatedHistory)
Then call generateResponse(...) on the new conversation to get the modelβs tool-aware reply.
LeapFunction
Swift (iOS / macOS)
Kotlin (all platforms)
Both types are Kotlin data classes bridged into Swift. @ObjCName annotations rename the description parameter on the Swift inits to functionDescription: / parameterDescription:.public class LeapFunction {
public var name: String
public var functionDescription: String // ObjC-renamed from Kotlin `description`
public var parameters: [LeapFunctionParameter]
public init(name: String, functionDescription: String, parameters: [LeapFunctionParameter])
}
public class LeapFunctionParameter {
public var name: String
public var type: LeapFunctionParameterType
public var parameterDescription: String // ObjC-renamed from Kotlin `description`
public var optional: Bool
public init(
name: String,
type: LeapFunctionParameterType,
parameterDescription: String,
optional: Bool // no default in Swift β pass `false` for required
)
}
data class LeapFunction(
val name: String,
val description: String,
val parameters: List<LeapFunctionParameter>,
)
data class LeapFunctionParameter(
val name: String,
val type: LeapFunctionParameterType,
val description: String,
val optional: Boolean = false,
)
Parameter types
LeapFunctionParameterType is translated into JSON Schema for the model. The same primitive set is exposed on both platforms.
Swift (iOS / macOS)
Kotlin (all platforms)
LeapFunctionParameterType is a Kotlin sealed class. SKIE generates an onEnum(of:)-compatible enum view, but the constructors you use to build instances keep the Kotlin nested-class names β there is no .string(...) / .number(...) alias.// Direct constructors (use these to build parameter types):
LeapFunctionParameterType.LeapStr(enumValues: [String]?, description: String?)
LeapFunctionParameterType.LeapNum(enumValues: [NSNumber]?, description: String?)
LeapFunctionParameterType.LeapInt(enumValues: [KotlinInt]?, description: String?)
LeapFunctionParameterType.LeapBool(description: String?)
LeapFunctionParameterType.LeapArr(itemType: LeapFunctionParameterType, description: String?)
LeapFunctionParameterType.LeapObj(
properties: [String: LeapFunctionParameterType],
required: [String],
description: String?
)
LeapFunctionParameterType.LeapNull() // no description parameter
LeapStr / LeapNum / LeapInt accept enumValues to constrain valid values.
LeapArr has itemType describing the element type.
LeapObj has properties: [String: LeapFunctionParameterType] and required: [String].
- The nested
description is overridden when the type is used directly as LeapFunctionParameter.type; itβs only consulted when the type is used inside LeapArr.itemType or LeapObj.properties.
LeapFunctionParameterType.LeapStr(enumValues: List<String>? = null, description: String? = null)
LeapFunctionParameterType.LeapNum(enumValues: List<Number>? = null, description: String? = null)
LeapFunctionParameterType.LeapInt(enumValues: List<Int>? = null, description: String? = null)
LeapFunctionParameterType.LeapBool(description: String? = null)
LeapFunctionParameterType.LeapArr(itemType: LeapFunctionParameterType, description: String? = null)
LeapFunctionParameterType.LeapObj(
properties: Map<String, LeapFunctionParameterType>,
required: List<String> = listOf(),
description: String? = null,
)
LeapFunctionParameterType.LeapNull()
The nested description is overridden when the type is used directly as LeapFunctionParameter.type; itβs only consulted when the type is used inside LeapArr.itemType or LeapObj.properties.
Example: array + enum parameters
Swift (iOS / macOS)
Kotlin (all platforms)
LeapFunction(
name: "get_weather",
functionDescription: "Query the weather of cities",
parameters: [
LeapFunctionParameter(
name: "cities",
type: LeapFunctionParameterType.LeapArr(
itemType: LeapFunctionParameterType.LeapStr(enumValues: nil, description: nil),
description: nil
),
parameterDescription: "Names of the cities to query weather for",
optional: false
),
LeapFunctionParameter(
name: "unit",
type: LeapFunctionParameterType.LeapStr(
enumValues: ["celsius", "fahrenheit"],
description: nil
),
parameterDescription: "Temperature unit",
optional: false
),
]
)
LeapFunction(
name = "get_weather",
description = "Get the weather forecast of cities",
parameters = listOf(
LeapFunctionParameter(
name = "cities",
type = LeapFunctionParameterType.LeapArr(
itemType = LeapFunctionParameterType.LeapStr()
),
description = "City names to query",
),
LeapFunctionParameter(
name = "temperature_unit",
type = LeapFunctionParameterType.LeapStr(
enumValues = listOf("Fahrenheit", "Celsius", "Kelvin")
),
description = "Units for temperature",
),
),
)
Function call parser
Different models emit tool-call tokens in different shapes. The parser translates those tokens into LeapFunctionCall values. The default LFMFunctionCallParser handles Liquid Foundation Model (LFM2) Pythonic-style control tokens (<|tool_call_start|> ... <|tool_call_end|>). For Qwen3 and other models using the Hermes function-calling format, use HermesFunctionCallParser.
Swift (iOS / macOS)
Kotlin (all platforms)
var options = GenerationOptions()
options.functionCallParser = HermesFunctionCallParser()
for try await response in conversation.generateResponse(
message: userMessage,
generationOptions: options
) {
// ...
}
val options = GenerationOptions.build {
functionCallParser = HermesFunctionCallParser()
}
conversation.generateResponse(userMessage, options).onEach { /* ... */ }.collect()
Pass null / nil as the parser to disable tool-call parsing entirely β the raw tool-call text is then surfaced as ordinary Chunks.