Skip to content
AGNT

Backend · agnt-backend

Backend overview.

FastAPI async Python service. PostgreSQL 16 with pgvector, Redis 7, APScheduler, Anthropic Claude, Stripe, and the ClawPulse A2A gateway.

What it is

The AGNT backend is a FastAPI application written in Python 3.13. It owns everything that's not a view:

  • Consumer agents on Telegram, WhatsApp, and Instagram webhooks
  • Venue business agents exchanging A2A bookings via ClawPulse
  • B2B onboarding and venue claim flows
  • Stripe subscriptions, metered billing, and fee collection
  • 16 LLM-powered tools dispatched by an Anthropic Messages loop
  • 40+ background jobs via APScheduler with Redis-backed leader election
  • An MCP server at /mcp/sse for external developer agents

Tech stack

LayerChoiceNotes
RuntimePython 3.13, uvicornAsync everywhere. No sync IO in request paths.
FrameworkFastAPIPydantic validation on every boundary.
DBPostgreSQL 16 + pgvectorSQLAlchemy 2.0 async ORM, Alembic migrations.
Cache / queueRedis 7Sessions, rate limiting, distributed locks, send queue.
LLMAnthropic Claude (Sonnet, Haiku)Ollama fallback for offline dev.
PaymentsStripeSubscriptions, booking fees, B2B checkout.
MessagingTelegram, WhatsApp Cloud (360dialog), InstagramWebhook-in, send queue out.
A2AClawPulse gatewayHMAC-SHA256 signed envelopes, circuit breakers, inbox poll.

Directory tour

The app/ package is organised by role, not by feature. Request plumbing lives in routers/, business logic in core/, database concerns in db/, background jobs split between scheduler.py and cron/.

app/core/

Where the work actually happens. Every file is single-purpose:

  • msg_router.py— main text + image dispatcher for all channels
  • llm_gateway.py— Anthropic / Ollama abstraction with token budgets and a per-user semaphore
  • soul_loader.py— system prompt builder (memory, patterns, weather, transport)
  • session_store.py— Redis chat history, Fernet encrypted, platform-scoped
  • tool_executor.py— 16 tools registered, 5s timeout, safe input strip
  • clawpulse.py— A2A client with global and per-venue circuit breakers
  • a2a_booking.py— outbound booking envelopes and listener spawn
  • a2a_response_listener.py— consumer inbox polling for venue responses
  • a2a_enums.pyEnvelopeStatus and BookingStatus state machines
  • agent_registry.py— consumer / venue / platform agent DNA registration
  • credit_manager.py— balance writes with SELECT FOR UPDATE
  • commerce.py— fee collection, Stripe idempotency, ledger
  • scheduler.py— 40+ APScheduler jobs with Redis leader election
  • venue_inbox_loop.py— per-venue poll loop manager
  • background_runtime.py— lifespan hooks for long-running tasks

app/routers/

HTTP routers mounted in main.py. See Routers for the full list.

app/db/

models.py is 901 lines and holds 45 SQLAlchemy models. session.py configures the async engine (pool_size=100, max_overflow=50). See Database & models.

app/features/

Feature sub-packages. Currently hosts scan/ (the business scan engine). Features that outgrow a single module graduate here.

app/middleware/

Only one middleware right now: agent_auth.py, which verifies the Bearer token on external agent calls and resolves it to an ApiKey row.

app/mcp/

agnt_network_server.py implements a Model Context Protocol server at /mcp/sse so external developer agents (Claude Code, Codex, Gemini CLI, etc.) can consume the venue network directly.

app/cron/

Nightly and weekly jobs that are too big for the main scheduler file: dreaming, graph building, wiki reconciliation, FAQ compilation.

Entry point

app/main.py constructs the FastAPI app, mounts every router, wires the lifespan hooks (start ClawPulse client, start scheduler, start background runtime), and configures CORS and middleware. Start it with:

bash
uvicorn app.main:app --reload --port 8000

Critical safety rules

Four invariants the backend enforces without exception. Breaking any of them is a production incident:

  1. Never book Lalamove delivery without explicit user confirmation.
  2. Never modify credit balance without SELECT FOR UPDATE.
  3. Never trust X-User-Idheaders — always resolve identity from the JWT Bearer token.
  4. Never skip Stripe idempotency keys on payment operations.

Related