> ## Documentation Index
> Fetch the complete documentation index at: https://chatbase.co/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Client-Side Tools

> Register local tool handlers that the agent can invoke during a conversation.

## What Are Client-Side Tools?

Client-side tools let your agent invoke functions that run locally on the Android device. Register a handler, and the SDK takes care of the rest — when the agent calls the tool, your handler runs and the result is fed back into the conversation automatically.

<Note>
  Client-side tools correspond to **Custom Actions** configured on your agent in the [Chatbase Dashboard](https://www.chatbase.co/dashboard). The `toolName` in the SDK matches the name of the configured action.
</Note>

## tool

`interface ChatbaseClient` — **Package:** `com.chatbase.sdk`

```kotlin theme={null}
fun tool(name: String, handler: suspend (input: Map<String, Any?>) -> Any)
```

Register a client-side tool handler.

<ParamField body="name" type="String" required>
  The tool name. Must match a Custom Action configured on your agent.
</ParamField>

<ParamField body="handler" type="suspend (Map<String, Any?>) -> Any" required>
  A suspend function that receives the parsed input and returns a result.
</ParamField>

```kotlin theme={null}
client.tool("get_weather") { input ->
    val city = input["city"] as String

    // Call a weather API, read a sensor, etc.
    mapOf(
        "city" to city,
        "temperature" to "22°C",
        "condition" to "Sunny"
    )
}
```

The agent can now call `get_weather` during a conversation. The SDK executes your handler and feeds the result back automatically. This loop can repeat up to 10 times per `sendMessage` call — if the agent requests more, `sendMessage` throws a `ChatbaseException` ("Tool loop exceeded maximum iterations").

<Warning>
  Tool results are limited to **20 KB** when serialized to JSON. Keep tool outputs concise — return only the data the agent needs.
</Warning>

## removeTool

```kotlin theme={null}
fun removeTool(name: String)
```

Unregister a previously registered tool handler.

<ParamField body="name" type="String" required>
  The tool name to remove.
</ParamField>

## Tracking Execution

Use the `onToolCall` and `onToolResult` callbacks to observe tool execution:

```kotlin theme={null}
client.sendMessage("What's the weather in Tokyo?") {
    onToolCall { tool ->
        println("Agent is calling: ${tool.toolName}")
        println("Input: ${tool.inputAsMap()}")
    }
    onToolResult { result ->
        println("Tool result: ${result.outputAsString()}")
    }
    onTextDelta { delta ->
        print(delta) // Agent's response after the tool result
    }
}
```

### ToolCallInfo

`data class ToolCallInfo` — **Package:** `com.chatbase.sdk`

Passed to the `onToolCall` callback before handler execution.

```kotlin theme={null}
data class ToolCallInfo(
    val toolCallId: String,
    val toolName: String,
    val input: JsonElement
)
```

```kotlin theme={null}
fun inputAsMap(): Map<String, Any?>
```

Parse the JSON input into a `Map<String, Any?>` for easy access.

### ToolResultInfo

`data class ToolResultInfo` — **Package:** `com.chatbase.sdk`

Passed to the `onToolResult` callback after handler execution.

```kotlin theme={null}
data class ToolResultInfo(
    val toolCallId: String,
    val toolName: String,
    val output: Any
)
```

```kotlin theme={null}
fun outputAsString(): String
```

Serialize the output to a JSON string.

## Interactive Tools

Since handlers are `suspend` functions, they can block on user interaction. For example, showing a color picker and waiting for the user's choice:

```kotlin theme={null}
client.tool("pick_color") { _ ->
    val deferred = CompletableDeferred<String>()

    // Show a color picker dialog (UI-framework specific)
    colorPickerRequest.value = deferred  // Observed by the Composable

    // Suspend until the user picks a color
    val color = deferred.await()

    mapOf("color" to color)
}
```

## Related

<CardGroup cols={2}>
  <Card title="Streaming" icon="wave-pulse" href="/docs/android-sdk/streaming">
    Streaming callbacks and Kotlin Flow
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/docs/android-sdk/error-handling">
    Handle errors during tool execution
  </Card>
</CardGroup>
