Guide

Agent programmatic access (Zero Human Auth)

Your bot approves a site login headlessly: fetch PoW, solve it, call approve — no browser, no site_token, no SSE on your side.

You are building the agent worker. No site_token, no SSE, no passport verification here.

Audience: Agent worker developersHuman role: No human in runtime flow

When to use this guide

  • A site integrator sent you login_request_id out-of-band.
  • You run Claude/Cursor/custom automation that must confirm login via API.
  • Autonomous scripts that mine PoW and approve without human input.

Before you start

  1. agent_token (at_…) in LIME_AGENT_TOKEN — from portal when the agent was created.
  2. login_request_id UUID from the site (webhook, queue, API callback).
  3. lime-agents-sdk or your own SHA-256 PoW loop.

Who does what

RoleResponsibility
You — agent workerGET challenge → PoW → approve with X-Agent-Token.
Site backend (other team)Create + SSE + JWT verify — not your code.

Your code (agent worker)

Only what you implement in this role. No PoW, SSE, or token logic from the partner side — that is in a separate guide.

  1. Agent worker

    Accept login_request_id from the site integrator

    Your input is only the UUID the site created. You never call POST /modules/agent-login/requests and you never use X-Site-Token.

    Tip: Stale IDs expire — always use the fresh ID from the current login attempt.

  2. Agent worker

    Fetch PoW challenge (public endpoint)

    GET /api/v1/auth/requests/{login_request_id} with no auth headers. Response includes pow_challenge and pow_difficulty — absent from the site's create response on purpose.

  3. Agent worker

    Solve PoW

    Compute pow_nonce so SHA-256(challenge+nonce) meets difficulty. This is CPU work your worker does before approve.

    Your worker — solve PoW
    # Solve PoW: nonce where SHA-256(challenge + nonce) < 2**(256 - difficulty)
    import hashlib, itertools, json, urllib.request
    
    url = "https://lime.pics/api/v1/auth/requests/{request_id}"
    data = json.load(urllib.request.urlopen(url))["data"]
    challenge, difficulty = data["pow_challenge"], data["pow_difficulty"]  # difficulty: 15
    
    limit = 2 ** (256 - difficulty)
    pow_nonce = next(
        str(n) for n in itertools.count()
        if int(hashlib.sha256(f"{challenge}{n}".encode()).hexdigest(), 16) < limit
    )
    # difficulty 15 ≈ a few seconds of CPU; send pow_nonce in the approve body
  4. Agent worker

    Approve with agent_token

    POST approve with header X-Agent-Token and body {"pow_nonce":"..."}. Stop here — the site handles SSE and session creation.

    Your worker — approve login
    # Agent runtime — solve PoW (GET /auth/requests/{id}), then approve
    curl -sS -X POST \
      "https://lime.pics/api/v1/modules/agent-login/requests/{request_id}/approve" \
      -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      -H "X-Agent-Token: {your_agent_token}" \
      -d '{"pow_nonce":"12345678"}'

What the site already did (not your code)

Before your worker runs, the site backend created the login request and is holding SSE open. You never implement those endpoints in the agent process.

  • Site called POST /modules/agent-login/requests with X-Site-Token and got login_request_id.
  • Site passed that UUID to you and listens on GET /modules/agent-login/events.
  • After your approve succeeds, they verify agent_passport_jwt locally — you do not receive the JWT.

What success looks like

POST approve returns APPROVED. The site sees the passport on its SSE stream — you do not handle agent_passport_jwt.

Same identity the site may have linked earlier

The site may have bound this agent_id to a user account via Agent Binding. Your approve only proves identity — they map claims.sub to their user.

  • Site maps agent_id → user

    After you approve, the site verifies the passport on SSE. If they use Agent Binding, claims.sub should match the agent_id stored at bind time.

  • MCP uses the same agent_id

    This worker can also fetch MCP JWTs. RS operators trust claims.sub in MCP tokens — the same UUID you just approved for site login.

Full runnable example

Agent-only Python (lime-agents-sdk)
# pip install lime-agents-sdk
# https://github.com/Mawyxx/lime-agents-sdk
# Full Python API: https://lime-agents-sdk.readthedocs.io/
import asyncio
from lime_agents import LimeAgent

async def main() -> None:
    agent = LimeAgent()  # LIME_AGENT_TOKEN
    result = await agent.login("{login_request_id}")
    print(result.status)

asyncio.run(main())

Related endpoints

Agent programmatic access (Zero Human Auth) · LIME