Skip to main content

Overview

Tool calling lets a model request one of your functions, receive the result, and fold it into its answer. The SDK runs the whole loop: generate, parse the tool call, execute your Kotlin lambda, feed the result back, generate the final response. Parsing lives in C++; there is no Kotlin fallback parser. Every entry point is an extension function on the RunAnywhere singleton. There is no RunAnywhereToolCalling class.

Imports

The string, int, double, bool, array, and object constructors on RAToolValue are extension functions in com.runanywhere.sdk.public.extensions.LLM and have to be imported individually.

Registering a tool

registerTool is a suspend function. The executor is a ToolExecutor, which is suspend (Map<String, RAToolValue>) -> Map<String, RAToolValue>. Arguments and return values are both typed value maps; the SDK marshals them to and from the JSON the model sees.

Generating with tools

Signature:
The first five parameters have no defaults, so pass null for the ones you do not need. history is prior turns as a flat alternating list ([user0, assistant0, user1, ...]) excluding the current turn, which is prompt. It is threaded to commons so the tool loop keeps multi-turn context. An explicit toolOptions overrides any tool_calling payload embedded in options. When both are absent, the SDK derives options from options and falls back to ToolCallingOptions.defaults().

Tool management

All are suspend functions on RunAnywhere.

ToolDefinition

ToolParameter

ToolParameterType values are TOOL_PARAMETER_TYPE_STRING, NUMBER, BOOLEAN, OBJECT, ARRAY, and UNSPECIFIED. Fully qualified, so ToolParameterType.TOOL_PARAMETER_TYPE_STRING, not ToolParameterType.STRING.

ToolCallingOptions

Defaults are max_tool_calls = 5, auto_execute = true, format = TOOL_CALL_FORMAT_NAME_JSON. toolChoice and forcedToolName passed to generateWithTools() override whatever the options carry.

ToolCallingResult

ToolCall carries id, name, arguments_json, type, created_at_ms, and raw_text. Arguments arrive as a JSON string, not a map. ToolResult carries tool_call_id, name, result_json, error, success, started_at_ms, and completed_at_ms. The result is likewise a JSON string. Pairing a call with its result:

ToolValue

RAToolValue is a typealias for the generated ToolValue. Build values with the companion extensions and read them with the property extensions. object is a Kotlin keyword, so both the constructor and the accessor need backticks: RAToolValue.`object`(fields). toJSONString(pretty), RAToolValue.parseObjectJSON(json), and RAToolValue.jsonString(map) convert between value maps and JSON. The accessor is .string, not .stringValue.

Examples

Calculator:
Return an error value rather than throwing. A thrown executor aborts the turn; an error value lets the model recover or explain. Zero-parameter tool:
Registering a set at startup:

Timeouts

Small on-device models sometimes fail to converge on a tool loop. Bound the call and cancel the generation when it expires, rather than leaving the UI waiting:

Errors

generateWithTools() throws SDKException with ERROR_CODE_NOT_INITIALIZED before RunAnywhere.initialize(). Individual tool failures come back on ToolResult, not as exceptions. See Error handling.

Notes

Executors run inside the generation loop, so a slow one blocks inference for its duration. Keep network calls out, or bound them yourself. Descriptions are the only thing the model has to decide with. A description that names the inputs and says what comes back beats one that names the function again. Keep returned payloads small. Everything a tool returns is fed back through the context window.

LLM generation

Text generation

VLM

Vision language models

System prompts

Control model behavior

Error handling

Error handling patterns