Your bot approves a site login headlessly: fetch PoW, solve it, call approve — no browser, no site_token, no SSE on your side.
| Role | Responsibility |
|---|---|
| You — agent worker | GET challenge → PoW → approve with X-Agent-Token. |
| Site backend (other team) | Create + SSE + JWT verify — not your code. |
Only what you implement in this role. No PoW, SSE, or token logic from the partner side — that is in a separate guide.
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.
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.
Compute pow_nonce so SHA-256(challenge+nonce) meets difficulty. This is CPU work your worker does before approve.
# 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 bodyPOST approve with header X-Agent-Token and body {"pow_nonce":"..."}. Stop here — the site handles SSE and session creation.
# 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"}'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.
POST approve returns APPROVED. The site sees the passport on its SSE stream — you do not handle agent_passport_jwt.
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.
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.
This worker can also fetch MCP JWTs. RS operators trust claims.sub in MCP tokens — the same UUID you just approved for site login.
# 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())