Conversational SQL Agent with Sandboxed Execution & Deep Agents Middleware
Arthur Edmond Β· LLM Engineer @ Swapn A production-grade SQL agent powered by LangChain Deep Agents, executing queries in an isolated Modal sandbox with 7-layer middleware defense
Posez des questions en langage naturel sur votre base de donnees β l'agent genere le SQL, l'execute dans un sandbox PostgreSQL isole (Modal), et repond en francais. 7 middleware (SQL guard, tool retry, context editing, model fallback...) assurent securite et resilience. Frontend avec streaming SSE, tool panels interactifs, et export CSV/JSON.
graph LR
U[Utilisateur] --> F["Frontend<br/>"]
U --> C[CLI Rich]
F --> S[FastAPI :8080]
C --> A[Deep Agent<br/>LangGraph]
S --> A
subgraph mw [" 7-Layer Middleware Stack "]
direction TB
SG["π‘οΈ SQL Guard"]
TR["π Tool Retry"]
TL["π« Tool Call Limit"]
LOG["π Tool Logger"]
CE["βοΈ Context Editing"]
MR["π Model Retry"]
MF["π Model Fallback"]
end
A --> mw
A --> T1["execute_sql"]
A --> T2["get_database_schema"]
A --> T3["export_csv"]
A --> T4["export_json"]
T1 & T2 & T3 --> PG_GW[PG Gateway]
PG_GW --> SB[Modal Sandbox]
SB --> PG[(PostgreSQL 15)]
A -.-> LS[LangSmith]
A -.-> ST[InMemoryStore]
A -.-> CP[MemorySaver]
Generation et execution de SQL a partir de questions en langage naturel. Support multi-tables, JOINs, CTEs, agregations.
PostgreSQL 15 dans un conteneur Modal ephemere. Utilisateur read-only, timeout 10s, aucun acces reseau externe.
Tools dedies pour l'export. L'agent genere des fichiers telechargeable avec liens directs dans le chat.
Tokens streames un par un. Tool panels interactifs avec spinner β check, input SQL visible, boutons Copy/CSV/JSON.
SQL guard, tool retry, tool call limit, logging, context editing, model retry, model fallback β chaque requete traverse 7 couches.
MemorySaver (checkpointer) + InMemoryStore (StoreBackend). Summarization automatique built-in Deep Agents.
Traces completes de chaque appel agent, tool, et middleware. Optionnel, activable via .env.
L'ordre d'execution est important β les middleware tools s'executent avant les middleware modele.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MIDDLEWARE EXECUTION ORDER β
β β
Tool calls: β ββββββββββββ βββββββββββββ βββββββββββββ ββββββββ β
β β SQL Guard ββ β Tool Retryββ β Call Limitββ β Log β β
β β block DDL β β 2x backoffβ β 20/run β βtimingβ β
β ββββββββββββ βββββββββββββ βββββββββββββ ββββββββ β
β β
Context: β ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Context Editing β clear tool results > 80k β β
β β keep=3 most recent, placeholder: [cleared] β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
Model calls: β βββββββββββββββ ββββββββββββββββββ β
β β Model Retry β β β Model Fallback β β
β β 3x backoff β β GPT β Claude β β
β βββββββββββββββ ββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| # | Middleware | Source | Role | Configuration |
|---|---|---|---|---|
| 1 | SQLGuardMiddleware |
Custom | Bloque les requetes destructives (DROP, DELETE, INSERT, ALTER...) | Whitelist: SELECT, WITH, EXPLAIN |
| 2 | ToolRetryMiddleware |
Built-in | Retry automatique des tools en echec (timeout sandbox, erreur reseau) | 2 retries, backoff 2x, jitter |
| 3 | ToolCallLimitMiddleware |
Built-in | Limite les appels tools par run β empeche les boucles infinies | 20 calls/run, soft exit |
| 4 | LogToolCallsMiddleware |
Custom | Log chaque tool call avec timing (ms), taille input/output | Sync + async |
| 5 | ContextEditingMiddleware |
Built-in | Efface les anciens resultats tools quand le contexte depasse le seuil | 80k tokens, garde 3 derniers |
| 6 | ModelRetryMiddleware |
Built-in | Retry automatique des appels LLM (rate limit, API timeout, 5xx) | 3 retries, backoff 2x, jitter |
| 7 | ModelFallbackMiddleware |
Built-in | Bascule sur un modele de secours si le principal echoue | Optionnel (config .env) |
| Composant | Technologie |
|---|---|
| Agent Framework | LangChain Deep Agents + LangGraph v2 |
| LLM | Claude Sonnet 4 / GPT-5-mini (+ fallback configurable) |
| Middleware | langchain.agents.middleware (5 built-in + 2 custom) |
| Sandbox | Modal (conteneur isole, PG15, read-only) |
| Base de donnees | PostgreSQL 15 |
| API Server | FastAPI + SSE streaming |
| Frontend | HTML/JS vanilla |
| CLI | Rich (panels, markdown, spinners) |
| Validation | Pydantic v2 (strict mode) |
| Tracing | LangSmith |
| Store | InMemoryStore + StoreBackend (Deep Agents) |
- Python 3.11+
- Compte Modal (gratuit pour commencer)
- Cle API Anthropic ou OpenAI
- (Optionnel) Cle API LangSmith
# Clone
git clone https://github.com/your-org/neo-deep-agent-lab.git
cd neo-deep-agent-lab
# Setup
python -m venv .venv && source .venv/bin/activate
make install
# Config
cp .env.example .env
# Remplir les cles API# ββ LLM principal ββ
LLM_PROVIDER=openai
LLM_MODEL=gpt-5-mini-2025-08-07
OPENAI_API_KEY=sk-...
# ββ LLM fallback (optionnel) ββ
LLM_FALLBACK_PROVIDER=anthropic
LLM_FALLBACK_MODEL=claude-sonnet-4-20250514
ANTHROPIC_API_KEY=sk-ant-...
# ββ Middleware ββ
CONTEXT_EDITING_TRIGGER=80000 # tokens seuil pour nettoyer le contexte
TOOL_CALL_LIMIT_PER_RUN=20 # max tool calls par run
# ββ Modal ββ
MODAL_TOKEN_ID=...
MODAL_TOKEN_SECRET=...
# ββ LangSmith (optionnel) ββ
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=lsv2_...
LANGCHAIN_PROJECT=neo-deep-agent-labmake serve
# β http://localhost:8080| Feature | Description |
|---|---|
| Streaming | Tokens affiches un par un en temps reel |
| Tool panels | Collapsibles avec spinner β check, input SQL, output table |
| Actions | Boutons Copy / CSV / JSON sur chaque resultat |
| Download | Liens de telechargement pour les exports agent |
| Design | (Fira Code, DM Mono, dark #111, borders 0.25px) |
make cli| Commande | Action |
|---|---|
reset |
Reinitialiser la conversation |
clear |
Effacer l'ecran |
quit |
Quitter |
make dump # Export PG depuis Docker β data/neo_dump.sqlsrc/
β
βββ π€ agent/
β βββ factory.py # Factory Deep Agent + 7-middleware stack
β βββ prompts.py # System prompt SQL (francais, anti-echo)
β
βββ π» cli/
β βββ chat.py # Chat terminal Rich (sync streaming)
β
βββ βοΈ config.py # Settings Pydantic (env vars, middleware config)
βββ π constants.py # Enums (LLMProvider, SSEEventType, SQL keywords)
β
βββ π‘οΈ middleware/
β βββ logging_mw.py # AgentMiddleware β sync+async logging avec timing
β βββ sql_guard.py # AgentMiddleware β bloque requetes destructives
β
βββ π sandbox/
β βββ app.py # Lifecycle sandbox Modal (singleton, lazy init)
β βββ image.py # Image Modal (Debian + PG15 + dump restore)
β βββ init_pg.sh # Init PostgreSQL + read-only user
β βββ pg.py # Gateway PG β QueryResult(stdout, stderr, exit_code)
β
βββ π server/
β βββ app.py # FastAPI (SSE, /history, /reset, /download)
β βββ static/
β βββ index.html # Frontend (Bittensor design language)
β
βββ π‘ streaming/
β βββ events.py # SSE event dataclasses (text-delta, tool-call-*)
β βββ sse_encoder.py # LangGraph v2 β SSE (tool results exclus du texte)
β
βββ π§ tools/
βββ schemas.py # Pydantic v2 strict schemas (ExecuteSQLInput, etc.)
βββ schema_tool.py # @tool β introspection schema (tables, colonnes)
βββ sql_tool.py # @tool β execution SQL via PG gateway β markdown
βββ export_tool.py # @tool β export CSV/JSON avec download link
| Couche | Protection | Implementation |
|---|---|---|
| Validation | Schemas Pydantic stricts sur les inputs tools | model_config = {"strict": True} |
| SQL Guard | Bloque DROP, DELETE, INSERT, UPDATE, ALTER, TRUNCATE, CREATE | AgentMiddleware custom |
| PostgreSQL | default_transaction_read_only = ON |
init_pg.sh |
| Timeout | Statement timeout 10s cote PostgreSQL | psql -v statement_timeout=10000 |
| Tool Limit | 20 tool calls max par run | ToolCallLimitMiddleware built-in |
| Context | Nettoyage auto des anciens resultats (80k tokens) | ContextEditingMiddleware built-in |
| Retry | Backoff exponentiel (pas de spam API/sandbox) | ToolRetryMiddleware + ModelRetryMiddleware |
| Sandbox | Conteneur Modal isole, detruit apres session | Modal ephemeral sandbox |
| Reseau | Aucun acces externe depuis le sandbox | Modal network isolation |
| Fallback | Bascule auto sur modele secondaire si le principal fail | ModelFallbackMiddleware built-in |
make test # 19 tests (tools, middleware, schemas)
make lint # Ruff linter
make format # Ruff formatterArthur Edmond Β· Swapn Built with LangChain Deep Agents, Modal, and an obsession for clean middleware stacks