Skip to content
sdk

Python

Sync (requests) and async (httpx). Same surface. Anonymous-first. Retries with exponential backoff and Retry-After honoring built in.

Install

pip install git+ssh://git@git.argand.org/nicweyand/argand.git#subdirectory=sdk/python

Source-only install from Forgejo. PyPI publish deferred until launch (mid-2026). Pin a commit SHA in your manifest for reproducibility.

Hello world (anonymous)

hello.py python
from argand import ArgandClient

with ArgandClient() as client:
    response = client.search("rust async runtime", page=1, limit=10)
    for hit in response.results:
        print(f"{hit.rank}. {hit.title} -> {hit.url}")

Async

async_hello.py python
import asyncio
from argand import AsyncArgandClient

async def main() -> None:
    async with AsyncArgandClient() as client:
        response = await client.search("rust async runtime")
        print(response.total_results)

asyncio.run(main())

Method surface

  • client.search(query, page=1, limit=10)SearchResponse
  • client.lucky(query)str (Location header URL)
  • client.fetch(...) / client.cite(...) — reserved. Raise NotImplementedAPIError until v2.

Auth

Pass an opaque key — no DID, no Solid Pod. Anonymous calls work without it.

from argand import ArgandClient

with ArgandClient(api_key="your-argand-api-key") as client:
    response = client.search("tokio")
    print(response.results[0].url)

Self-hosted Argand

from argand import ArgandClient

with ArgandClient(base_url="https://argand.example.org") as client:
    response = client.search("self-hosted")
    print(response.total_results)

Retry semantics

Default: 3 attempts, 250ms → 8s exponential backoff. 429 and 5xx retry. Retry-After (seconds form) is honored. 401 / 403 raise immediately.

from argand import ArgandClient, RetryPolicy

retry = RetryPolicy(max_attempts=5, base_delay_s=0.1, max_delay_s=4.0)
with ArgandClient(retry=retry) as client:
    response = client.search("retries")

Error types

All exceptions descend from argand.ArgandError:

  • AuthError — 401/403, never retried.
  • RateLimitError — 429 after retries exhausted; carries retry_after.
  • TimeoutError — transport timeout.
  • TransportError — DNS / TLS / connection failures.
  • ServerError — 5xx after retries.
  • ProtocolError — server returned a body that doesn't match the contract.
  • NotImplementedAPIError — v2-reserved (fetch, cite).
from argand import (
    ArgandClient,
    AuthError,
    RateLimitError,
    ServerError,
    NotImplementedAPIError,
)

with ArgandClient() as client:
    try:
        response = client.search("rust async runtime")
    except RateLimitError as e:
        print(f"Backoff exhausted; retry after {e.retry_after}s")
    except AuthError:
        print("Bad API key")
    except ServerError:
        print("Argand had a bad day")
    except NotImplementedAPIError:
        print("That method is reserved for v2")