# Python SDK

Use Authlane from Python with typed Result handling and user-scoped local tools.

The Python SDK mirrors the control-plane resources and keeps provider execution in your trusted
Python process.

## Prerequisites

```bash
pip install authlane
```

Python 3.11 or newer is required.

## Initialize the client

The client talks to `https://app.authlane.io` unless you say otherwise, so only a self-hosted
deployment needs `base_url`.

```python
import os

from authlane import Authlane

with Authlane(
    api_key=os.environ["AUTHLANE_API_KEY"],
) as authlane:
    result = authlane.services.list()
    if result.error is not None:
        raise RuntimeError(result.error.code)
    assert result.data is not None
    services = result.data
```

## Connect an external user

```python
import os

from authlane import Authlane

external_user_id = "user_123"  # Derive this from the authenticated server session.

with Authlane(api_key=os.environ["AUTHLANE_API_KEY"]) as authlane:
    session_result = authlane.connect_sessions.create(
        external_user_id=external_user_id,
        allowed_services=[],
        allowed_origin="https://app.example.com",
        expires_in_seconds=600,
    )
    if session_result.error is not None:
        raise RuntimeError(session_result.error.code)
    assert session_result.data is not None
    session = session_result.data
```

`allowed_services=[]` is a one-time snapshot of every service currently enabled for the tenant.

## Load user-scoped tools

```python
import os

from authlane import Authlane
from authlane.adapters import generic

def load_tools(external_user_id: str):
    with Authlane(api_key=os.environ["AUTHLANE_API_KEY"]) as authlane:
        user = authlane.user(external_user_id)
        result = user.tools.list(adapter=generic())
        if result.error is not None:
            return result
        assert result.data is not None
        for tool in result.data.values():
            print(tool.name)
        return result.data
```

Raw capability definitions expose `tool.annotations` and the derived `tool.risk` value (`read`,
`write`, or `destructive`). Use those values to build an approval gate in Agno, LangChain, OpenAI
Agents, or a custom adapter. Tenant read-only policy is already enforced by Authlane before Python
receives the tool list.

## Async applications

```python
import os

from authlane import AsyncAuthlane
from authlane.adapters import langchain

async def load_tools(external_user_id: str):
    async with AsyncAuthlane(api_key=os.environ["AUTHLANE_API_KEY"]) as authlane:
        user = authlane.user(external_user_id)
        result = await user.tools.list(adapter=langchain())
        if result.error is not None:
            return result
        assert result.data is not None
        return result.data
```

## Expected result

Every expected SDK failure is represented by a `Result` with either `data` or `error`.

## Handle errors

Inspect `error.code`, `message`, `hint`, and `doc_url`. Network, validation, provider, and adapter
failures do not raise through the SDK Result contract.

## Security boundary

Bind `authlane.user(external_user_id)` from a trusted session before choosing an adapter. Each tool
invocation requests a fresh lease and calls the provider directly from Python.

## Next step

Use [Agno](/docs/sdk/agno), [LangChain](/docs/sdk/langchain), or the generic adapter described in
[framework adapters](/docs/sdk/frameworks).
