Skip to main content

Python SDK for LIME 2.0 agent authentication. Zero-config, Proof-of-Work auto-solve, async-first.

Project description

LIME Agents SDK

PyPI version Python versions License: MIT CI

Official Python SDK for LIME agent workers. Async-first client that performs site-login approval end-to-end: fetch Proof-of-Work challenge, solve SHA-256 PoW, submit approve with retries.

Installation

pip install lime-agents-sdk

Install the latest commit from GitHub:

pip install git+https://github.com/Mawyxx/lime-agents-sdk.git

Requirements: Python 3.10+

Quick start

Examples use readable names (Lime, login) on top of the shipped API (LimeAgent, approve). See API reference for exact types and parameters.

Minimal

from lime_agents import LimeAgent as _LimeAgent


class Lime(_LimeAgent):
    """aiogram-style client: token first, login() instead of approve()."""

    def __init__(self, token: str):
        super().__init__(agent_token=token)

    async def login(self, request_id: str):
        return await self.approve(request_id)


AGENT_TOKEN = "at_..."  # LIME Owner Portal → agent token (copy once)

async def login_to_site(request_id: str) -> str:
    """Agent confirms sign-in to a site. Returns status."""
    lime = Lime(AGENT_TOKEN)
    try:
        result = await lime.login(request_id)
        return result.status  # "DELIVERED"
    finally:
        await lime.aclose()

Production

from lime_agents import LimeAgent as _LimeAgent, PowTimeoutError, ApiError


class Lime(_LimeAgent):
    def __init__(self, token: str):
        super().__init__(agent_token=token)

    async def login(self, request_id: str):
        return await self.approve(request_id)


AGENT_TOKEN = "at_..."


class Agent:
    """Autonomous worker that signs in to sites when asked."""

    def __init__(self):
        self.lime = Lime(AGENT_TOKEN)

    async def on_login_required(self, request_id: str) -> str | None:
        """Site requires login — agent confirms."""
        try:
            result = await self.lime.login(request_id)
            return result.status
        except PowTimeoutError:
            # Proof-of-Work exceeded pow_timeout (default 10s) — retry once
            try:
                result = await self.lime.login(request_id)
                return result.status
            except PowTimeoutError:
                return None
        except ApiError as exc:
            print(f"[{exc.code}] {exc.message}")
            return None

Authentication

The SDK authenticates agent HTTP calls with the X-Agent-Token header.

Resolution order:

  1. Constructor argument agent_token="at_..."
  2. Environment variable LIME_AGENT_TOKEN

If neither is set (or the value is empty after trimming), construction raises AuthenticationError:

from lime_agents import LimeAgent, AuthenticationError

try:
    agent = LimeAgent()
except AuthenticationError as exc:
    print(exc.message)

Obtain the agent token once when registering an agent in the LIME owner portal. Store it as a server-side secret in your worker environment.

Integration pattern: Headless agent

Typical embedding: hold one LimeAgent per worker process and call approve() when a login request arrives.

from lime_agents import LimeAgent


class TradingAgent:
    def __init__(self, token: str):
        self.lime = LimeAgent(agent_token=token)

    async def on_login_required(self, request_id: str) -> str:
        result = await self.lime.approve(request_id)
        return result.status

The site backend creates the request (POST /modules/agent-login/requests), delivers login_request_id to your worker, and long-polls events until status becomes DELIVERED. Your worker only runs the approve step above.

API reference

LimeAgent

Async client for agent-runtime operations (approve login, read profile).

Constructor

All arguments are keyword-only.

Parameter Type Default Description
agent_token str | None None Agent secret. Falls back to LIME_AGENT_TOKEN.
base_url str | None None API root including /api/v1. Falls back to LIME_API_BASE, then https://lime.pics/api/v1.
timeout float 30.0 Per-request HTTP timeout in seconds (httpx).
max_retries int 3 Maximum retries on transient network errors and HTTP 408/429/5xx.
pow_timeout float 10.0 Wall-clock budget in seconds for the PoW solver loop.
http_client httpx.AsyncClient | None None Inject a custom async HTTP client (tests, corporate proxy/TLS). When omitted, the SDK creates and owns a client.
agent = LimeAgent(
    agent_token="at_live_...",
    base_url="https://lime.pics/api/v1",
    timeout=60.0,
    max_retries=5,
    pow_timeout=15.0,
)

Context manager: async with LimeAgent() as agent: calls aclose() on exit. Call await agent.aclose() manually when not using a context manager.

async approve(request_id: str) -> ApprovalResult

Confirms a site login request on behalf of the agent.

Internal steps:

  1. GET /auth/requests/{request_id} (public, no auth) — read pow_challenge, pow_difficulty
  2. Solve PoW: find nonce such that int(SHA256(challenge + nonce), 16) < 2**(256 - difficulty)
  3. POST /modules/agent-login/requests/{request_id}/approve with X-Agent-Token and body {"pow_nonce": "<nonce>"}

Parameters:

Name Type Description
request_id str Login request ID from the site backend (login_request_id from create).

Returns: ApprovalResult with FSM status (typically DELIVERED after successful approve).

from lime_agents import LimeAgent, PowTimeoutError, ApiError

async with LimeAgent() as agent:
    try:
        result = await agent.approve("550e8400-e29b-41d4-a716-446655440000")
        print(result.status, result.approved_agent_id)
    except PowTimeoutError:
        print("PoW not solved in time; increase pow_timeout or retry")
    except ApiError as exc:
        print(exc.code, exc.http_status, exc.message)

async get_profile() -> AgentProfile

