Skip to main content

engini

Agent-first Python SDK for the Engini Public API — discover tools, execute them against your connected apps, and wrap them as LLM tool definitions.

pip install engini            # SDK
pip install 'engini[cli]'     # SDK + the `engini` CLI

Quickstart

from engini import Engini

client = Engini(api_key="eng_…")          # or set ENGINI_API_KEY

# Discover canonical tool schemas
tools = client.tools.get(applications=["salesforce"], search="accounts", limit=5)

# Execute a tool against a connection
conn_id = next(c.connection_id for c in client.connections.list(application="salesforce"))
result = client.tools.execute(
    "salesforce_getrecords", {"sobject": "Account"}, connection_id=conn_id
)
print(result.output)

JWT auth is the fallback: Engini(token="<jwt>", company_token="<id>"), or set ENGINI_API_TOKEN / ENGINI_COMPANY_TOKEN. With an API key the company is bound to the key, so no company token is needed. Point at another host with Engini(..., base_url=…).

Use with an LLM

Provider adapters wrap canonical schemas into vendor tool definitions client-side, with no vendor SDK dependency. OpenAI is the default; Anthropic is also available.

# Bind applications → connections once, then drive a tool-calling loop
toolset = client.toolset(tools=["salesforce_getrecords"], connections={"salesforce": "Prod"})

openai_tools = client.provider.wrap_tools(toolset.tools())   # plain OpenAI tool-JSON dicts
# … send openai_tools to the model, get a response …
results = toolset.handle_tool_calls(llm_response)            # runs the calls, returns results

client.toolset(...) builds a local toolset (no I/O until used) or loads a server one via toolset_id=….

Files

Tools whose input_schema marks a field "format": "engini/file" accept files. Wrap a file with engini.File and pass it as the field value — the SDK base64-encodes it into the {base64_content, mime_type, filename} wire shape. A field can take a single file or a list, per the tool's schema.

from engini import Engini, File

client = Engini(api_key="eng_…")
client.tools.execute(
    "doc_summarize",
    {
        "document": File.from_path("report.pdf"),                  # single file
        "attachments": [File.from_path("a.png"), File.from_path("b.png")],  # list of files
    },
    connection_id=conn_id,
)

File.from_path infers the filename and mime type; File.from_bytes(data, filename=…, mime_type=…) and File.from_base64(…) cover in-memory content.

In the LLM loop an agent can't produce base64, so file fields are presented to it as string fields. Register the files you'll allow and let the model reference one by key:

results = toolset.handle_tool_calls(
    llm_response, files={"report": File.from_path("report.pdf")}
)

What this adds over the raw REST client

Built on the autogenerated engini-client, the SDK adds what the generated client deliberately lacks: typed errors (the EnginiError family), retry/backoff, auto-pagination, pluggable auth (ApiKeyAuth / BearerAuth), Provider adapters for OpenAI/Anthropic, and the ergonomic Toolset object.

Command-line interface

The engini[cli] extra ships an engini command — a machine-first CLI over the same surface.

engini --help     # login · logout · whoami · tools · applications · connections · connect
engini login --api-key eng_…                 # or run interactively on a TTY
engini whoami                                 # who am I / which company
engini applications list --available          # discover connector apps
engini tools list --application salesforce    # discover tools
engini tools call salesforce_getrecords --args '{"sobject":"Account"}' --connection <id>
engini tools call doc_summarize --args '{}' --file document=@report.pdf   # attach a file
engini tools result <handle> --select records.Id   # drill into a large result
engini connect salesforce                     # create a connection end to end (interactive / agent)
engini connect                                # no app → open the connections page in your browser

connect [<app>] walks the whole connection-creation flow — discover the app's authentication methods, collect credentials (or run the OAuth2 sign-in), create the connection, check it, refresh its objects, and (when the app supports it) pick which objects to sync. On a TTY it prompts and opens the browser inline. Async jobs poll up to --timeout (--no-wait returns early; a timeout exits 124).

Agent recipe (piped / non-TTY). connect never blocks for an agent: at each gate it prints {"need": …, "resume": "<exact next command>"} and exits 5. The agent asks the user for the value and runs the resume command:

