> ## 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.

# SDK overview

> engini (Python) and @engini/sdk (TypeScript) - one surface, two languages.

The Python and TypeScript SDKs expose an identical surface by design - same resources, same semantics, mirrored naming (snake\_case in Python, camelCase in TypeScript).

## Install

<CodeGroup>
  ```bash Python theme={null}
  pip install engini              # Python >= 3.9
  ```

  ```bash TypeScript theme={null}
  npm install @engini/sdk         # ESM, ships type declarations
  ```
</CodeGroup>

## Authentication

<CodeGroup>
  ```python Python theme={null}
  from engini import Engini

  client = Engini()                      # reads ENGINI_API_KEY (preferred) or ENGINI_API_TOKEN
  client = Engini(api_key="eng_...")     # explicit API key -> x-api-key header
  client = Engini(token="...")           # explicit PAT     -> Authorization: Bearer
  ```

  ```typescript TypeScript theme={null}
  import { Engini } from "@engini/sdk";

  const client = new Engini();                     // reads ENGINI_API_KEY (preferred) or ENGINI_API_TOKEN
  const client2 = new Engini({ apiKey: "eng_..." });
  const client3 = new Engini({ token: "..." });
  ```
</CodeGroup>

`api_key`/`token`/`auth` are mutually exclusive. Verify a credential with `client.auth.whoami()`. How the two credential types differ: [Authentication](/developers/get-started/authentication).

Other constructor options: `base_url`/`baseUrl` (defaults to `https://api.engini.io`), `provider` (LLM adapter, defaults to OpenAI), `verify` (TLS control for private CAs / staging).

## The resources

| Resource | What it does |
| - | - |
| `client.tools` | Discover tools (`get`), read one schema (`get_one`/`getOne`), execute (`execute`) |
| `client.connections` | List/create/delete connections, the OAuth flow, object selection, defaults |
| `client.toolsets` | Server-persisted toolset CRUD |
| `client.mcp` | Inspect and configure the account's [MCP servers](/developers/cli/command-reference#mcp-servers) (`list`, `get`, `update`, `activate`, `deactivate`, `available_tools`/`availableTools`). No create/delete - those stay in the engini.io UI |
| `client.opa` | Manage [on-prem agents](/developers/cli/command-reference#on-prem-agents): `list`, `get`, `create`, `update` (merges), `delete`, `enable`, `disable`, `get_token`/`getToken`, `rotate_token`/`rotateToken`, `download_logs`/`downloadLogs` (bytes), `latest_release`/`latestRelease`. `create` returns the token |
| `client.applications` | Browse the application catalog (`list`, `get`) |
| `client.auth` | `whoami()` - identity behind the credential |
| `client.toolset(...)` | Build a [`Toolset`](/developers/sdk/toolsets) - the LLM-facing tool belt |

## Execute a tool

<CodeGroup>
  ```python Python theme={null}
  tools = client.tools.get(applications=["salesforce"], search="accounts", limit=5)

  result = client.tools.execute(
      "salesforce_getrecords", {"sobject": "Account"}, connection_id=conn_id
  )
  print(result.output, result.history_id)
  ```

  ```typescript TypeScript theme={null}
  const tools = await client.tools.get({ applications: ["salesforce"], search: "accounts", limit: 5 });

  const result = await client.tools.execute(
    "salesforce_getrecords",
    { sobject: "Account" },
    { connectionId },
  );
  console.log(result.output, result.historyId);
  ```
</CodeGroup>

## Errors, pagination & rate limits

* Every failure raises a **typed error** from one hierarchy (`EnginiAuthError`, `EnginiRateLimitError`, `EnginiToolExecutionError`...) - full tree and handling patterns: [Errors & pagination](/developers/sdk/errors-pagination).
* **You never page manually**: list methods auto-paginate and return complete arrays.
* The SDK does **not** retry automatically - on `EnginiRateLimitError`, back off per the API's [rate-limit rules](/developers/get-started/pagination-errors-rate-limits).

## Python vs TypeScript in one minute

* Python is fully **synchronous**; TypeScript is fully **async** (`await` everything).
* Execute's arguments param: `arguments` (Python) vs `args` (TS); options are keyword-only (Python) vs a trailing options object (TS).
* Providers import from the root in TS (`import { AnthropicProvider } from "@engini/sdk"`) but from submodules in Python (`from engini.providers.anthropic import AnthropicProvider`).
* List methods auto-paginate in both - you always get the full array.
* Neither SDK retries automatically - handle `EnginiRateLimitError`/`EnginiServerError` yourself if you need retries.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.