LLM-solvable challenge-response authentication for AI agent APIs
Project description
agent-challenge
LLM-solvable challenge-response authentication for AI agent APIs.
Traditional CAPTCHAs block agents. Proof-of-work wastes compute. agent-challenge uses reasoning puzzles that any LLM can solve through thinking alone — no scripts, no hashing, no external tools.
Install
pip install agent-challenge
Server Side
from agentchallenge import AgentChallenge
# Create an instance with your secret
ac = AgentChallenge(secret="your-server-secret-key")
# Generate a challenge
challenge = ac.create()
# challenge.prompt = "Reverse the following string: NOHTYP"
# challenge.token = "eyJpZCI6ImNoXz..." (signed, stateless)
# Send challenge.prompt and challenge.token to the agent via your API
# When the agent responds with their answer:
result = ac.verify(token=challenge.token, answer="PYTHON")
if result.valid:
print("Agent verified! ✅")
else:
print(f"Failed: {result.error}")
Agent Side
The agent just reads the prompt and answers it. That's it.
Server: "Reverse the following string: NOHTYP"
Agent: "PYTHON"
Server: "What is 234 + 567?"
Agent: "801"
Server: "Decode this ROT13-encoded string: URYYB"
Agent: "HELLO"
No SDK needed on the agent side. No computation. Just reasoning.
Challenge Types
| Type | Example | Difficulty |
|---|---|---|
reverse_string |
Reverse "PYTHON" → "NOHTYP" | Easy |
simple_math |
234 + 567 = ? | Easy |
pattern |
2, 4, 8, 16, ? → 32 | Easy |
rot13 |
Decode "URYYB" → "HELLO" | Medium |
letter_position |
Sum of A=1,B=2.. in "CAT" → 24 | Medium |
extract_letters |
Every 2nd char of "HWEOLRLLOD" | Medium |
word_math |
7 + 8 as a word → "fifteen" | Hard |
Configuration
ac = AgentChallenge(
secret="your-secret", # Required (min 8 chars)
difficulty="easy", # "easy", "medium", or "hard"
ttl=300, # Challenge expiry in seconds
types=["reverse_string"], # Restrict to specific types
)
API
AgentChallenge(secret, difficulty, ttl, types)
Create an instance. The secret is used for HMAC-signing tokens.
ac.create(challenge_type=None) → Challenge
Generate a challenge. Returns:
challenge.id— unique challenge IDchallenge.prompt— text to send to the agentchallenge.token— signed token for stateless verificationchallenge.expires_at— expiry timestampchallenge.to_dict()— serialize for JSON API responses
ac.verify(token, answer) → VerifyResult
Verify an agent's answer. Returns:
result.valid— booleanresult.error— error message if invalidresult.challenge_type— which type was usedresult.elapsed_ms— verification time
Stateless Design
No database required. Challenge data is HMAC-signed into tokens:
- Server creates challenge → signs answer hash into token
- Agent receives prompt + token
- Agent sends back answer + token
- Server verifies HMAC signature, checks expiry, compares answer hash
Tokens can't be forged or tampered with. Each contains its own expiry.
JavaScript Port
A JavaScript/Node.js version is included at src/agentchallenge.js:
import { AgentChallenge } from './agentchallenge.js';
const ac = new AgentChallenge({ secret: 'your-secret' });
const challenge = ac.create();
const result = ac.verify(challenge.token, 'agent answer');
Testing
PYTHONPATH=src python3 run_tests.py
47 tests covering initialization, creation, verification, normalization, tokens, all 7 challenge types, integration flows, difficulty distribution, performance, and cross-secret isolation.
License
MIT
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_challenge-0.5.0.tar.gz.
File metadata
- Download URL: agent_challenge-0.5.0.tar.gz
- Upload date:
- Size: 24.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc2754016d5b901b4b5f190c55658d03f04d42e804e92132f334fc5db73a2e2f
|
|
| MD5 |
97457789e49b23704b6633d141f3711c
|
|
| BLAKE2b-256 |
21805743fafdf4e215378c7560de023276a2521081e1ee34ecb080fd5ef20e73
|
File details
Details for the file agent_challenge-0.5.0-py3-none-any.whl.
File metadata
- Download URL: agent_challenge-0.5.0-py3-none-any.whl
- Upload date:
- Size: 28.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0799c31c4976a296ec77d0163dc20c03b3856f179a918429a1e2ef483f3603d1
|
|
| MD5 |
5662da0d917d5eb458b2c1c4a088dfa8
|
|
| BLAKE2b-256 |
9609d7336242b1b7f08776189abd465213a747a93cccc958500497ff7969e3d7
|