Operations Guide

March 24, 2026 ยท View on GitHub

Environment Variables

Copy .env.example to .env and adjust as needed.

VariableDefaultPurpose
APP_NAMEAgoraAPI display name
APP_VERSION0.1.0API version string
ENVIRONMENTdevelopmentRuntime environment label
LOG_LEVELINFOPython logging verbosity
DATABASE_URLpostgresql+asyncpg://agora:password@localhost:5432/agoraPostgres DSN
DATABASE_ECHO_SQLfalseEnable SQLAlchemy SQL/params echo logging
MAX_REQUEST_BODY_BYTES1048576Reject requests larger than this many bytes (via Content-Length)
HEALTH_CHECK_INTERVAL3600Seconds between health-check cycles
RECOVERY_CHALLENGE_TTL_SECONDS900Recovery challenge TTL
OUTBOUND_HTTP_TIMEOUT_SECONDS10Timeout for outbound HTTP checks
REGISTRY_REFRESH_INTERVAL3600Seconds between registry.json refreshes
ADMIN_API_TOKENemptyRequired for admin/metrics endpoints
ALLOW_PRIVATE_NETWORK_TARGETSfalseDev/testing override for private host checks
ALLOW_UNRESOLVABLE_REGISTRATION_HOSTNAMESfalseDev/testing override to allow unresolved registration hostnames
RATE_LIMIT_BACKENDautoauto, memory, or redis
REDIS_URLemptyRedis URL for shared rate limiting
RATE_LIMIT_PREFIXagora:rate_limitRedis key namespace prefix
REGISTRATION_RATE_LIMIT_PER_IP10POST /api/v1/agents per-source-IP limit
REGISTRATION_RATE_LIMIT_PER_API_KEY10POST /api/v1/agents per-key secondary limit
REGISTRATION_RATE_LIMIT_GLOBAL200POST /api/v1/agents global limit
LIST_AGENTS_RATE_LIMIT_PER_IP100GET /api/v1/agents per-source-IP limit (always applied)
LIST_AGENTS_RATE_LIMIT_PER_API_KEY1000GET /api/v1/agents additional per-key secondary limit
LIST_AGENTS_RATE_LIMIT_GLOBAL5000GET /api/v1/agents global limit
ADMIN_RATE_LIMIT_PER_IP30Per-IP limit for admin token endpoints
ADMIN_RATE_LIMIT_GLOBAL300Global limit for admin token endpoints
METRICS_MAX_ENTRIES2048Max in-memory metric key cardinality
MONTHLY_BUDGET_CENTSemptyReserved budget setting

Background Jobs

  • Health checker:

    • Runs every HEALTH_CHECK_INTERVAL.
    • Checks only agents queried in the last 24 hours.
    • Probe order per agent: /.well-known/agent-card.json (primary), then agent.url, then origin /.
    • Also attempts ERC-8004 discovery at https://<agent-domain>/.well-known/agent-registration.json.
    • Updates health_status, last_health_check, last_healthy_at, protocol_version (from fetched card when available), econ_id (when auto-populated), erc8004_verified, and commitment_verified (when commitments_url + verified DID are present).
    • Does not delete stale agents.
  • Registry refresher:

    • Runs every REGISTRY_REFRESH_INTERVAL.
    • Rebuilds cached snapshot for /api/v1/registry.json.

Stale Semantics

  • Stale threshold: 7 days.
  • An agent is stale only when health_status == unhealthy and:
    • last_healthy_at is older than 7 days, or
    • never healthy and registered_at is older than 7 days.
  • unknown agents are never stale.
  • Staleness is advisory only in MVP; no auto-removal is performed.

Rate Limits

Window: 1 hour.

EndpointLimit
POST /api/v1/agents10/hour per source IP + 10/hour per API key + 200/hour global
GET /api/v1/agents100/hour per source IP + 1000/hour per API key + 5000/hour global
PUT /api/v1/agents/{id}20/hour per API key
DELETE /api/v1/agents/{id}10/hour per API key
GET /api/v1/registry.json10/hour per IP
POST /api/v1/agents/{id}/recovery/start5/hour per IP and 3/hour per agent
POST /api/v1/agents/{id}/recovery/complete10/hour per IP and 5/hour per agent
GET /api/v1/metrics + GET /api/v1/admin/stale-candidates30/hour per source IP + 300/hour global

Rate-limited responses return 429 and Retry-After.

For multi-instance deployments, configure RATE_LIMIT_BACKEND=redis + REDIS_URL.

SSRF and URL Safety

  • Registration/update reject private/internal/localhost targets by default.
  • Registration also rejects unresolved hostnames by default.
  • Recovery and health outbound probes enforce safe public targets by default and pin DNS resolution for each request to prevent rebinding between check and connect.
  • For isolated dev environments, set ALLOW_PRIVATE_NETWORK_TARGETS=true.
  • To allow unresolved hostnames in non-production experiments, set ALLOW_UNRESOLVABLE_REGISTRATION_HOSTNAMES=true.

Observability

  • Request logs include method, path, status, and latency.
  • Recovery abuse logs include source IP, agent ID, and outcome.
  • Metrics endpoint: GET /api/v1/metrics (requires X-Admin-Token and uses bounded route-template counters).

Registry Export Behavior

GET /api/v1/registry.json returns cached snapshot with:

  • Cache-Control: public, max-age=300, stale-while-revalidate=120
  • ETag
  • Last-Modified