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

# Toolsets

> Bundle connections and tools into a scoped tool belt - locally or persisted on the server.

A `Toolset` binds applications to connections and (optionally) restricts which tools are allowed. It's the unit you hand to an LLM: it produces provider-shaped tool schemas and executes the model's tool calls.

## Build one locally

<CodeGroup>
  ```python Python theme={null}
  toolset = client.toolset(
      tools=["salesforce_getrecords"],            # optional allow-list
      connections={"salesforce": "Prod"},         # id, name, or None for the default
  )
  ```

  ```typescript TypeScript theme={null}
  const toolset = client.toolset({
    tools: ["salesforce_getrecords"],
    connections: { salesforce: "Prod" },          // id, name, or null for the default
  });
  ```
</CodeGroup>

Connection bindings accept an integer id, a connection **name** (resolved via the API), or `None`/`null` to use your server default for that application.

## Use it

<CodeGroup>
  ```python Python theme={null}
  schemas = toolset.tools()                        # provider-shaped (default) or format="canonical"
  result = toolset.execute("salesforce_getrecords", {"sobject": "Account"})
  results = toolset.handle_tool_calls(llm_response)  # parse + run all tool calls from an LLM reply
  ```

  ```typescript TypeScript theme={null}
  const schemas = await toolset.tools();           // { format: "canonical" } for raw schemas
  const result = await toolset.execute("salesforce_getrecords", { sobject: "Account" });
  const results = await toolset.handleToolCalls(llmResponse);
  ```
</CodeGroup>

`handle_tool_calls` captures per-call tool failures (execution, connection, validation errors) as structured error results so the batch continues; systemic failures (auth, network, server) still raise. See [LLM providers](/sdk/llm-providers) for the full agent loop.

## Persist on the server

<CodeGroup>
  ```python Python theme={null}
  toolset_id = toolset.save(name="CRM agent belt")   # -> GUID; also sets toolset.id
  same = client.toolset(toolset_id=toolset_id)        # load it back

  client.toolsets.list()
  client.toolsets.get(toolset_id)
  client.toolsets.delete(toolset_id)
  ```

  ```typescript TypeScript theme={null}
  const toolsetId = await toolset.save({ name: "CRM agent belt" });
  const same = await client.toolset({ toolsetId });   // note: async in TS

  await client.toolsets.list();
  await client.toolsets.get(toolsetId);
  await client.toolsets.delete(toolsetId);
  ```
</CodeGroup>

Server toolsets also scope the REST API directly: pass `?toolsetId=` on `GET /v1/tools` (discovery) and `POST /v1/tools/{slug}/execute` (connection resolution + allow-list enforcement).
