Python client for the Agent Disco API — grade any public URL for AI-agent discoverability.
Project description
agentdisco — Python client for Agent Disco
Grade any public URL for AI-agent discoverability. Thin Python wrapper over the REST API at https://agentdisco.io/api/v1.
Install
pip install agentdisco
Requires Python 3.9+.
Quick start
Submit a scan (anonymous, 10 scans/day/IP)
from agentdisco import AgentDisco
with AgentDisco() as client:
scan = client.submit_scan("https://example.com")
print(scan.id, scan.status)
Poll until complete
import time
with AgentDisco() as client:
scan = client.submit_scan("https://example.com")
while scan.status not in {"completed", "failed"}:
time.sleep(5)
scan = client.get_scan(scan.id)
print(f"grade: {scan.grade} ({scan.score}/100)")
Mint a key (raises your quota to 100 scans/day)
from agentdisco import AgentDisco
# Unauthenticated mint — no prior token needed, rate-limited at
# 5 keys/hour/IP. Token is shown ONCE; store it.
key = AgentDisco().mint_key()
print(key.token) # ak_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
authed = AgentDisco(token=key.token)
authed.submit_scan("https://your-site.example")
Get summary for a previously-scanned host
with AgentDisco() as client:
site = client.get_website("example.com")
print(site.latest_grade, site.latest_score, site.scan_count)
Scan history + re-scan
with AgentDisco() as client:
# Paginated history, most-recent first (per_page capped at 50).
for scan in client.get_scans("example.com", per_page=20):
print(scan.grade, scan.score)
# Queue a fresh scan of a known host (counts against your scan quota).
fresh = client.rescan("example.com")
print(fresh.id, fresh.status)
Async client
AsyncAgentDisco mirrors AgentDisco method-for-method over asyncio:
import asyncio
from agentdisco import AsyncAgentDisco
async def main():
async with AsyncAgentDisco(token="ak_...") as client:
scan = await client.submit_scan("https://example.com")
history = await client.get_scans("example.com")
print(scan.id, len(history))
asyncio.run(main())
Same arguments, return types, and exceptions as the sync client —
including await AsyncAgentDisco.from_colony_token(...).
Sign in with the Colony (agents)
Autonomous agents on The Colony can authenticate
without a browser, and — since v0.4.0 — without ever sending their Colony
credential to Agent Disco. The SDK runs the OAuth 2.0 Token Exchange
(RFC 8693) at the Colony, naming Agent Disco as the audience, and
presents only the short-lived, audience-scoped id_token it mints:
from agentdisco import AgentDisco
# One-liner: sign in with your Colony access token and get an authed client.
# The raw token goes only to thecolony.ai; Agent Disco sees just the id_token.
client = AgentDisco.from_colony_token(my_colony_token)
client.submit_scan("https://your-site.example") # authenticated tier (500/day)
# Or keep the minted key's plaintext to reuse across processes:
key = AgentDisco().exchange_colony_token(my_colony_token)
print(key.token, key.rate_limit_tier) # ak_… authenticated
# Already ran the exchange yourself? Present the id_token directly:
key = AgentDisco().present_colony_id_token(my_id_token)
Agent-only: a human Colony subject is rejected with UnauthorizedError,
as is any token not minted for Agent Disco (wrong audience, raw Colony
tokens included — the server refuses them outright since Agent Disco's
2026-07-20 release; SDK ≤0.3.x no longer works for Colony sign-in).
Higher rate limits
Authenticated-tier keys (500 scans/day/key) need a signed-in account, or a Colony agent login (above). Sign up at https://agentdisco.io/register, then mint via the web form at https://agentdisco.io/developers.
| Tier | Rate limit | How to get |
|---|---|---|
| Anonymous (no key) | 10 scans / day / IP | default |
| Anonymous key | 100 scans / day / key | mint_key() above |
| Authenticated key | 500 scans / day / key | sign in (/developers) or from_colony_token() |
Error handling
from agentdisco import (
AgentDisco,
InvalidUrlError,
NotFoundError,
RateLimitedError,
)
try:
scan = AgentDisco().submit_scan("https://example.com")
except InvalidUrlError as e:
print(f"URL rejected: {e}")
except RateLimitedError as e:
print(f"quota exceeded; retry in {e.retry_after_seconds}s")
except NotFoundError as e:
print(f"not found: {e}")
All SDK-raised exceptions inherit from AgentDiscoError, so a single
broad catch works too:
from agentdisco import AgentDiscoError
try:
...
except AgentDiscoError as e:
log.warning("agentdisco failure: %s", e)
Network-layer failures (connection timeout, DNS) leak through as raw
httpx.HTTPError — they're platform issues, not API errors.
Custom base URL
For self-hosted deployments or local testing:
AgentDisco(base_url="http://localhost:1977")
Links
- API docs: https://agentdisco.io/api/docs
- Check catalogue: https://agentdisco.io/checks
- Live scanner: https://agentdisco.io
Licence
MIT. See LICENSE. The scanner itself is operated by
Starsol Ltd (England, company 06002018); only this client library
is open-source. Issues + pull requests welcome.
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 agentdisco-0.4.0.tar.gz.
File metadata
- Download URL: agentdisco-0.4.0.tar.gz
- Upload date:
- Size: 16.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9fc84e123c6c472cb230af2fc68051fd584540fdb4e7adb75ca4ff7fc2034078
|
|
| MD5 |
f0e2325630fcd02fb381210f7abca3f6
|
|
| BLAKE2b-256 |
a29461dbca2f6f8ee0daaa2a8cbc33fee8c211aa9debdfd01a694e08b0d7bdcc
|
File details
Details for the file agentdisco-0.4.0-py3-none-any.whl.
File metadata
- Download URL: agentdisco-0.4.0-py3-none-any.whl
- Upload date:
- Size: 15.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f56071f0fefb89ebdbc3ef95af66b825f63b474de6f3ee58867b8764fd3d4f5e
|
|
| MD5 |
994eacddcd174b1378da3ff3a07b42ea
|
|
| BLAKE2b-256 |
5a2cdba8135e58c99ed51b7926b10839ab6d56872eebc75a502505feffa18707
|