Returns the authenticated agent's Core profile.

HTTP: GET /core/agents/me/profile with X-Agent-Token.

async with LimeAgent() as agent:
    profile = await agent.get_profile()
    print(profile.agent_id)
    print(profile.owner_kyc_level)
    print(profile.agent_reputation)

Types

ApprovalResult

Frozen dataclass returned by approve().

Field Type Description
request_id str Login request ID
site_id str Site that created the request
status str FSM value, e.g. APPROVED, DELIVERED
expires_at datetime Request expiry (timezone-aware when API sends offset)
approved_agent_id str | None Agent that approved (set after approve)

AgentProfile

Frozen dataclass returned by get_profile(). Matches GET /core/agents/me/profile response fields.

Field Type Description
agent_id str Agent identifier
owner_id str Owning LIME user
display_name str | None Public display name
avatar_url str | None Avatar URL
description str | None Public description
owner_kyc_level int | None Owner KYC level synced from Foundation
agent_reputation int | None Reputation score

Error handling

All SDK exceptions inherit from LimeError. Each carries message, and optionally code, http_status, and detail (API envelope).

Exception When
LimeError Base class; transport failures after retries, malformed JSON
AuthenticationError Missing/empty token at construct; HTTP 401; MISSING_AGENT_TOKEN, INVALID_AGENT_TOKEN
PowTimeoutError PoW solver exceeded pow_timeout
RateLimitError HTTP 429 / RATE_LIMIT_EXCEEDED
ApiError Other API errors (ok: false envelope)

ApiError attributes: code, message, http_status, detail.

import asyncio

from lime_agents import (
    LimeAgent,
    LimeError,
    AuthenticationError,
    PowTimeoutError,
    RateLimitError,
    ApiError,
)

async def run() -> None:
    try:
        async with LimeAgent() as agent:
            await agent.approve("lr_abc123")
    except AuthenticationError as exc:
        print("auth:", exc.message)
    except PowTimeoutError as exc:
        print("pow:", exc.message)
    except RateLimitError as exc:
        print("rate limit:", exc.http_status)
    except ApiError as exc:
        print(f"api [{exc.http_status}] {exc.code}: {exc.message}")
    except LimeError as exc:
        print("sdk:", exc.message)

asyncio.run(run())

Non-retried HTTP statuses: 400, 401, 403, 404, 409 (e.g. INVALID_POW, SITE_LOGIN_CONFLICT).

Configuration

Environment variables

Variable Required Description
LIME_AGENT_TOKEN Yes (unless agent_token= passed) Agent secret (at_...)
LIME_API_BASE No API root, e.g. https://lime.pics/api/v1

Constructor tuning

Use case Suggestion
Slow network Increase timeout (e.g. 60.0)
Flaky upstream Increase max_retries (e.g. 5)
High PoW difficulty / slow CPU Increase pow_timeout (e.g. 30.0)
Staging / self-hosted API Set base_url or LIME_API_BASE

Logging

HTTP and retry events are logged under the lime logger (not lime_agents):

import logging

logging.basicConfig(level=logging.DEBUG)
logging.getLogger("lime").setLevel(logging.DEBUG)

At DEBUG, the client logs request method and URL. Tokens, pow_challenge, and pow_nonce are never logged.

Advanced usage

Custom httpx.AsyncClient

Inject a client for custom TLS, proxies, or tests. You own the client lifecycle when injecting; the SDK does not close an injected client.

import httpx
from lime_agents import LimeAgent


async def approve_with_proxy() -> None:
    client = httpx.AsyncClient(
        timeout=60.0,
        verify="/path/to/corporate-ca.pem",
        proxy="http://proxy.corp.example:8080",
    )
    agent = LimeAgent(agent_token="at_...", http_client=client)
    try:
        await agent.approve("lr_abc123")
    finally:
        await client.aclose()

Retries and timeouts

Retries use exponential backoff with jitter on connection errors, timeouts, and HTTP 408, 429, 500, 502, 503, 504. Each retry attempt is bounded by max_retries (default 3).

agent = LimeAgent(
    agent_token="at_...",
    max_retries=5,
    timeout=45.0,
    pow_timeout=20.0,
)

PoW debugging

PoW runs in a thread pool (asyncio.to_thread) so the event loop stays responsive. To observe HTTP flow (not nonce values):

import logging

logging.getLogger("lime").setLevel(logging.DEBUG)

If PowTimeoutError occurs, increase pow_timeout or verify pow_difficulty from GET /auth/requests/{id} (default 15 on production).

Links

License

MIT — see LICENSE.

Project details


Download files

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

Source Distribution

lime_agents_sdk-0.1.0.tar.gz (11.9 kB view details)

Uploaded Source

Built Distribution

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

lime_agents_sdk-0.1.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file lime_agents_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: lime_agents_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 11.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for lime_agents_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4163ad0724814f6b9ad4b0ae7a94ebe9dedc62dfadef8e76c8689d32a2f0960a
MD5 c29396b8a9a7dfbe898294bf82cbcf63
BLAKE2b-256 55caa7cf4374d7abaab65f05d6bde407aa94424b319b6b37e056bbbb27620293

See more details on using hashes here.

File details

Details for the file lime_agents_sdk-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: lime_agents_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for lime_agents_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3d05ee931fbe50b4eff53221e9239975a8c89781c60e1f27bcd82d7502fd409e
MD5 77f5fc0845936de97f6ad6a7c1162fd5
BLAKE2b-256 c87efe57f439fcb05f4553232e8368d169b8afbddfd62574963874045fea8b63

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page