# direct-credential (e.g. monday)
engini connect monday --json                   # → need:fields (+ resume)
engini connect monday --auth 0 --field ApiKey=<key>   # creates → checks → refreshes

# OAuth2 (e.g. outlook) — never opens a browser for the agent
engini connect outlook --json                  # → need:oauth (sign_in_url, state, resume)
engini connect outlook --oauth-state <state>   # after sign-in: polls token → creates

# object selection — resume never re-creates the connection
engini connect <app> --connection <id> --object 5 --object 9

The same steps are available as standalone primitives: engini connections sign-in-url / oauth-complete (OAuth) and engini connections create / delete / check / refresh / objects / select-objects.

Output is machine-first: human-readable on a TTY, compact JSON when piped, pretty JSON with --json. Every command also accepts --quiet and --schema (a machine-readable arg schema), and mutating commands accept --dry-run. Exit codes are a stable contract (0 ok · 2 usage · 3 auth · 4 not found · 5 validation · 124 timeout).

Large results. Tool outputs can be huge, and an agent shouldn't pay tokens for data it hasn't asked for. When a tools call result exceeds --max-bytes (default 4096), it is spilled to a local sandbox ($XDG_CACHE_HOME/engini/results/) and the command prints a compact envelope — {handle, data_size, shape, preview, hint} — instead of the full payload. Drill in on demand with engini tools result <handle>: --select <dot.path> (maps over lists), --fields a,b (project keys), --offset/--limit (page a list), or --full; --list / --clear manage the store. --inline (or --max-bytes 0) forces the full inline result; --raw / --llm emit full output and bypass the sandbox. The store auto-prunes to the most-recent 20 results, dropping anything older than 24h, so a handle is short-lived — drill in during the same session.

Credentials and host config live in $XDG_CONFIG_HOME/engini/config.toml (%APPDATA%\engini\config.toml on Windows), written 0600. Resolution order is flags > environment > config; the env vars are ENGINI_API_KEY (preferred) or ENGINI_API_TOKEN, plus ENGINI_COMPANY_TOKEN.

Source & docs: https://github.com/engini/engini-sdk

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

engini-0.10.0.tar.gz (76.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

engini-0.10.0-py3-none-any.whl (72.2 kB view details)

Uploaded Python 3

File details

Details for the file engini-0.10.0.tar.gz.

File metadata

  • Download URL: engini-0.10.0.tar.gz
  • Upload date:
  • Size: 76.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for engini-0.10.0.tar.gz
Algorithm Hash digest
SHA256 4de0709eb85526ad32a171c17be1e30bd948a7fc1caa18a39db4f80aacf2728e
MD5 7b1b57f2c091685848b95f7eaef107bd
BLAKE2b-256 7423c66f6dff02e576830b34e46ccd573828e86d1e11cfcaf90d00ca88bd80c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for engini-0.10.0.tar.gz:

Publisher: release-python.yml on engini/engini-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file engini-0.10.0-py3-none-any.whl.

File metadata

  • Download URL: engini-0.10.0-py3-none-any.whl
  • Upload date:
  • Size: 72.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for engini-0.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9a7f8c746c90a343dc8691c39bb21d38675e41d1e4912fabd19c917f3d748f30
MD5 d76029bd8fd7d13d7593612e7fdcb45e
BLAKE2b-256 3d969f02f91e92f623f27b0db3df551b240dbf909443f1518797fc823e196126

See more details on using hashes here.

Provenance

The following attestation bundles were made for engini-0.10.0-py3-none-any.whl:

Publisher: release-python.yml on engini/engini-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.19.0

2 files

0.18.0

2 files

0.17.0

2 files

0.16.0

2 files

0.14.0

2 files

0.11.1

2 files

0.11.0

2 files

This release

0.10.0 This release

2 files

0.9.0

2 files

0.7.1

2 files

0.6.0

2 files

0.5.1

2 files

0.5.0

2 files

0.3.0

2 files

0.2.0

2 files

0.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page