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/ssefor external developer agents
Tech stack
| Layer | Choice | Notes |
|---|---|---|
| Runtime | Python 3.13, uvicorn | Async everywhere. No sync IO in request paths. |
| Framework | FastAPI | Pydantic validation on every boundary. |
| DB | PostgreSQL 16 + pgvector | SQLAlchemy 2.0 async ORM, Alembic migrations. |
| Cache / queue | Redis 7 | Sessions, rate limiting, distributed locks, send queue. |
| LLM | Anthropic Claude (Sonnet, Haiku) | Ollama fallback for offline dev. |
| Payments | Stripe | Subscriptions, booking fees, B2B checkout. |
| Messaging | Telegram, WhatsApp Cloud (360dialog), Instagram | Webhook-in, send queue out. |
| A2A | ClawPulse gateway | HMAC-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 channelsllm_gateway.py— Anthropic / Ollama abstraction with token budgets and a per-user semaphoresoul_loader.py— system prompt builder (memory, patterns, weather, transport)session_store.py— Redis chat history, Fernet encrypted, platform-scopedtool_executor.py— 16 tools registered, 5s timeout, safe input stripclawpulse.py— A2A client with global and per-venue circuit breakersa2a_booking.py— outbound booking envelopes and listener spawna2a_response_listener.py— consumer inbox polling for venue responsesa2a_enums.py—EnvelopeStatusandBookingStatusstate machinesagent_registry.py— consumer / venue / platform agent DNA registrationcredit_manager.py— balance writes with SELECT FOR UPDATEcommerce.py— fee collection, Stripe idempotency, ledgerscheduler.py— 40+ APScheduler jobs with Redis leader electionvenue_inbox_loop.py— per-venue poll loop managerbackground_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:
uvicorn app.main:app --reload --port 8000Critical safety rules
Four invariants the backend enforces without exception. Breaking any of them is a production incident:
- Never book Lalamove delivery without explicit user confirmation.
- Never modify credit balance without
SELECT FOR UPDATE. - Never trust
X-User-Idheaders — always resolve identity from the JWT Bearer token. - Never skip Stripe idempotency keys on payment operations.