Add Maritime/Logistics support assistant with safety/eval layer #1
@@ -14,18 +14,42 @@ trade-offs documented in [`docs/SAFETY_WRITEUP.md`](docs/SAFETY_WRITEUP.md).
|
||||
|
||||
## Architecture
|
||||
|
||||
Three narrow agents behind a deterministic supervisor -- the supervisor is
|
||||
plain Rust control flow, not another LLM call, so *what's allowed through*
|
||||
is never itself something the model can be talked out of:
|
||||
Three narrow agents behind a deterministic supervisor:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Q["Customer Query"] --> PRE{{"Guardrail: Pre-check<br/>regex injection scan"}}
|
||||
PRE -- allow --> RET["Retrieval Agent<br/>vector search + LLM relevance filter"]
|
||||
RET <--> QD[("Qdrant Vector Store<br/>chunked KB docs")]
|
||||
RET --> DRAFT["Drafting Agent<br/>tool-calling loop"]
|
||||
DRAFT -- lookup_shipment --> SHIP[("Shipment Repository")]
|
||||
DRAFT -- escalate_to_human --> ESC[("Escalation Desk")]
|
||||
DRAFT --> POL["Policy-Compliance Agent"]
|
||||
POL --> DOCS[("acceptable_use.md +<br/>tracking_policy.md")]
|
||||
POL --> POST{{"Guardrail: Post-check<br/>PII/injection scan + policy verdict"}}
|
||||
POST -- allow / escalate --> FINAL["Final Answer + Citations -> Customer"]
|
||||
PRE -- block --> FINAL
|
||||
PRE -.-> AUDIT[("Audit Log<br/>JSONL, append-only")]
|
||||
POST -.-> AUDIT
|
||||
|
||||
classDef agent fill:#eef2ff,stroke:#4f46e5,color:#312e81
|
||||
classDef guardrail fill:#fff7ed,stroke:#ea580c,color:#7c2d12
|
||||
classDef store fill:#f1f5f9,stroke:#64748b,color:#334155
|
||||
classDef audit fill:#f0fdf4,stroke:#16a34a,color:#14532d
|
||||
classDef io fill:#f8fafc,stroke:#334155,color:#0f172a
|
||||
|
||||
class RET,DRAFT,POL agent
|
||||
class PRE,POST guardrail
|
||||
class QD,SHIP,ESC,DOCS store
|
||||
class AUDIT audit
|
||||
class Q,FINAL io
|
||||
```
|
||||
query -> guardrail.pre_check (rule-based, blocks prompt injection)
|
||||
-> RetrievalAgent (Qdrant vector search -> LLM relevance filter)
|
||||
-> DraftingAgent (tool-calling: lookup_shipment, escalate_to_human)
|
||||
-> PolicyAgent (LLM compliance check against acceptable_use.md)
|
||||
-> guardrail.post_check (rule-based PII/injection scan + policy verdict)
|
||||
-> answer, audit record
|
||||
```
|
||||
|
||||
The supervisor (`src/agents/supervisor.rs`) is what runs this graph -- plain
|
||||
Rust control flow, not another LLM call, so *what's allowed through* is
|
||||
never itself something the model can be talked out of. The dashed edges are
|
||||
the audit trail: every guardrail decision is logged, not just the blocked
|
||||
ones.
|
||||
|
||||
Every LLM call asks for a schema-validated structured output (via a forced
|
||||
tool-call, see `src/llm/client.rs`) rather than free text -- there's no
|
||||
|
||||
Reference in New Issue
Block a user