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

# Tool Calling

> Let the model call your functions

Register a tool and the function that runs it. The SDK owns the call-and-execute loop and
detects the format the model expects.

```ts theme={null}
RunAnywhere.llm.tools.register(weatherTool, async (args) => ({
  tempC: await fetchTemp(String(args.city)),
}))

const result = await RunAnywhere.llm.generate('What is the weather in Lisbon?')
```

## The tools namespace

`RunAnywhere.llm.tools` carries `register`, `unregister`, and `list`.

## Defining a tool

```ts theme={null}
import type { ToolDefinition } from '@runanywhere/electron'

const weatherTool: ToolDefinition = {
  name: 'get_weather',
  description: 'Get the current temperature for a city',
  parameters: [
    {
      name: 'city',
      type: 'string',
      description: 'City name',
      required: true,
    },
  ],
}
```

## Controlling the loop

| Field          | Default | Meaning                           |
| -------------- | ------- | --------------------------------- |
| `tools`        | `[]`    | Tools for this call only          |
| `toolChoice`   | `auto`  | Whether the model may call a tool |
| `maxToolCalls` | `5`     | Cap on calls in one exchange      |

Tools registered through `tools.register` are offered to every generation. Tools passed in
`options.tools` apply to that call alone.

## Executors run in the main process

This is what Electron has over the browser and the phone. A tool executor here has the full
Node API: the filesystem, child processes, the network with no CORS, and any native module you
have installed.

```ts theme={null}
RunAnywhere.llm.tools.register(readFileTool, async (args) => {
  const contents = await readFile(String(args.path), 'utf8')
  return { contents }
})
```

That power cuts both ways. A model deciding which file to read is a model deciding which file
to read. Validate the arguments, confine paths to a directory you chose, and never hand a tool
a shell string the model composed.

## Watching the calls happen

The stream reports tool activity, which is what lets you show "checking the weather…" rather
than a stalled cursor:

```ts theme={null}
for await (const event of RunAnywhere.llm.generateStream(prompt)) {
  if (event.type === 'toolCallAdded') status.textContent = `Calling ${event.name}…`
  if (event.type === 'textDelta') output.textContent += event.text
}
```

## Which models can do this

Tool calling needs a model with enough context to hold the tool definitions. The SDK gates on
context length rather than a model allowlist, so any model with a large enough window can
participate, though instruction-tuned models trained on tool use do it far more reliably. A
desktop can afford a larger `contextLength` at load time, which helps here.
