API reference
The PyGuard backend is a FastAPI application that exposes a small HTTP surface. Most interactions happen through Slack, which calls into the same process_chat_message function internally, so the HTTP API is there for programmatic access and for the (existing) web chat UI.
- Base URL (local):
http://127.0.0.1:8000 - Authentication: none in beta. Run the backend on localhost or behind your own VPN.
POST /api/chat
The main conversational endpoint. Runs the full Memory Agent plus fraud or follow-up pipeline and returns a single ChatResponse.
Request body (ChatRequest)
{
"message": "Generate a fraud intelligence report.",
"user": "alice@example.com",
"source": "chat",
"subject": "monthly-review"
}
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| message | string | yes | The user's message. |
| user | string | no | Identifier for the sender. Defaults to "default". |
| source | string | no | Channel identifier for the message history. Defaults to "chat". |
| subject | string or null | no | Optional thread-like grouping; used by the message history helpers. |
The HTTP endpoint does not currently take slack_thread_ts or slack_channel_id. Those are only injected by the Slack service and are used for the in-thread follow-up routing.
Response body (ChatResponse)
{
"status": "success",
"type": "fraud_analysis",
"response": "... short narrative summary ...",
"rule_created": null,
"fraud_analysis": {
"verification_passed": true,
"attempts": 1
},
"pdf_path": "/abs/path/to/backend/reports/fraud_report_<ts>/fraud_report_<ts>.pdf",
"report_id": 12,
"report_version": 1,
"error": null
}
| Field | Type | Notes |
| --- | --- | --- |
| status | "success" | "error" | Top-level result indicator. |
| type | string | One of action_execution, rule_creation, both, user_management, fraud_analysis, report_qa, report_edit, conversational, error. |
| response | string | The assistant's final user-facing text. |
| rule_created | object or null | Populated when the Memory Agent created a rule. |
| fraud_analysis | object or null | Verification metadata for fraud runs. |
| pdf_path | string or null | Absolute path to the generated or updated PDF when applicable. |
| report_id | number or null | Matching row id in fraud_reports when this response is tied to a persisted report. |
| report_version | number or null | Current version of the bundle (bumps on every successful edit). |
| error | string or null | Error text when status == "error". |
Example
curl -s http://127.0.0.1:8000/api/chat \
-H "Content-Type: application/json" \
-d '{"message":"Generate a fraud intelligence report","user":"alice"}' \
| jq
GET /api/history
Returns recent rows from the messages table (all sources combined). Useful for debugging the conversation log.
curl -s "http://127.0.0.1:8000/api/history?limit=10" | jq
Query parameters
| Parameter | Default | Notes |
| --- | --- | --- |
| limit | 50 | Maximum number of rows to return. |
Response
{
"messages": [
{
"id": 42,
"user": "U0ALE1GP7DF",
"source": "slack",
"input": "Generate a fraud intelligence report.",
"subject": null,
"created_at": "2026-04-20T17:41:03.118Z"
}
]
}
GET /api/rules
Returns every row from the rules table. Useful for seeing what preferences the Memory Agent has persisted for future turns.
curl -s "http://127.0.0.1:8000/api/rules" | jq
GET /api/health
Liveness check.
curl -s "http://127.0.0.1:8000/api/health"
# {"status":"ok"}
Behind the scenes
The Slack service in backend/slack/service.py calls process_chat_message directly with two extra kwargs (slack_thread_ts, slack_channel_id) that are not exposed through the HTTP route. This is how the in-thread Q&A and edit routing works. If you build a new surface (WhatsApp, a web UI, anything else), the pattern is the same: call process_chat_message directly with whatever thread or conversation identifier makes sense for your surface.
Deployment
The backend is a standard uvicorn-served FastAPI app. You can deploy it anywhere you can install Python 3.11, tectonic, and a persistent file system for the reports/ bundles. Because PyGuard writes to disk per request and persists SQLite state, a single long-lived process is the simplest topology. A container image with tectonic preinstalled is recommended for production-style deployments.
See /setup for deploying the marketing site to Vercel; the backend itself is not currently deployed there.